# Salesforce / CM / BI 最终结论版

Date: `2026-07-07`

## 一句话结论

这次研究的核心结论不是
`CM 做不到这些事`
，
而是：

- Salesforce 现网仍在核心业务对象上自动维护大量报表语义
- CM 平台和 PingCAP 本地 pack 已经承载了其中相当一部分
- 当前最主要的差异仍然是
  `pack parity 没补齐`
  和
  `activation-state mismatch`
- 真正更像平台边界的，主要还是还活在 live Salesforce
  `Apex trigger`
  里的逻辑

## 1. Salesforce 会做什么

对当前最重要的 CRM / BI 对象，Salesforce 现网还在自动维护：

- auto-number
- formula / rollup / derived 字段
- validation rules
- record-triggered / scheduled Flows
- Apex triggers

从报表视角看，最重要的 5 组语义是：

1. `Lead Funnel / Qualification`
   Salesforce 维护 `LeadLifecycleStage`、`LeadStatus`、`lead_mql_timestamp`、
   `lead_iqm_timestamp`、lead-account / tenant 关联。
2. `Pipeline / Forecast / Opportunity Quality`
   Salesforce 维护 `forecast_category`、`forecast_type`、`stage_name`、
   `stage_duration`、`arr_amount_usd`、`accurate_acv_amount`、服务起止、
   close/launch helper 等机会语义。
3. `Campaign Attribution / ICP Analysis`
   Salesforce 维护 `CampaignMember.first_responded_date`、response/status、
   first/last touch、以及和机会侧 ARR/ACV/stage 的归因连接。
4. `Order / ARR / RevRec / Collections`
   Salesforce 维护 order-to-org carry-over、PLG pool、contract gating、
   revenue / invoice / collection / service-window / accumulated-revenue 语义。
5. `Account / Tenant Linkage / Customer Identity`
   Salesforce 维护 `AccountID`、`Region`、`Segmentation`、`TenantStatus`、
   `TiDBCloudPortalID`、account-to-tenant bridge、
   `accumulate_revenue_to_org_tenant_id`。

所以关键点不是
`记录能不能创建出来`
，
而是
`记录创建后有没有被补成报表真正依赖的业务语义`
。

## 2. CM 目前已支持什么

先说平台 / pack 已经存在的能力面：

- formula fields
- validation rules
- rollup summaries
- record-triggered Flow substrate
- 部分 auto-number

再说已经有明确本地证据的代表性机制：

- Lead 侧已有
  `BN_Lead_Relate_to_Account_by_Email_Domain_Flow`
  `IQM_Completion_Flow`
  `Lead_Auto_Create_Org`
  `Lead_Status_Duration`
- Opportunity 侧已有
  `Opportunity_Auto_To_Launch_Stage`
  `Opportunity_Close_Date_Auto_Set`
  `Opportunity_Cloud_Order_Type_Set`
  `Opportunity_Launch_Stage_Validation`
  `Opportunity_Pricebook_Default`
  `Std_OpportunityStageDerivedFields`
- Campaign attribution 侧已有
  `Lead_Set_First_And_Last_CampaignMember`
  `Contact_Set_First_And_Last_CampaignMember`
  这一组 first/last touch 维护 Flow
- Account / Org 侧已有
  `Org_Set_Account`
- validation 定义已明确落地但未必激活的有
  `Nurture_Marketing_Date`
  `Nurture_Sales_Date`
  `PingCAP_Contract_Entity_EMEA_only`
- local auto-number 已明确落地的有
  `Account_ID__c`
  `ContractNumber`
  `OrderNumber`
  `QuoteNumber`

更重要的是，这些不是“只有文件存在”。
本地 pack 里已经能看到 active 的 record-triggered Flow，例如：

- `IQM_Completion_Flow` 是 `Lead` 上的 `RecordBeforeSave`
  `CreateAndUpdate` Flow
- `Opportunity_Cloud_Order_Type_Set` 是 `Opportunity` 上的
  `RecordBeforeSave` Flow
- `Org_Set_Account` 是 `Org__c` 上的 `RecordBeforeSave` Flow

finance 这条线也不能再写成“Order 基本没接住”。
按当前仓库证据，本地 `Order` 已经至少承接了：

- `Quote -> Order` 核心字段继承
- payment field inheritance
- `Order_Default_RevRec_Entity`
- account-level governing-contract validation replacement policy

所以结论很明确：

`CM 不是没有 Flow/validation/rollup 这类能力，而是这些能力只覆盖了 live Salesforce 语义的一部分。`

## 3. CM 当前主要差异 / 风险点是什么

当前差异最好分成 4 类，不要混成一类“能力缺口”。

### A. `activation-state mismatch`

定义已经在本地，但 live 是 active、本地是 inactive。

当前最明确的是：

- `Lead.Nurture_Marketing_Date`
- `Lead.Nurture_Sales_Date`
- `Opportunity.PingCAP_Contract_Entity_EMEA_only`
- `Quote.Customer_s_Hardware_Configuration`
- `Quote.Details_of_vCPU_Calculation`
- `Quote.Version_of_TiDB`

这类更像
`配置/启用状态没对齐`
，
不是没能力。

### B. `exact named missing mechanisms`

名字已经拿到，而且当前本地 pack 确认没找到。

高价值例子：

- `Account_Contract_Valid_Message`
- `Account_Current_Order_Type`
- `Order_Org_Auto_Set_Account_Create`
- `Order_Org_Auto_Set_Account_Update`
- `Order_Set_PLG_BD_Pool`
- `Campaign_Member_Key_Message_Update`
- `RevRec_Set_PLG_BD_Pool`
- `Quote_update_nonstandard_conditions_checkbox`
- `Quote_update_nonstandard_conditions_checkbox_2`

这类最适合直接进
`L2 pack parity backlog`
。

### C. `auto-number parity missing`

当前本地 auto-number 已有：

- `Account_ID__c`
- `ContractNumber`
- `OrderNumber`
- `QuoteNumber`

当前本地 auto-number 仍缺：

- `Revenue__c.Name`
- `Invoice_Collection__c.Name`
- `Opportunity_Product__c.Name`
- `Order_Product__c.Name`
- `Quote_Product__c.Name`

这类也更像
`pack parity`
，
不是平台完全没法做。

但 finance 线上不要把这类缺口和 `Flow/status/carry-over` 缺口等权看待。

按当前仓库证据：

- `salesforce_orders`、`salesforce_order_daily_view`、
  `cp_order_monthly_revrec`、`monthly_cloud_billing_revrec.py`
  主要按 `order_id`、`order_name`、金额、状态、服务期在算
- `Revenue__c.Name` 目前更明确只是被暴露成 `revenue_name`
- `Invoice_Collection__c.Name` 当前更明显出现在通知模板里，而不是 finance
  SQL 的核心 join key 里

所以：

- `Name auto-number` 仍然该补
- 但如果目标是先止住 `gcp-digital-bi` 的 finance 指标漂移，
  `CollectionsStatus / carry-over / PLG pool / invoice-status`
  这类 Flow parity 的优先级更高

### D. `runtime boundary`

这才是更接近
`CM 目前真没支持`
的部分。

高风险对象：

- `LeadTrigger`
- `LeadAITrigger`
- `OpportunityTrigger`
- `AccountTrigger`
- `OrderTrigger`
- `QuoteTrigger`
- `RevenueTrigger`
- custom line-item trigger surfaces

这部分如果要做 parity，通常不是补 metadata 就完，需要把 Apex 逻辑改写成
Flow / metadata-action
或真正补 runtime 能力。

### E. `intentional replacement`

还有一类不要误判成缺口：

- `Order_Activate_Contract_Status`
- `Order_Activate_Contract_Start`
- `Order_Activate_Contract_End`
- `Order_Activate_Requires_Contract`
- `Order_Create_Requires_Effective_CSA_MA_Contract`

这组目前更像 PingCAP 本地 policy 的有意替代，不是普通 drift。

### F. 报告里的项是不是都算 `CM gap`

不是。

更准确地说，这份报告列的是
`Salesforce live 行为 vs CM 当前落地状态`
之间所有会影响 BI 口径的差异项。

其中只有一部分应该被归为
`CM 真 gap / runtime boundary`
。

最稳的重分类是：

| 差异类型 | 默认算不算 `CM 真 gap` | 现在怎么读 |
|---|---|---|
| `activation-state mismatch` | `No` | 定义已经在本地，只是 live active / local inactive |
| `exact named missing mechanisms` | `Usually no` | 多数属于 `CM 已支持，但 PingCAP L2 pack 还没补齐` |
| `auto-number parity missing` | `Usually no` | 多数属于 `CM 已支持，但本地 metadata 还没补齐` |
| `intentional replacement` | `No` | 先确认 PingCAP 本地 policy 是否就是期望口径 |
| `runtime boundary` | `Yes` | 这才是更像 `CM 目前真没支持` 的部分 |

所以如果有人问：

`报告里列出来的都是 CM 的 gap，对吧？`

当前最稳回答是：

`不对。报告列的是 BI 风险差异清单，不是纯 CM 能力缺陷清单。`

为了避免后文再被误读，整份报告默认按下面这条规则读：

- `CM 当前主要差异 / 风险点`
  不等于
  `CM 没能力`
- 只有明确落到
  `runtime boundary`
  或仍只活在 live Salesforce trigger/runtime 里的残余逻辑，才优先按
  `CM 真边界`
  处理

四个最能说明这个边界的代表例子：

| 例子 | 现在最稳归类 | 为什么不该直接读成 `CM 没能力` |
|---|---|---|
| `Lead_Assignment_Rule_modification_for_NA_EMEA` | `已支持 / 已回归覆盖` | 本地已有 regression case 通过，说明这条不是 gap |
| `Lead_StatusChangeTimestamp` | `semantic parity mismatch` | 本地 `Lead_Status_Duration` 已近似承接，只是写入条件比 live 更宽 |
| `Order_Activate_Contract_*` | `intentional replacement` | 当前证据更支持 PingCAP 本地 governing-contract policy 替代，不是 accidental missing |
| `Campaign_Member_Key_Message_Update` | `L2 exact-flow parity` | 这是 pack 侧同名 Flow 缺口，不是 `CampaignMember` 对象或 CM Flow substrate 不存在 |

## 3.5 三桶拆分

如果现在就要把高价值差异项直接分桶，最稳的是下面这张表。

| 桶 | 对象/机制 | 当前判断 | 直接受影响报表/模型 | 建议动作 |
|---|---|---|---|---|
| `CM 已支持，但没配齐` | `Lead.Nurture_Marketing_Date`, `Lead.Nurture_Sales_Date` | 定义已在本地，只是 local inactive | `salesforce_leads`, `dim_lead`, `dws_lead_timeline` | 先做 activation 对齐，不先定义成平台缺口 |
| `CM 已支持，但没配齐` | Lead assignment / reminder / notification parity surfaces | 当前更像 L2 Flow parity backlog，不像 substrate 缺失 | `salesforce_lead`, `salesforce_leads`, `dws_lead_timeline`, `cloud-lead-pipeline-insight` | 继续补 exact-name Lead Flow，并把剩余 name clue 做完 |
| `CM 已支持，但没配齐` | `Opportunity.PingCAP_Contract_Entity_EMEA_only` + 3 条 Quote inactive validation | 定义已在本地，只是 activation-state mismatch | `salesforce_oppo`, `salesforce_opportunities`, `dws_salesforce_arr_summary`, `dws_opportunity_stage_duration` | 先激活，再复核下游口径 |
| `CM 已支持，但没配齐` | `Quote_update_nonstandard_conditions_checkbox`, `Quote_update_nonstandard_conditions_checkbox_2` | 已知 exact-name missing Flow | `salesforce_opportunities`, `dim_opportunity`, `dws_salesforce_arr_summary` | 直接进 `L2 pack` backlog |
| `CM 已支持，但没配齐` | `Campaign_Member_Key_Message_Update` | 已知 exact-name missing Flow | `salesforce_campaign_members`, `dws_campaign_attribution`, `dws_lead_timeline` | 直接补 Flow，优先级高 |
| `CM 已支持，但没配齐` | `Account_Contract_Valid_Message`, `Account_Current_Order_Type`, `Account_Partner_Sales_Owner_Set` | 已知 exact-name missing Flow | `crm_account`, `salesforce_accounts`, `dim_account`, `dim_tenant` | 直接进 `L2 pack` backlog |
| `CM 已支持，但没配齐` | `Order_Org_Auto_Set_Account_*`, `Order_Set_PLG_BD_Pool`, `contractOpportunityInset`, `RevRec_Set_PLG_BD_Pool`, `Collection_Set_PLG_BD_Pool`, `Collection_Amount_and_Payable_Amount_exc_tax`, `Collection_Amount_and_Payable_Amount_exc_tax_Update`, `Cloud_Registration_Source_from_Org_to_Collections` | 已知 exact-name missing Flow / carry-over gap；都更像 finance parity backlog，不像 substrate 缺失 | `salesforce_orders`, `salesforce_order_daily_view`, `cp_order_monthly_revrec`, `salesforce_revrec`, `salesforce_org_monthly_revrec`, `stg_salesforce_invoice_collection` | 作为 finance parity backlog 优先处理 |
| `CM 已支持，但没配齐` | `Revenue__c.Name`, `Invoice_Collection__c.Name`, custom line-item `Name` | 缺的是 auto-number parity，不是明确 substrate 缺失；当前 BI 直接爆炸半径也低于 finance status/carry-over Flow 缺口 | `salesforce_revrec`, `stg_salesforce_invoice_collection`, `salesforce_orders`, `salesforce_opportunity_products` | 直接补 `L2 metadata`，但 finance 止血不应排在状态切换 Flow 前面 |
| `更像 CM 真边界` | `LeadTrigger`, `LeadAITrigger` | 仍只活在 live Apex trigger | `salesforce_leads`, `dws_lead_timeline`, `cloud-lead-pipeline-insight` | 单列 Apex 替代设计，不和普通 parity 混排 |
| `更像 CM 真边界` | `OpportunityTrigger`, `QuoteTrigger` | 仍只活在 live Apex trigger | `salesforce_opportunities`, `dws_salesforce_arr_summary`, `dws_opportunity_stage_duration` | 单列 runtime / Flow rewrite 项 |
| `更像 CM 真边界` | `OrderTrigger`, `RevenueTrigger`, custom line-item trigger surfaces | 仍只活在 live trigger/runtime 逻辑 | `salesforce_orders`, `salesforce_order_daily_view`, `cp_order_monthly_revrec`, `salesforce_org_monthly_revrec` | 单列 finance runtime boundary 项 |
| `更像 CM 真边界` | `AccountTrigger`, `Trigger_CampaignMember` | 目前仍属于 trigger-only 候选边界 | `salesforce_accounts`, `dim_tenant`, `salesforce_campaign_members`, `dws_campaign_attribution` | 先把 pack parity 清掉，再单独评估残余 trigger 逻辑 |
| `更像策略/BI 口径差异` | `Order_Activate_Contract_Status`, `Order_Activate_Contract_Start`, `Order_Activate_Contract_End`, `Order_Activate_Requires_Contract` | 当前证据更支持 PingCAP 本地 policy replacement，不是普通漏迁 | `salesforce_orders`, `salesforce_order_daily_view`, `cp_order_monthly_revrec` | 先确认预期口径，不直接补回 Salesforce 原语义 |
| `更像策略/BI 口径差异` | `Order_Create_Requires_Effective_CSA_MA_Contract` | 当前证据更支持它是被本地 governing-contract policy 替代的 Salesforce-era 旧规则名，不该默认算成 `CM 不会做 validation` | `salesforce_orders`, `salesforce_order_daily_view`, `cp_order_monthly_revrec` | 先做 policy review，不默认回补同名规则 |
| `更像策略/BI 口径差异` | 营销/财务 dashboard owner 清单不完整 | 这是消费面证据边界，不是 CM 对象能力缺口 | 影响的是审计表达完整度，不是某个上游模型本身 | 后续补 dashboard / owner inventory，但不要记成平台 gap |

一句话记忆：

- `Flow / validation / auto-number 同名缺失`，大多数先放到
  `CM 已支持，但没配齐`
- `Apex trigger-only`
  的残余逻辑，才优先放到
  `更像 CM 真边界`
- `Order_Activate_*`
  这种本地 policy 替代，先放到
  `更像策略/BI 口径差异`

## 3.6 高频对象的默认修复层

如果讨论要更快落到
`先补哪里`
，
下面这张短表更直接。

| 对象组 | 当前最稳读法 | 默认第一修复层 | 哪一部分才更像 `CM 真 gap` |
|---|---|---|---|
| `Lead` | 主体是 lifecycle / assignment / timestamp parity，没有证据支持“CM 完全不会做 lead 语义” | `L2 Flow parity` + `activation-state` 对齐 | `LeadTrigger` / `LeadAITrigger` 残余 |
| `Opportunity` + `Quote` | 主体是 pipeline / forecast / quote-commercial parity，很多字段和本地 peer 已经在 | `L2 exact-flow parity` + inactive validation 激活 | `OpportunityTrigger` / `QuoteTrigger` 残余 |
| `CampaignMember` + `Contact` | 主体是 attribution / stitching parity，不是 Campaign 主表能力空白 | `L2 exact-flow parity`，先补 `Campaign_Member_Key_Message_Update`，再补 Contact 邻近 Flow | `Trigger_CampaignMember` + Contact trigger surfaces |
| `Account` + `Org__c` | 主体是 shared-key / tenant bridge parity；本地桥已经在，但 account-side exact-name Flow 还没补齐 | `L2 exact-flow parity`，优先 `Account_Current_Order_Type`、`Account_Partner_Sales_Owner_Set` | `AccountTrigger` 残余 |
| `Order` + `Invoice_Collection__c` | 主体是 finance carry-over / status / org-account bridge parity，不像 substrate 缺失 | `L2 finance carry-over parity`，优先 `Order_Org_Auto_Set_Account_*`、`Order_Set_PLG_BD_Pool`、IC 四条 Flow | `OrderTrigger` 残余 |
| `Revenue__c` | 既有迁移缺口，也开始碰到真实 runtime 边界 | 先补 `RevRec_Set_PLG_BD_Pool` + `Name` auto-number | `RevenueTrigger` 残余 |
| custom line-item 三件套 | 既是 pack parity，也带 trigger-only 明细逻辑 | 先补三个 `Name` auto-number，再逐条追回 helper Flow/metadata | line-item trigger surfaces |

一句话：

- `对象上有同名 Flow / validation / auto-number 缺口`
  ，默认先补
  `L2 pack`
- `对象上只剩 live Apex trigger`
  ，才默认上升成
  `CM runtime`

## 4. 对哪张报表有影响

最值得直接按报表组来看。

### 对象级速览

如果要最贴近原问题，下面这张表最直接：

| 对象 | Salesforce 现网还在做什么 | CM 目前已支持 | CM 当前主要差异 / 风险点 | 最先影响哪组报表 | 谁更可能先感知 |
|---|---|---|---|---|---|
| `Lead` | 维护 lifecycle、`lead_mql_timestamp`、`lead_iqm_timestamp`、lead-account / tenant 关联、部分 reminder / assignment / notification 语义 | Lead 公式、17 条 active validation、12 条 Lead Flow 已迁；已有 `IQM_Completion_Flow`、`Lead_Auto_Create_Org`、`Lead_Status_Duration` 等；本地 `convertLead` 标准动作也已路由到 `Std_ConvertLead`，并用 `Std_ConvertLeadCampaignPreview` 预览 primary campaign attribution / child relink | 22 个 live Lead Flow 未迁；`Nurture_*` 已定义但 inactive；`LeadTrigger` / `LeadAITrigger` 仍是 runtime boundary；`Lead_StatusChangeTimestamp` 当前更像本地近似承接但语义过宽 | `Lead Funnel / Qualification`，其次 `Campaign Attribution / ICP Analysis`，并继续外溢到 lead signup / acquisition stitching | `alfred.wang@pingcap.com` 的 lead timeline 使用面，`yiming.wang@pingcap.com` 的 ICP / lead analytics 使用面；当前 schema 也已直接坐实 `salesforce_leads` 带 `lead_mql_timestamp`、`lead_iqm_timestamp`、`lead_status`、`pre_account_region`、`pre_account_segmentation`，而 `dim_lead` / `dws_icp_summary` / `dws_lead_timeline` 都明确带 `lead_surrogate_key` |
| `Opportunity` | 维护 stage、forecast、`arr_amount_usd`、`accurate_acv_amount`、`owner_team`、`cloud_order_type`、launch/close helpers，以及和 quote/order 的关键商业语义 | Opportunity 公式、rollup、21 条 active validation、12 条 Flow 已有；`salesforce_opportunities` 所需核心字段在本地完整存在 | 17 个 live Opportunity Flow 未迁；`PingCAP_Contract_Entity_EMEA_only` inactive；`OpportunityTrigger` 仍是 runtime boundary；`OpportunityShareToPersalesOwner` 更像 owner-team 侧 parity gap | `Pipeline / Forecast / Opportunity Quality`，其次 `Campaign Attribution / ICP Analysis` | `Chen Du` 的 data-quality dashboard，`yiming.wang@pingcap.com` 的 dq views，`xiaopeng.zhu@pingcap.com` 的 ARR summary；当前最硬的 live `Looker Studio` surface 只有 `1733a75e-a1b2-4415-8732-2c053657e245`（`dws_data_quality_alerting` + `rpt_data_quality_wtw_comparison` + cleanup detail）和 `837f6250-3c3d-44b9-af6f-4db9aeb30a94`（`dws_salesforce_arr_summary`）。`aadb4637-a4be-41e0-a045-8df92303e595`、`0f2ad8b8-a0a5-40e1-842a-f208c6247c0b`、`d9161f0e-f04c-49dc-82e1-053ab508ce67` 目前更适合作为 `lineage-backed secondary consumer` 来读，而不是和前两者平级宣称为 live report-backed front-door；私有 discovery 资产里还有 `Data Discovery for Salesforce Opportunities` |
| `Quote` | 维护服务起止、nonstandard-term、commercial helper、approval / validation 语义，并回填到 opportunity analytics | `QuoteNumber`、重公式/rollup、部分 validation / Flow、本地 quote-enrichment 已有；更具体地说，`Quote.json` 已有 `Service_Start_Date__c` / `Service_End_Date__c`、`Governing_Service_*`、`Migration_Credit_is_nonstandard__c`、`Other_Nonstandard_Terms_and_Conditions__c`，approval 备份已直接引用 nonstandard-term 字段，而 Order governing-contract validation 还会继续消费 quote service-window | 2 条 Quote Flow 缺失，3 条 Quote validation 已定义但 inactive；因此当前更像“cleanup / auto-check parity 缺口”，不是“Quote 没有 nonstandard-term / service-window substrate”；`QuoteTrigger` 仍是 runtime boundary | `Pipeline / Forecast / Opportunity Quality` | 先在 `salesforce_opportunities` / `dim_opportunity` / data-quality 报表面暴露；当前最稳定的 governed/report-backed surface 仍然复用 `1733a75e-a1b2-4415-8732-2c053657e245` 和 `837f6250-3c3d-44b9-af6f-4db9aeb30a94` 这组 opportunity family；`aadb4637-a4be-41e0-a045-8df92303e595` 更适合作为 secondary lineage clue，不和主 front-door 平级。`1733...` 的 `dws_salesforce_pipeline_data_quality_cleanup_detail_v2` datasource 已经直接点到 `quote_service_start_date`，说明 quote service-window 不只是间接存在于模型里，而是已经进入前台 quality cleanup 面。 |
| `CampaignMember` | 维护 `first_responded_date`、response/status/involvement、first/last touch 语义 | 已有 4 条 first/last touch Flow；本地模型已计算 `attribution_percentage`、`attributed_acv`、`attributed_arr`；`convertLead` 标准动作还显式声明读取 `CampaignMember` 做 primary campaign attribution preview，而 `Std_RelinkLeadChildren` 会把 converted Lead 的 `CampaignMember` child 重新挂到 Contact；当前 `dbt-dev` 还会把缺失的 `first_responded_date` 按 involved 状态用 `created_date` / `last_modified_date` 中点回填 | `Campaign_Member_Key_Message_Update` 缺失；`Trigger_CampaignMember` 仍是 runtime boundary | `Campaign Attribution / ICP Analysis`，也会打到 `Lead Funnel / Qualification` | `yiming.wang@pingcap.com` 的 attribution / ICP queries，以及 `Campaign Attribution Tuner` / campaign discovery 使用面；当前最硬的 governed consumer `8c6f30a4-c6fe-4536-ac62-d937d0176ebd` 这轮 live query 最直接命中的是 `dws_marketing.dws_campaign_attribution`，字段已复现到 `attributed_arr`、`campaign_id`、`campaign_name`、`contact_response_date`、`opportunity_contact_role`；schema 侧也已坐实 `salesforce_campaign_members` 带 `first_responded_date`、`campaign_member_status`、`has_responded`、`is_contact_involved`、`contact_involvement_level` |
| `Contact` | 维护 owner/internal/cloud 默认值和部分 region/account helper，并参与 lead/contact merge 与 campaign attribution stitching | Contact 基础对象、5 条公式、`Contact_Set_First_And_Last_CampaignMember*` 已有；本地 contact/lead/campaign member 拼接链已跑通 | live Contact Flow 当前未见本地 peer；Contact trigger surfaces 仍是 runtime boundary | `Campaign Attribution / ICP Analysis`，其次 `Lead Funnel / Qualification` | 当前最硬的 governed surface 是 `report_id = 8c6f30a4-c6fe-4536-ac62-d937d0176ebd` 的 attribution 明细，而且 live datasource 组合已经坐实它同时带 `contact`、`lead`、`campaign_member`、`opportunity_contact_role`；更硬一点的 schema 证据是 `dws_campaign_attribution` 和 `dws_campaign_attribution_details` 都直接带 `contact_name`、`contact_response_date`、`is_contact_primary`、`campaign_name`、`campaign_region`、`opportunity_name`；`fd12e3fc-d36f-4cc5-b2d9-9ed2808489dc` 则会复用 `dws_lead_timeline` / `anls_marketing.dim_lead` |
| `Order` | 维护 order-to-org carry-over、payment/contract gating、服务窗口、order-day 累计收入语义 | `OrderNumber`、本地 Order 公式/rollup、`Std_CreateOrderFromQuote`、payment field inheritance、`Order_Default_RevRec_Entity` 已有；当前还能更具体地说，active `Cloud_Registration_Source_from_Org_to_Order` 已把 `Org.source__c -> Order.Cloud_Registration_Source__c` 接上 | `Order_Org_Auto_Set_Account_*`、`Order_Set_PLG_BD_Pool`、部分 carry-over gap 未补；`OrderTrigger` 仍是 runtime boundary | `Order / ARR / RevRec / Collections` | `xiaopeng.zhu@pingcap.com`、`fanfei.kong@pingcap.com` 的 order-day / revrec 使用面；当前 governed/report-backed finance surface 不只 `837f6250-3c3d-44b9-af6f-4db9aeb30a94` 的 ARR summary，还包括 `58339683-7a7a-4bb6-91bd-14b149572ac9` 长期打 `dws_salesforce_order_current_monthly_mrrarr_bo_subscription_and_cloud`、account-quarterly MRRARR pivot，以及 `f9c4bd70-8ce4-487c-abb1-5518ffffd6bd` 直接打 `model_fp_and_a.dws_salesforce_activated_order_account_basic_info_v3`。另一方面，从 `2026-01-01` 到现在仍未看到 `Looker Studio` 直接命中 `salesforce_order_daily_view` / `salesforce_org_monthly_revrec` / `monthly_revrec_*`，但 `fanfei.kong@pingcap.com` 的 live direct query 已经持续打 `salesforce_order_daily_view` 与 `salesforce_org_monthly_revrec`，所以 collections / revrec 使用面不能再只写成纯 lineage；私有 discovery 资产里还有 `revrec_discovery`、`monthly_billing_validation` |
| `Revenue__c` | 维护 revrec 明细、`amount_before_adjust`、`revenue_status`、汇率与月度 revenue 聚合语义 | Revenue 公式已有，`RevRec_Account` / `RevRec_Partner_Name` 已有，本地 finance marts 已建 | `RevRec_Set_PLG_BD_Pool` 缺失；`Revenue__c.Name` auto-number 缺失；`RevenueTrigger` 仍是 runtime boundary | `Order / ARR / RevRec / Collections` | 先在 `salesforce_revrec` / `dws_salesforce_arr_summary` / monthly revrec 使用面暴露；当前 governed 面更像 `837...` 这类 ARR + forecast/quota 复合 surface，而 `f9c4...` 这轮又进一步给了一个更硬的月度 revrec report-backed 面：label-backed SQL 已直接打 `model_fp_and_a.dws_salesforce_activated_order_account_monthly_revrec_v3`，字段片段能复现 `revrec_usd`、`serverless_revrec_usd`、`support_revrec_usd`、`order_accumulate_revenue_to_org`。更细的 `revenue_amount` / `credit_amount` / `adjusted_revenue_amount` 仍主要停在 `fanfei.kong@pingcap.com` 的 `salesforce_org_monthly_revrec` / 邻近 monthly revrec direct-query 面，而不是独立的 revenue Looker report。 |
| `Invoice_Collection__c` | 维护 collection status、cash/payable helper、PLG pool、marketplace/cloud-registration carry-over、invoice notice 语义 | 本地已有不少公式/rollup，Order 侧已经消费 collections 相关汇总；`dbt-dev` staging 已明确投出 `collections_status_c`、`cash_collected_c`、`payable_amount_usd_2_exc_tax_c`、`plg_bd_pool_c`、`marketplace_c` | 4 条高置信 live Flow 仍未迁；`Invoice_Collection__c.Name` auto-number 缺失；更像 finance parity backlog 而不是平台空白 | `Order / ARR / RevRec / Collections` | 先在 `salesforce_order_daily_view` / `salesforce_org_monthly_revrec` / collections-revrec 校验面暴露。更稳的读法是：`f9c4...` 已经把 activated-order/monthly-revrec/account-tenant bridge 这层前门坐实，但 `collections_status_c` / `cash_collected_c` / `payable_amount_usd_2_exc_tax_c` / `marketplace_c` 这组 helper 字段，在当前证据里更硬的是 `salesforce_order_daily_view`、`salesforce_org_monthly_revrec` 和 recurring-output/direct-query 面，而不是最新同批 report SQL 明文。 |
| `Opportunity_Product__c` / `Order_Product__c` / `Quote_Product__c` | 维护 `product_family`、`net_fees`、`list_price`、服务窗口、man-day / surplus 等 line-item 语义，并统一 auto-number `Name` | 三个对象都有公式；`Order_Product__c` 还有 1 个 rollup 和 1 条 validation；本地已有多条 line-item helper 机制 | 三个 `Name` auto-number 都缺；trigger-only line-item 逻辑仍留在 live Salesforce | `Pipeline / Forecast / Opportunity Quality` 与 `Order / ARR / RevRec / Collections` | `0f2ad8b8-a0a5-40e1-842a-f208c6247c0b` 先在 `dws_opportunity_stage_duration` / `dws_opportunity_stage_conversion_rates` 暴露 `opportunity_product_family`；`58339683-7a7a-4bb6-91bd-14b149572ac9`、`837f6250-3c3d-44b9-af6f-4db9aeb30a94`、`df532c1a-ba9a-44b1-aa56-50b6b0869591`、`f9c4bd70-8ce4-487c-abb1-5518ffffd6bd` 则先在 current/monthly order MRRARR 与 ARR family 暴露 `order_product_family` / ARR / MRR |
| `Account` | 维护 `AccountID`、`Region`、`Segmentation`、`ICP`、owner / account-current-order-type 等共享维度语义 | `Account_ID__c`、Account 公式/rollup/部分 Flow 已有；共享维表所需核心字段已在本地链路中；当前还能再更具体地说，本地 active Flow 至少已包括 `Account_status_Flow`、`Account_First_Order_Start_Date_Update`、`Account_Auto_Submit_Approval` | 4 个 live Account Flow 缺失；`AccountTrigger` 仍是 runtime boundary | `Account / Tenant Linkage / Customer Identity`，也会外溢到 `Lead Funnel` / `Pipeline`，并通过 cloud-tenant enrichment 进入 `PLG / signup funnel` | `xiaopeng.zhu@pingcap.com`、`chen.du@pingcap.com` 的 account 维度使用面；当前已坐实的 live `Looker Studio` account surface 主要是 `673c89ef-fb02-4303-a9a2-5519a652051c`、`58339683-7a7a-4bb6-91bd-14b149572ac9`、`2128769b-9f86-4c7a-a9f4-8cc7491868e3`；`aadb4637-a4be-41e0-a045-8df92303e595` 更像 opportunity/account 共用的 secondary lineage consumer。`58339683...` 现在还能更具体地看成 `salesforce/nexuscrm account+org` 与 account-quarterly / order-current-month MRRARR 的复合消费面；而 schema 侧也已直接坐实 `salesforce_accounts` 带 `account_id`、`account_number`、`fy26_icp`、`fy26_segmentation`、`industry`、`owner_user_id`、`region`、`vertical`，`model_tidbcloud.dws_cloud_tenants_basicinfo` 还直接带 `account_id`、`account_name`、`account_industry`、`account_segmentation`、`account_current_order_type`、`account_tam_name`。这轮再往前推进了一步：当前 live report-backed query 里，`account_current_order_type` 已直接命中 `31605...` 和 `f9c4...`，而 `sales_team_name` / `owner_user_id` 已直接命中 `673...` 和 `212...`；相反，`contract_valid*` 在这组 front-door 里暂时还是 `0 hit`。 |
| `Org__c` | 维护 org-tenant-account 关系、`accumulate_revenue_to_org_tenant_id`、cloud-registration / revenue accumulation 语义 | `Org_Set_Account` 已有；本地 org/account 桥和 finance link 已存在 | 邻近的 Order / Invoice carry-over parity 仍会反向污染 org/tenant 维表 | `Account / Tenant Linkage / Customer Identity`，以及 `Order / ARR / RevRec / Collections` | `laura.luo@pingcap.com` 的 dim-customer / tenant lookup，`bi-reader-sa` 对 `dim_org` 的稳定读取，以及 `eric.chen@pingcap.com` 对 `salesforce_org_monthly_revrec` 的 tenant-month 使用面；当前 schema 也已坐实 `dim_org` 带 `tenant_id`、`account_id`、`accumulate_revenue_to_org_tenant_id`、`org_name`，`dim_customer` 带 `customer_surrogate_key`、`salesforce_account_id`、`salesforce_account_number`、`tenant_ids`、`region`、`is_billing_capable`，`anls_cloud.dim_tenant` 还直接带 `tenant_id`、`tenant_name`、`org_name`、`account_name`、`tenant_email`、`tenant_email_domain`。 |
| `Contract` | 维护 `ContractNumber`、status/approval/effective-date 和 account-contract-valid 这类治理语义 | `ContractNumber`、4 条公式、1 条 validation、2 条本地 Contract Flow 已有 | 2 条 live Contract Flow 未迁；contract trigger 仍是 runtime boundary | 更像复用 `Pipeline / Forecast / Opportunity Quality` 与 `Order / ARR / RevRec / Collections`，而不是单独一组 contract 报表 | 当前更稳的 consumer surface 仍主要复用 `1733a75e-a1b2-4415-8732-2c053657e245`、`837f6250-3c3d-44b9-af6f-4db9aeb30a94` 这组主 opportunity/ARR family；`aadb4637-a4be-41e0-a045-8df92303e595`、`0f2ad8b8-a0a5-40e1-842a-f208c6247c0b`、`d9161f0e-f04c-49dc-82e1-053ab508ce67` 现在更适合当 secondary lineage consumer，而不是独立 contract dashboard |

### 对象到具体模型速查

如果问题要落到
`到底是哪几张报表 / 哪几个模型先被打到`
，
下面这张表更直接：

| 对象 | 当前能直接点名的 Looker / dbt 模型 | 最敏感字段 / 语义 |
|---|---|---|
| `Lead` | Looker `salesforce_lead`, `cloud-lead-pipeline-insight`; dbt `salesforce_leads`, `dim_lead`, `dws_lead_timeline`, `dws_icp_summary` | `lead_mql_timestamp`, `lead_iqm_timestamp`, `LeadLifecycleStage`, `LeadStatus`, `account_id`, `TiDBCloudPortalID`; 以及 `dim_lead` 里的 `first_touch_source_channel`, `sign_up_source_channel` |
| `Opportunity` | Looker `salesforce_oppo`, `cloud-lead-pipeline-insight`; dbt `salesforce_opportunities`, `dim_opportunity`, `dws_salesforce_arr_summary`, `dws_opportunity_stage_duration`, `dws_opportunity_stage_conversion_rates`, `dws_data_quality_alerting`, `salesforce_campaign_attribution`, `salesforce_orders` | `forecast_category`, `forecast_type`, `stage_name`, `stage_duration_days`, `arr_amount_usd`, `accurate_acv_amount`, `owner_team`, `cloud_order_type`, `launch_date` |
| `Quote` | dbt `salesforce_opportunities`, `dim_opportunity`, `dws_salesforce_arr_summary`, `dws_opportunity_stage_duration`，以及后续 order / ARR reporting | `service_start_date`, `service_end_date`, nonstandard-term / support-tier / discount helper |
| `CampaignMember` | dbt `salesforce_campaign_members`, `salesforce_campaign_attributions`, `salesforce_campaign_attribution_details`, `dws_campaign_attribution`, `dws_campaign_attribution_details`, `dws_lead_timeline`, `dws_icp_summary` | `first_responded_date`, `campaign_member_status`, `has_responded`, `contact_involvement_level`, `attribution_percentage`, `attributed_acv`, `attributed_arr` |
| `Contact` | dbt `salesforce_contacts`, `salesforce_leads`, `dim_lead`, `salesforce_campaign_interacted_accounts`, `dws_campaign_attribution_details`, `dws_lead_timeline`; governed surface 已坐实 `report_id = 8c6f30a4-c6fe-4536-ac62-d937d0176ebd` | `contact_name`, `email`, `status`, `account_id`, `contact_response_date`, `is_contact_primary`, lead/contact stitching |
| `Order` | dbt `salesforce_orders`, `salesforce_order_daily_view`, `salesforce_order_current_monthly_arr`, `cp_order_monthly_revrec`, `dws_salesforce_arr_summary`, `salesforce_org_monthly_revrec` | `accumulate_revenue_to_org_tenant_id`, `order_status`, `order_product_family`, `order_service_start_date`, `order_service_end_date`, `revenues`, `accumulated_revenue` |
| `Revenue__c` | dbt `salesforce_revrec`, `salesforce_orders`, `salesforce_order_daily_view`, `cp_order_monthly_revrec`, `salesforce_org_monthly_revrec` | `revenue_name`, `revenue_date`, `revenue_status`, `amount_before_adjust`, `amount`, `credit_amount`, `revenue_exchange_rate` |
| `Invoice_Collection__c` | dbt `stg_salesforce_invoice_collection`, `salesforce_orders`, `salesforce_order_daily_view`, recurring finance / collections outputs | `invoice_status_c`, `collections_amount_c`, `cash_collected_c`, `payable_amount_usd_2_exc_tax_c`, `plg_bd_pool_c`, `actual_billing_date_c` |
| `Opportunity_Product__c` / `Order_Product__c` / `Quote_Product__c` | dbt `salesforce_opportunity_products`, `salesforce_opportunities`, `dws_opportunity_stage_duration`, `dws_opportunity_stage_conversion_rates`, `salesforce_orders`, `salesforce_order_daily_view`, `cp_order_monthly_revrec` | `opportunity_product_name`, `product_family`, `net_fees`, `service_start_date`, `service_end_date`, `order_product_family`, service-window rollups |
| `Account` | Looker `crm_account`, `cloud-lead-pipeline-insight`; dbt `salesforce_accounts`, `dim_account`, `anls_cloud.dim_tenant`, `dws_icp_summary`, `customer_surrogate_keys`, `customers`, `model_tidbcloud.dws_cloud_tenants_basicinfo` | `AccountID`, `Region`, `Segmentation`, `ICP`, `Industry`, `TenantStatus`, `TiDBCloudPortalID`, `tenant_ids`, `account_current_order_type`, `account_tam_name` |
| `Org__c` | dbt `salesforce_orgs`, `dim_org`, `dim_tenant`, `salesforce_accounts`, `salesforce_org_monthly_revrec`, `customer_surrogate_keys`; Looker `crm_account` 的 tenant enrichment | `tenant_id`, `account_id`, `accumulate_revenue_to_org_tenant_id`, `org_name` |
| `Contract` | dbt `salesforce_opportunities`，以及继续串到 `stg_salesforce_order`, `stg_salesforce_quote`, `stg_salesforce_revenue`, `stg_salesforce_invoice_collection` 的跨对象治理链 | `contract_id`, `contract_archived_date`, contract-valid / effective-date governance |

### 次一级对象补充

上面那 9 个对象是最核心的一层，但还有几类对象虽然不总是直接作为 headline mart 出现，实际上也会把语义往下游传：

| 对象 | 当前更像打到哪里 | 为什么不能忽略 |
|---|---|---|
| `Opportunity_Product__c` | dbt `salesforce_opportunity_products`，再进 `salesforce_opportunities` 及其下游 | line-item 的产品族、服务起止、net fee 会改写机会侧服务窗口和产品分析。 |
| `Order_Product__c` | dbt `salesforce_orders`, `salesforce_order_daily_view`, `cp_order_monthly_revrec` | order-line 的服务窗口和净额会直接改写 revrec / ARR / commitment plan 口径。 |
| `Quote_Product__c` | 先经 quote enrichment 进入 `salesforce_opportunities`，再外溢到 pipeline / ARR reporting | quote line-item 的商业条款和产品语义会被折叠进机会分析。 |
| `Contract` | staging 层，以及 `salesforce_opportunities`, `stg_salesforce_order`, `stg_salesforce_quote`, `stg_salesforce_revenue`, `stg_salesforce_invoice_collection` 这些跨对象链路 | 它不是 headline mart，但它是机会、订单、收入、回款之间的治理键，contract gating / replacement policy 会跨对象扩散。 |
| `Contact` | dbt `salesforce_contacts`, `salesforce_leads`, `dws_campaign_attribution`, `dws_campaign_attribution_details`, `dws_lead_timeline` | contact parity 问题不会只停在联系人对象本身，会打歪 lead/contact stitching 和 campaign attribution join。 |
| `Campaign` | dbt `salesforce_campaigns`, `salesforce_campaign_members`, `salesforce_campaign_attributions`, `dws_campaign_attribution`, `dws_icp_summary` | campaign 主表和 `CampaignMember` 一起决定 first-touch / last-touch / pre-IQM / pre-opp attribution 语义。 |

### 三个对象继续深挖

如果要继续沿着
`Salesforce 会做什么`
、
`CM 已支持什么`
、
`CM 未支持/疑似未支持什么`
、
`会先打到哪张报表`
这四列往下走，当前最值得优先盯的还是
`Lead`
、
`Opportunity`
、
`Invoice_Collection__c`
。

#### `Lead`

| 维度 | 当前最稳结论 |
|---|---|
| Salesforce 现网会做什么 | 不只是写 `lead_mql_timestamp` / `lead_iqm_timestamp`。现网还明确有 `Lead_Assignment_Rule_modification_for_NA_EMEA` 这类 assignment flow，以及 `Lead_StatusChangeTimestamp` 这种 `RecordBeforeSave` `CreateAndUpdate` flow：只有当 `Status` 进入 picklist tag `working_or_later` 时，才写 `Date_Status_Changed__c = $Flow.CurrentDateTime`。 |
| CM 目前已支持 | 本地已明确有 `IQM_Completion_Flow`、`Lead_Auto_Create_Org`、`BN_Lead_Relate_to_Account_by_Email_Domain_Flow`、`Lead_Status_Duration`，再加上 Lead 公式和 17 条 active validation。也就是说 lifecycle、IQM、account/org 关联、状态改写 substrate 都不是空白。 |
| CM 当前主要差异 / 风险点 | 22 个 live Lead Flow 仍未迁；`Nurture_Marketing_Date` / `Nurture_Sales_Date` 已定义但 inactive；`LeadTrigger` / `LeadAITrigger` 仍是 runtime boundary。`Lead_StatusChangeTimestamp` 也不该再读成“完全没支持”，而是 `本地有近似 flow，但语义比 live 更宽` 的 parity mismatch。 |
| 直接打到哪些字段 / 模型 | 已硬证实的营销主链字段是 `lead_mql_timestamp`、`lead_iqm_timestamp`、`LeadStatus`、`account_id`、`TiDBCloudPortalID`，直接进 Looker `salesforce_lead`, `cloud-lead-pipeline-insight` 和 dbt `salesforce_leads`, `dim_lead`, `dws_lead_timeline`, `dws_icp_summary`。更硬一点的 live schema 证据是：`dwh_marketing.salesforce_leads` 明确带 `lead_mql_timestamp`、`lead_iqm_timestamp`、`lead_status`、`pre_account_region`、`pre_account_segmentation`；`anls_marketing.dim_lead` 明确带 `lead_surrogate_key`、`salesforce_account_id`、`salesforce_contact_ids`、`salesforce_lead_ids`、`first_touch_source_channel`、`sign_up_source_channel`；`dws_icp_summary` 和 `dws_lead_timeline` 也都直接带 `lead_surrogate_key`。`date_status_changed` 目前只在 `stg_salesforce_lead` 这层被直接坐实，还不能过度外推到命名 marketing marts。 |
| 当前最稳读法 | Lead 这条线主要不是 `CM 没能力`，而是 `Lead lifecycle / assignment / status semantics 还没完全迁齐`；真正更像平台边界的仍是 `LeadTrigger` / `LeadAITrigger`。当前更硬的 consumer 读法也不该只停在“marketing mart 名字”，而是已经能具体落到 `salesforce_leads -> dim_lead / dws_icp_summary / dws_lead_timeline` 这一组带 `lead_surrogate_key` 和 source-channel 字段的前台链。 |

#### `Opportunity`

| 维度 | 当前最稳结论 |
|---|---|
| Salesforce 现网会做什么 | 现网持续维护 `stage_name`、`forecast_category`、`forecast_type`、`arr_amount_usd`、`accurate_acv_amount`、`owner_team`、`cloud_order_type`、launch/close helper。已恢复出高信号 live 行为包括 `Opportunity_Stage_To_Lunched` 这条 scheduled flow，以及 `OpportunityShareToPersalesOwner` 这条 `RecordAfterSave` create-flow；update 场景很可能走 sibling `OpportunityUpdateShareToPerSalOwner`。 |
| CM 目前已支持 | 本地已经有 `Opportunity_Auto_To_Launch_Stage`、`Opportunity_Close_Date_Auto_Set`、`Opportunity_Cloud_Order_Type_Set`、`Opportunity_Pricebook_Default`、`Std_OpportunityStageDerivedFields`、`Add_or_update_Opt_Owner_s_Role`，再加上 21 条 active validation、公式和 rollup。机会主表进入 `salesforce_opportunities` 所需的大部分核心字段已能本地表达；其中 `Add_or_update_Opt_Owner_s_Role` 还会在 `RecordBeforeSave(CreateAndUpdate)` 把 `Owner.UserRole.Name` 写到 `Opt_Owner_Role__c`，所以 owner-role 语义并不是本地空白。 |
| CM 当前主要差异 / 风险点 | 17 个 live Opportunity Flow 仍未迁；`PingCAP_Contract_Entity_EMEA_only` 已定义但 inactive；`OpportunityTrigger` 仍是 runtime boundary。当前最强 exact-name missing candidate 是 `OpportunityShareToPersalesOwner`，但要注意这条被确认的是 create-flow，不宜直接把 update 行为也归到同一条名字上；更稳的说法是 `local owner-role peer exists, but exact presales share/access parity is still missing`。 |
| 直接打到哪些字段 / 模型 | 最直接命中的字段是 `forecast_category`、`forecast_type`、`stage_name`、`stage_duration_days`、`arr_amount_usd`、`accurate_acv_amount`、`owner_team`、`cloud_order_type`、`launch_date`。对应模型包括 Looker `salesforce_oppo`, `cloud-lead-pipeline-insight` 和 dbt `salesforce_opportunities`, `dim_opportunity`, `dws_salesforce_arr_summary`, `dws_opportunity_stage_duration`, `dws_opportunity_stage_conversion_rates`, `dws_data_quality_alerting`, `salesforce_orders`。其中 `owner_team` 当前更硬的消费面在 bizops / data-quality 侧，而不是 marketing attribution 主链。 |
| 当前最稳读法 | Opportunity 的大头仍是 `pack parity` 和 `activation-state mismatch`，不是 substrate 缺失；真正的 CM 边界还是 `OpportunityTrigger` 以及可能残留在 trigger/runtime 的行为。 |

#### `Invoice_Collection__c`

| 维度 | 当前最稳结论 |
|---|---|
| Salesforce 现网会做什么 | 这条线现在已经不是黑盒。历史回归证据已恢复出 4 条高置信 live Flow：`Collection_Set_PLG_BD_Pool`、`Collection_Amount_and_Payable_Amount_exc_tax`、`Collection_Amount_and_Payable_Amount_exc_tax_Update`、`Cloud_Registration_Source_from_Org_to_Collections`。它们分别在 live 里维护 pool carry-over、exc-tax payable/collections helper，以及从 `Org__c` 到 collections 的 cloud-registration / marketplace carry-over。 |
| CM 目前已支持 | 本地 `Invoice_Collection__c` 已有不少公式/rollup，覆盖 `Collections_Amount_USD__c`、`Payment_Status__c`、`Uncollected_Amount__c` 一类 numeric/status helper；`Actual_Billing_Date__c` 的 validation parity 也已存在。并且本地 `Order` 端已经有按 `CollectionsStatus__c = 'Collected'` 过滤的 IC rollup。 |
| CM 当前主要差异 / 风险点 | 上面 4 条 exact-name Flow 当前本地都没找到；`Invoice_Collection__c.Name` auto-number 仍缺。更关键的是，这里的主要缺口已经可以收敛为 `carry-over / status-transition / helper-field parity`，而不是“CM 不会算金额公式”。 |
| 直接打到哪些字段 / 模型 | 最直接命中的字段是 `plg_bd_pool_c`、`collections_amount_exc_tax_c`、`collections_amount_usd_exc_tax_c`、`payable_amount_usd_2_exc_tax_c`、`marketplace_c`、`collections_status_c`、`invoice_status_c`、`cash_collected_c`。对应模型先从 `stg_salesforce_invoice_collection` 开始，再外溢到 `salesforce_orders`, `salesforce_order_daily_view`, `salesforce_org_monthly_revrec`, `cp_order_monthly_revrec` 和 recurring finance outputs。按当前证据，这类 Flow parity 对 finance 指标的优先级高于 `Name` auto-number parity。 |
| 当前最稳读法 | `Invoice_Collection__c` 目前最像 `finance parity backlog`，不是 `CM 平台空白`。更准确地说，是 `本地已有公式/rollup substrate，但 live 的 carry-over / collected-timing / payable helper Flow 还没补齐`。 |

#### `Order`

| 维度 | 当前最稳结论 |
|---|---|
| Salesforce 现网会做什么 | 不只是生成 `OrderNumber`。现网还维护 order-to-org/account carry-over、PLG pool、`cloud_order_type`、服务窗口、递延/确认收入聚合，以及激活时的 contract gating。当前 live 侧已知缺失名里最关键的是 `Order_Org_Auto_Set_Account_Create`、`Order_Org_Auto_Set_Account_Update`、`Order_Set_PLG_BD_Pool`、`contractOpportunityInset`。 |
| CM 目前已支持 | 本地已经有 `OrderNumber` auto-number、重公式/rollup、12 条 active validation、`Std_CreateOrderFromQuote`、`Order_Quote_Payment_Field_Inheritance`、`Order_Default_RevRec_Entity`。而且 PingCAP 本地已经用 account-level governing-contract policy 取代了旧的 `Order.ContractId`-authoritative 检查，所以 `Quote -> Order` 核心字段继承和一大块 finance substrate 不是空白。 |
| CM 当前主要差异 / 风险点 | 上面 4 条 live Order Flow 仍未迁；`OrderTrigger` 仍是 runtime boundary。`Order_Create_Requires_Effective_CSA_MA_Contract` 不能简单读成“少了一条 validation”，它更像已被本地 policy 有意替代。4 条 `Order_Activate_*` local inactive 也更像 intentional replacement，不是 accidental gap。 |
| 直接打到哪些字段 / 模型 | 最直接命中的字段是 `accumulate_revenue_to_org_tenant_id`、`order_status`、`order_product_family`、`order_service_start_date`、`order_service_end_date`、`revenues`、`accumulated_revenue`、`order_net_fees`。对应模型包括 dbt `salesforce_orders`, `salesforce_order_daily_view`, `salesforce_order_current_monthly_arr`, `cp_order_monthly_revrec`, `salesforce_org_monthly_revrec`, `dws_salesforce_arr_summary`。如果 carry-over 漂了，最先坏的往往不是一个页面字段，而是 tenant/account 对齐和 revrec allocation。 |
| 当前最稳读法 | `Order` 这条线是 `finance parity + intentional policy replacement + residual trigger boundary` 的混合体。当前最该先补的是 carry-over / pool / org-account linkage Flow，不是先把所有 contract-era 旧规则按名字回填。 |

#### `Revenue__c`

| 维度 | 当前最稳结论 |
|---|---|
| Salesforce 现网会做什么 | 现网会自动生成 `Name`，并维护 `revenue_date`、`revenue_status`、`amount_before_adjust`、`amount`、`credit_amount`、exchange-rate 以及与 Order/Org 侧拼接的 revenue history。当前已恢复出的高价值 live 机制是 `RevRec_Set_PLG_BD_Pool`，另外 `RevenueTrigger` 仍承担一部分 runtime 行为。 |
| CM 目前已支持 | 本地 `Revenue__c` 已有 14 条公式；`RevRec_Account`、`RevRec_Partner_Name` 已有；finance 链路也已经在用 `salesforce_revrec` -> `salesforce_orders` -> `salesforce_order_daily_view` / `cp_order_monthly_revrec` 这条聚合路径。`dbt-dev` 当前 `salesforce_revrec.sql` 还直接把 `stg_salesforce_revenue` 投成 `revenue_name`、`revenue_date`、`revenue_status`、`amount_before_adjust`、`amount`、`credit_amount`、`revenue_exchange_rate`。也就是说 revenue 不是“没有对象支持”，而是下游已经真实依赖它。 |
| CM 当前主要差异 / 风险点 | `Revenue__c.Name` auto-number 缺失；`RevRec_Set_PLG_BD_Pool` Flow 缺失；`RevenueTrigger` 仍是 runtime boundary。这里要特别分清两层：`Name` 和缺失 Flow 属于 parity backlog，`RevenueTrigger` 才更像真实平台边界。 |
| 直接打到哪些字段 / 模型 | 直接命中的字段是 `revenue_name`、`revenue_date`、`revenue_status`、`amount_before_adjust`、`amount`、`credit_amount`、`revenue_exchange_rate`。它们先进 dbt `salesforce_revrec`，再被 `salesforce_orders` 聚成 nested `revenues`，继续进 `salesforce_order_daily_view`、`cp_order_monthly_revrec`、`salesforce_org_monthly_revrec`。更往下会先打到 `monthly_revrec_orders.revenue_amount`、`credit_amount`、`adjusted_revenue_amount` 和 category revenue splits；当前 live 使用面更像 `xiaopeng.zhu@pingcap.com` / `fanfei.kong@pingcap.com` 的 recurring-revrec direct-query，而不是独立 revenue dashboard。 |
| 当前最稳读法 | `Revenue__c` 同时含有 `迁移缺口` 和 `真实运行时边界`。如果目标是先止住 `gcp-digital-bi` finance 漂移，优先级通常是先补 `RevRec_Set_PLG_BD_Pool` 和 `Name`，再把剩余 `RevenueTrigger` 逻辑单列成 runtime 项。 |

#### `Account / Org__c`

| 维度 | 当前最稳结论 |
|---|---|
| Salesforce 现网会做什么 | 这条 shared-dimension 链维护的是 `AccountID`、`Region`、`Segmentation`、`ICP`、`TenantStatus`、`TiDBCloudPortalID`、tenant-account bridge 和 `accumulate_revenue_to_org_tenant_id`。`Org__c` 现网里有 `Org_Set_Account` 这种 tenant/account bridge flow；`Account` 侧当前已知缺失名则集中在 `Account_Contract_Valid_Message`, `Account_Contract_Valid_Message_1`, `Account_Current_Order_Type`, `Account_Partner_Sales_Owner_Set`。 |
| CM 目前已支持 | 本地已经有 `Account_ID__c` auto-number、Account 公式/rollup、`Account_status_Flow`、first-order/date maintenance；`Org__c` 侧已有 active 的 `Org_Set_Account`。而且 `dbt-dev` 里 `salesforce_orgs.sql` 会把 `tenant_id -> account_id -> accumulate_revenue_to_org_tenant_id` 显式投出来，`dim_tenant.sql` 会再把 `cloud_tenants + salesforce_orgs + salesforce_accounts` 拼起来，`customer_surrogate_keys.sql` / `customers.sql` 也继续把 account 与 tenant 聚成统一 customer 视角。当前 live schema 已直接坐实：`dwh_business_operations.salesforce_accounts` 带 `account_id`、`account_number`、`fy26_icp`、`fy26_segmentation`、`industry`、`owner_user_id`、`region`、`vertical`；`anls_business_operations.dim_org` 带 `tenant_id`、`account_id`、`accumulate_revenue_to_org_tenant_id`、`org_name`；`anls_core.dim_customer` 带 `customer_surrogate_key`、`salesforce_account_id`、`salesforce_account_number`、`tenant_ids`、`region`、`is_billing_capable`；`anls_cloud.dim_tenant` 带 `tenant_id`、`tenant_name`、`org_name`、`account_name`、`tenant_email`、`tenant_email_domain`。所以 shared-dimension substrate 不只是 repo 里有 lineage，而是前台表也已经把这些关键 join 列真实跑出来了。 |
| CM 当前主要差异 / 风险点 | 4 个 live Account Flow 仍未迁；`AccountTrigger` 仍是 runtime boundary。`Org__c` 本身这轮没有看到明显 object-specific parity hole，但 Order/Revenue/Invoice 的 carry-over 缺口会反向污染 account/tenant 维表，所以这条链不能只看 `Account` / `Org__c` 自身定义。 |
| 直接打到哪些字段 / 模型 | 最直接命中的字段是 `AccountID`、`Industry`、`Region`、`Segmentation`、`TenantStatus`、`TiDBCloudPortalID`、`tenant_ids`、`customer_surrogate_key`、`accumulate_revenue_to_org_tenant_id`。更细一点，当前 live front-door 表已经能直接点到：`salesforce_accounts.account_id/account_number/fy26_icp/fy26_segmentation/industry/owner_user_id/region/vertical`，`dim_org.tenant_id/account_id/accumulate_revenue_to_org_tenant_id/org_name`，`dim_customer.customer_surrogate_key/salesforce_account_id/salesforce_account_number/tenant_ids/region/is_billing_capable`，`anls_cloud.dim_tenant.tenant_id/tenant_name/org_name/account_name/tenant_email/tenant_email_domain`。对应模型包括 Looker `crm_account`, `cloud-lead-pipeline-insight` 和 dbt `salesforce_accounts`, `dim_account`, `dim_tenant`, `salesforce_orgs`, `customer_surrogate_keys`, `customers`, `salesforce_org_monthly_revrec`。报表面现在也能更具体地区分两层：一层是 account/forecast/current-month MRRARR governed surface，例如 `report_id = 673c89ef-fb02-4303-a9a2-5519a652051c`、`2128769b-9f86-4c7a-a9f4-8cc7491868e3`、`58339683-7a7a-4bb6-91bd-14b149572ac9`，它们当前 query snippet 已经直接点到 `account_number`、`fy26_icp`、`fy26_segmentation`、`account_id`、`account_name`、`account_industry`、`account_segmentation`、`region`、`tenant_id`；另一层是 cloud tenant bridge surface，`model_tidbcloud.dws_cloud_tenants_basicinfo` 自己被多个 `Looker Studio` report 直接消费。反过来，这轮还没看到 `dim_customer`、`dim_org`、`anls_cloud.dim_tenant` 被 `Looker Studio` 直接命中，所以它们当前更像稳定 identity front door，而不是命名 dashboard 的第一接触面。 |
| 当前最稳读法 | `Account / Org__c` 不是“对象自己坏了就自己报错”的类型，而是 shared-dimension 链。最该读成 `Account Flow parity + Org bridge already covered + Order/Revenue carry-over back-propagation`。并且这条 shared-key 现在已经不只打 account/customer 维表，还会经 `model_tidbcloud.dws_cloud_tenants_basicinfo` 进一步外溢到 `PLG / signup funnel` 以及多组 cloud/billing tenant surface。 |

#### `Quote`

| 维度 | 当前最稳结论 |
|---|---|
| Salesforce 现网会做什么 | 现网不只是生成 `QuoteNumber`。它还维护折扣、审批、服务起止、support tier、标准/非标准条款等商业语义，并把这些 quote-side 字段继续喂给机会分析。当前高价值 live gap 已收敛到 2 条缺失 Flow：`Quote_update_nonstandard_conditions_checkbox`、`Quote_update_nonstandard_conditions_checkbox_2`，外加 3 条 live active 但本地 inactive 的 validation：`Customer_s_Hardware_Configuration`、`Details_of_vCPU_Calculation`、`Version_of_TiDB`。 |
| CM 目前已支持 | 本地已经有 `QuoteNumber` auto-number、75 条公式、6 个 rollup、8 条 active validation 和 2 个 Flow。也就是说 quote enrichment 用到的大部分字段和校验 substrate 已经存在，不是“CM 不会处理 quote”。 |
| CM 当前主要差异 / 风险点 | 2 条 live Quote Flow 仍未迁；上述 3 条 validation 已定义但 inactive；`QuoteTrigger` 仍是 runtime boundary。这里的主问题仍是 pack parity 和 activation-state mismatch，而不是对象能力空白。 |
| 直接打到哪些字段 / 模型 | 最直接命中的字段是 `QuoteNumber`、`quote_status`、`discount`、`service_start_date`、`service_end_date`、`technical_support_level`、`db_cloud_support_tier`、`other_nonstandard_terms_and_conditions`。`dbt-dev` 当前 `salesforce_opportunities.sql` 会把 approved quote 的 `quote_service_start_date` / `quote_service_end_date` 单独拉平，并把 quote 明细以 nested `quotes` 数组挂到 opportunity 上。它们不会停在 quote 自己，而是先进入 dbt `salesforce_opportunities` 的 quote enrichment，再外溢到 `dim_opportunity`, `dws_salesforce_arr_summary`, `dws_opportunity_stage_duration`, `dws_data_quality_alerting`，以及后续 order / ARR 语义。更硬一点的 live schema 证据是：`dwh_business_operations.salesforce_opportunities` 和 `salesforce_opportunities_snapshot` 都明确有 `quote_service_start_date` / `quote_service_end_date`；而 `bo.dws_salesforce_pipeline_data_quality_cleanup_detail_v2` 也直接带这两个字段。 |
| 当前最稳读法 | `Quote` 是 `pipeline / commercial enrichment` 链，不是独立报表链。最该先补的是 2 条 nonstandard-term Flow，再做 3 条 validation 的 activation 对齐，最后才轮到 `QuoteTrigger` 这类 runtime 残余。当前更硬的受影响面主要复用 opportunity report family，而且 quote service-window 已经不是“只在底层 enrichment”，而是进入了前台 pipeline/data-quality cleanup 面。 |

#### `CampaignMember`

| 维度 | 当前最稳结论 |
|---|---|
| Salesforce 现网会做什么 | 现网持续维护 response / involvement / first-touch / last-touch 语义，并通过 `first_responded_date`、`campaign_member_status`、`has_responded`、`is_contact_involved`、`contact_involvement_level` 把 campaign touch 变成 attribution 输入。当前最明确的 live gap 是 `Campaign_Member_Key_Message_Update`，另外 `Trigger_CampaignMember` 仍在 live runtime。 |
| CM 目前已支持 | 本地已有 34 条公式，以及 4 条 first/last-touch maintenance Flow：`Lead_Set_First_And_Last_CampaignMember`、`Lead_Set_First_And_Last_CampaignMember_delete`、`Contact_Set_First_And_Last_CampaignMember`、`Contact_Set_First_And_Last_CampaignMember_delete`。下游本地模型也已经真实计算 `attribution_percentage`、`attributed_acv`、`attributed_arr`。 |
| CM 当前主要差异 / 风险点 | 1 条 live Flow 仍未迁：`Campaign_Member_Key_Message_Update`；`Trigger_CampaignMember` 仍是 runtime boundary。当前最稳动作不是大范围猜测，而是先把这 1 条已知 Flow 补齐，再看还有多少残余确实只能由 trigger 承担。 |
| 直接打到哪些字段 / 模型 | 最直接命中的字段是 `first_responded_date`、`campaign_member_status`、`has_responded`、`is_contact_involved`、`contact_involvement_level`，然后会继续影响 `salesforce_campaign_attributions.attribution_percentage`、`dws_campaign_attribution.attributed_acv`、`attributed_arr`。对应模型包括 dbt `salesforce_campaign_members`, `salesforce_campaign_attributions`, `salesforce_campaign_attribution_details`, `dws_campaign_attribution`, `dws_campaign_attribution_details`, `dws_lead_timeline`, `dws_icp_summary`。更硬一点的 live schema 证据是：`dwh_marketing.salesforce_campaign_members` 明确带 `first_responded_date`、`campaign_member_status`、`has_responded`、`is_contact_involved`、`contact_involvement_level`；而 front-door `dws_campaign_attribution` / `dws_campaign_attribution_details` 直接带 `attributed_arr`、`campaign_name`、`campaign_region`、`contact_name`、`contact_response_date`、`is_contact_primary`、`opportunity_name`。 |
| 当前最稳读法 | `CampaignMember` 是 `attribution weight engine`，不是只有 CRM 页面展示。它当前属于 `小规模迁移缺口 + 明确 runtime 边界`：先补 `Campaign_Member_Key_Message_Update`，价值已经很高。当前最硬的报表证据也不再只是“有人查 attribution 表”，而是 front-door attribution 表本身就把 response / contact / opportunity 语义直接展开了。 |

#### `Opportunity_Product__c` / `Order_Product__c` / `Quote_Product__c`

| 维度 | 当前最稳结论 |
|---|---|
| Salesforce 现网会做什么 | 这三个 custom line-item 对象现网都会 auto-number `Name`，并通过 trigger / helper 维护 `product_family`、`net_fees`、`list_price`、`service_start_date`、`service_end_date`、man-day / surplus 等产品明细语义。`Order_Product__c` 现网还有 active validation。 |
| CM 目前已支持 | 本地三个对象都有公式；`Order_Product__c` 还有 1 个 rollup 和 1 条 matching validation。当前仓库还已有多条 line-item 侧本地机制或历史命名面，例如 `OpportunityLineItem_Net_Fees_Autocalc`、`OpportunityLineItem_ListPrice_Autofill_From_Pricebook`、`OpportunityLineItem_Product2_Autofill_From_Pricebook`、`QuoteLineItem_Net_Fees_Autocalc`。同时 `dbt-dev` 当前 `salesforce_opportunity_products.sql` 已明确把 `product_family`、`net_fees`、`service_start_date_c`、`service_end_date_c` 投出来，`salesforce_opportunities.sql` 又会把这些字段聚成 `overall_start_date`、`same_product_overall_start_date`、`same_product_overall_end_date`。 |
| CM 当前主要差异 / 风险点 | 三个对象的 `Name` auto-number 当前都没补；三者 trigger-only 逻辑仍留在 live Salesforce。这里是很典型的 `迁移缺口 + 真实 runtime boundary` 双重结构。 |
| 直接打到哪些字段 / 模型 | 最直接命中的字段是 `opportunity_product_name`、`order_product_id`、`product_name`、`product_code`、`net_fees`、`service_start_date`、`service_end_date`、`product_family`。对应模型包括 dbt `salesforce_opportunity_products`, `salesforce_opportunities`, `salesforce_orders`, `salesforce_order_daily_view`, `cp_order_monthly_revrec`，以及 quote/order/product-family 相关下游分析。当前更硬的消费面拆成两层：`report_id = 0f2ad8b8-a0a5-40e1-842a-f208c6247c0b` 这类面仍可作为 `lineage-backed secondary consumer` 来证明 `opportunity_product_family` 会进入 `dws_opportunity_stage_duration` 和 `dws_opportunity_stage_conversion_rates`；而更硬的 live report-backed surface 仍主要是 `report_id = 58339683-7a7a-4bb6-91bd-14b149572ac9`、`837f6250-3c3d-44b9-af6f-4db9aeb30a94`、`df532c1a-ba9a-44b1-aa56-50b6b0869591`、`f9c4bd70-8ce4-487c-abb1-5518ffffd6bd` 这组 finance/ARR 面里的 `order_product_family`、`arr_usd_cd_rate_current_month`、`mrr_usd_cd_rate_finance`。 |
| 当前最稳读法 | line-item 三个对象不是“边角料”，它们是 service-window / product-family / net-fee 这条明细链。最容易先止血的是补 3 个 `Name` auto-number；真正更重的部分是把仍留在 trigger 里的产品明细逻辑改写出来。按当前报表面，`Opportunity_Product__c` 更先在 opportunity stage-duration / stage-conversion / product-family 分析里露头，`Order_Product__c` 更先在 ARR/MRR/revrec 面里露头，`Quote_Product__c` 则更多是通过 quote enrichment 间接渗进 opportunity family。 |

#### `Contract`

| 维度 | 当前最稳结论 |
|---|---|
| Salesforce 现网会做什么 | 现网会自动生成 `ContractNumber`，并维护 `status`、`approval`、`effective date` 这类合同治理语义。当前审计里已经明确看到 2 条 live Flow：`Auto_Expire_Contract`、`Contract_Update_Account_Contract_Valid`，另外 contract trigger 仍承担一部分 live runtime 行为。 |
| CM 目前已支持 | 本地已经有 `ContractNumber` auto-number、4 条公式、1 条 active validation、2 条本地 Contract Flow：`Contract_Archived_Status_Autopromote`、`Std_ContractActivateStamp`。也就是说合同对象在本地不是“完全没接”。 |
| CM 当前主要差异 / 风险点 | 2 条 live Contract Flow 当前未在本地看到；contract trigger 仍是 runtime boundary。相比主交易链，这条的 gap 更像 governance semantics 和 contract-valid flag 维护，而不是直接的前台业务流转缺口。 |
| 直接打到哪些字段 / 模型 | `Contract` 目前不是 headline mart，但 `contract_id` 会继续流进 `salesforce_opportunities`, `stg_salesforce_order`, `stg_salesforce_quote`, `stg_salesforce_revenue`, `stg_salesforce_invoice_collection`；`salesforce_opportunities.sql` 也直接保留了 `contract_id` / `contract_archived_date`。更硬一点的 live schema 证据是：`dwh_business_operations.salesforce_opportunities` 和 `salesforce_opportunities_snapshot` 都明确带 `contract_id` / `contract_archived_date`。所以它最先影响的是 contract-governed order / service-period / finance governance 分析，而不是单独一张 CRM 报表。当前更稳的主 consumer 仍是复用 `1733...` / `837...` 这组主 `Opportunity / ARR / data-quality` family；`aadb4637-a4be-41e0-a045-8df92303e595`、`0f2ad8b8-a0a5-40e1-842a-f208c6247c0b`、`d9161f0e-f04c-49dc-82e1-053ab508ce67` 现在更适合作为 secondary lineage consumer，而不是单独的 contract dashboard。 |
| 当前最稳读法 | `Contract` 是 cross-object governance key。它值得补，但优先级通常低于 Opportunity/Order/Revenue 主链；更像“合同治理语义 drift”，不是最先炸 BI 指标的那一层。当前最需要保留的边界是：它确实已经进了前台机会快照/机会分析字段，但仍是作为 cross-object governance 列位间接显影，而不是 contract 自己先报错。 |

#### `Contact`

| 维度 | 当前最稳结论 |
|---|---|
| Salesforce 现网会做什么 | 现网至少还有 1 条 active Flow，外加 4 条 active Apex triggers；当前审计把它概括成 owner/internal/cloud 默认值和部分 region/account helper 维护。虽然对象本身不是主交易核心，但它会参与 lead/contact merge、campaign interaction 和 attribution stitching。 |
| CM 目前已支持 | 本地已有 5 条公式；Contact 基础对象和下游拼接模型都在。并且从 attribution 链看，本地已经有 `Contact_Set_First_And_Last_CampaignMember*` 这一组 contact-adjacent Flow，说明 Contact 并不是完全脱离 campaign/lead 语义。`dbt-dev` 当前 `salesforce_contacts.sql` 已直接输出 `contact_id`、`account_id`、`contact_name`、`email`、`status`；`salesforce_campaign_interacted_accounts.sql` 还会把 lead-only campaign member 借 `Lead.converted_contact_id` 转成 contact，再 join 回 `account_id`。 |
| CM 当前主要差异 / 风险点 | live Contact Flow 当前还没在 pack 中看到；Contact trigger surfaces 仍是 runtime boundary。这里证据没有主交易链那么细，但已经足够说明 Contact 仍存在 automation parity hole。 |
| 直接打到哪些字段 / 模型 | 最先影响的不是“contact 自己报表”，而是 dbt `salesforce_contacts`, `salesforce_leads`, `dim_lead`, `salesforce_campaign_interacted_accounts`, `dws_campaign_attribution`, `dws_campaign_attribution_details`, `dws_lead_timeline` 这类 lead/contact blended 模型。当前已经能点到一个很具体的 governed consumer：`report_id = 8c6f30a4-c6fe-4536-ac62-d937d0176ebd` 会打 `dws_campaign_attribution_details`，字段片段里明确有 `contact_name`、`contact_response_date`、`is_contact_primary`；更硬一点的 schema 证据是 `dws_campaign_attribution` / `dws_campaign_attribution_details` 本身就带 `contact_name`、`contact_response_date`、`is_contact_primary`、`campaign_name`、`campaign_region`、`opportunity_name`；`report_id = fd12e3fc-d36f-4cc5-b2d9-9ed2808489dc` 则会复用 `dws_lead_timeline` 和 `anls_marketing.dim_lead`，所以 contact 偏差会先表现成 stitching / attribution join 漂移，而不是 contact 对象单报表。 |
| 当前最稳读法 | `Contact` 是 lead/contact stitching 边缘链。它的价值不在于单对象曝光，而在于一旦 contact 侧默认值或 trigger 语义不对，会把 lead timeline、campaign attribution、interacted-account 这几条链一起带歪。当前最硬的报表信号已经不是泛指“marketing mart”，而是 attribution report `8c6f30a4-c6fe-4536-ac62-d937d0176ebd` 和 lead/ICP report `fd12e3fc-d36f-4cc5-b2d9-9ed2808489dc`，并且 attribution front-door 表的字段名已经能直接把 contact 语义指出来。 |

#### `Campaign`

| 维度 | 当前最稳结论 |
|---|---|
| Salesforce 现网会做什么 | 这轮 live audit 没看到 active Flow / Validation / Apex trigger 级的大 automation surface；更像在维护 `type`、`status`、`active`、`exclude-from-attribution` 这类活动主数据语义。 |
| CM 目前已支持 | 本地已经有 8 个 rollup，基础消费面也比较清楚；`salesforce_campaigns`、`salesforce_campaign_attributions`、`dws_campaign_attribution`、`dws_lead_timeline`、`dws_icp_summary` 这些链已经在消费 campaign 主表。 |
| CM 当前主要差异 / 风险点 | 本轮没有看到明显 object-specific parity gap，也没有看到像 `CampaignMember` 那样的高置信 missing Flow。当前更像 `campaign metadata/hygiene surface`，不是 automation 缺口大户。 |
| 直接打到哪些字段 / 模型 | `Campaign` 最先打到的是 dbt `salesforce_campaigns`, `salesforce_campaign_members`, `salesforce_campaign_interacted_accounts`, `salesforce_campaign_attributions`, `dws_campaign_attribution`, `dws_campaign_attribution_details`, `dws_lead_timeline`, `dws_icp_summary`。但要注意：这里真正高敏感的往往不是 Campaign 主表本身，而是它和 `CampaignMember` / `Opportunity` 一起形成的 attribution context。 |
| 当前最稳读法 | `Campaign` 本身目前没有被证据推成 major gap object。更准确的说法是：Campaign 是 attribution context 的主表，而当前 automation 风险主要落在 `CampaignMember`，不是 `Campaign` 自己。 |

### Marketing Live Warehouse 补证

除了 repo 里的 SQL / LookML 证据，这轮还直接核对了 `2026-07-07` 当前 live warehouse 里的 marketing 表、字段和规模。

这一步把
`对象 -> 哪些 live 字段真的在线`
进一步坐实了。

| live 表 | 当前直接确认到的字段 / 规模 | 这对对象级判断意味着什么 |
|---|---|---|
| `dwh_marketing.salesforce_leads` | `401,564` 行；字段确认有 `lead_mql_timestamp`, `lead_iqm_timestamp`, `lead_status`, `pre_account_region`, `pre_account_segmentation` | `Lead` 这条线当前在 live warehouse 里确实是靠 `lead_mql_timestamp` / `lead_iqm_timestamp` 和 pre-account 维度往下游传播；本轮字段核对没有看到 `date_status_changed` 或 `most_recent_working_status_date`，所以 `Lead_StatusChangeTimestamp` 仍不该过度外推到命名 marketing marts。 |
| `dwh_marketing.salesforce_campaign_members` | `713,226` 行；字段确认有 `first_responded_date`, `campaign_member_status`, `has_responded`, `is_contact_involved`, `contact_involvement_level` | `CampaignMember` 不是只在 repo SQL 里“理论上重要”，这些 attribution 前置字段在 live warehouse 里都真实存在。 |
| `dws_marketing.dws_campaign_attribution` | `1,045` 行；字段确认有 `attribution_percentage`, `attributed_acv`, `attributed_arr`, `campaign_name`, `opportunity_name`, `segmentation` | `CampaignMember` / `Opportunity` 的归因语义已经不只是中间层，而是已经落成最终归因金额和分群字段。 |
| `dws_marketing.dws_icp_summary` | `1,861` 行；字段确认有 `first_touch_campaign`, `last_touch_before_iqm`, `last_touch_before_opp_creation`, `iqm_campaign_touches`, `opp_campaign_touches`, `mapped_stage_name` | `Lead + CampaignMember + Opportunity` 的组合会直接改写 ICP 路径分析，而不是只影响一张 attribution 明细表。 |
| `dws_marketing.dws_lead_timeline` | `734,525` 行；当前事件类型至少有 `campaign_interaction = 584,191`, `mql_milestone = 136,173`, `icp_campaign_interaction = 13,343`, `iqm_milestone = 818` | `Lead`、`CampaignMember`、`Opportunity` 的时间戳和互动语义确实已经在 live 里展开成 timeline 事件，不只是设计上的 intended output。 |
| `anls_marketing.dim_lead` | `2,929,519` 行；字段确认有 `lead_surrogate_key`, `salesforce_account_id`, `salesforce_contact_ids`, `salesforce_lead_ids`, `first_touch_source_channel`, `sign_up_source_channel`, `region` | `Lead / Contact / Account` 的 stitching 结果已经被用在一个更宽的 marketing 分析维表里，所以 `Contact` 和 lead-account 关联问题不会只停在 CRM mart。 |

这一轮的实际收敛是：

- marketing 侧现在已经不只是
  `repo lineage 很强`
- 我们也能直接点出
  `当前 live 表里到底有哪些字段和多少行`
- 组织级作业元数据还进一步证明了
  `2026-07-01` 之前的真实 direct-query signal：
  `yiming.wang@pingcap.com`
  在
  `2026-01-08` 到 `2026-06-25`
  之间多次直接引用
  `gcp-digital-bi.dws_marketing.dws_icp_summary`
  （`364` 次）、
  `gcp-digital-bi.dws_marketing.dws_lead_timeline`
  （`8` 次）、
  `gcp-digital-bi.dwh_marketing.salesforce_leads`
  （`54` 次）、
  `gcp-digital-bi.anls_marketing.dim_lead`
  （`114` 次）；
  `alfred.wang@pingcap.com`
  也在
  `2026-03-25`
  直接引用过
  `gcp-digital-bi.dws_marketing.dws_lead_timeline`
  进一步复核
  `region-us-west2`
  的 project-level `JOBS_BY_PROJECT`
  后，
  `Campaign Attribution`
  这条线也补到了一条更硬的 direct-query 证据：
  `yiming.wang@pingcap.com`
  在
  `2026-06-23`
  直接查询了
  `gcp-digital-bi.dws_marketing.dws_campaign_attribution`
  ，而且查询里明确点到了
  `attributed_arr`,
  `campaign_name`,
  `campaign_region`,
  `contact_response_date`,
  `opportunity_created_date`,
  `opportunity_name`
  等字段
- 但 owner/dashboard 这层仍然比 finance 弱，所以 marketing 现在最稳的证据组合是
  `repo lineage + live warehouse fields + direct-query signal`
  ，而不是
  `完整 dashboard registry`
- 不过最该保留的边界也变了：
  attribution 现在已经有
  `live table/field + direct query`
  证据，
  真正还弱的是
  `dashboard / owner / governed consumer surface`
  这一层，
  而不是
  `有没有真实人直接查过这张表`

### 再往下一层：当前源码已经能直接解释这些字段为什么会进报表

这轮把 `pingcap-inc/dbt-dev` 和 `pingcap-inc/digital-bi-discovery` 重新拉了一遍以后，
`Lead` / `CampaignMember` / `Opportunity` / `Invoice_Collection__c`
对报表的作用链已经不只是
`名字像会用到`
，
而是可以直接从源码层看到：

| 资产 | 当前直接看到的逻辑 | 对对象级判断的新增意义 |
|---|---|---|
| `dbt-dev/models/digital_bi_dbt/warehouse/marketing/salesforce_leads.sql` | 把 `stg_salesforce_lead` 和 `stg_salesforce_contact` 合并，显式产出 `lead_mql_timestamp`、`lead_iqm_timestamp`、`pre_account_region`、`pre_account_segmentation`、`lead_status` | `Lead` 不是只影响一个 mart 名字；它在 warehouse 层就已经把 lead/contact 合并成下游营销主键输入。 |
| `dbt-dev/models/digital_bi_dbt/analytics/marketing/dim_lead.sql` | 把 `salesforce_leads`、`salesforce_accounts`、GA4 pseudo leads、cloud tenant users 和 `sign_up_complete` 事件拼成统一 `lead_surrogate_key`，产出 `first_touch_source_channel`、`sign_up_source_channel` | `Lead` / `Contact` / `Account` 的偏差会继续污染 signup / acquisition stitching，不只是 `Lead Funnel`。 |
| `dbt-dev/models/digital_bi_dbt/marts/marketing/dws_lead_timeline.sql` | 从 `salesforce_leads`、`salesforce_opportunities`、`salesforce_campaign_members`、`salesforce_campaigns` 生成 `mql_milestone`、`iqm_milestone`、`pipeline_created`、`customer_milestone`、`campaign_interaction` | `Lead + CampaignMember + Opportunity` 的组合影响已经在模型里被显式展开成 timeline 事件，不是推测。 |
| `dbt-dev/models/digital_bi_dbt/marts/marketing/dws_icp_summary.sql` | 直接从 `dws_lead_timeline` 统计 `first_touch_campaign`、`last_touch_before_iqm`、`last_touch_before_opp_creation`、`iqm_campaign_touches`、`opp_campaign_touches`，并联到 `salesforce_opportunities` / `salesforce_accounts` | `CampaignMember` / `Lead` / `Opportunity` 的语义会直接改写 ICP 路径和 opportunity 分群，不只是 attribution 明细表。 |
| `dbt-dev/models/digital_bi_dbt/warehouse/marketing/salesforce_campaign_members.sql` | 把 `campaign_member_status` 映射成 `is_contact_involved` / `contact_involvement_level`，并在 involved 但缺 `first_responded_date` 时做回填 | `CampaignMember` 的状态维护不是 cosmetic 字段；它就是后面 attribution 和 timeline 的前置条件。 |
| `dbt-dev/models/digital_bi_dbt/marts/marketing/dws_campaign_attribution.sql` | 用 `salesforce_campaign_attributions.attribution_percentage` 去乘 `accurate_acv_amount` 和 `arr_amount_usd`，直接产出 `attributed_acv`、`attributed_arr` | `CampaignMember` / `Opportunity` 差异会直接进金额归因，不是停在行为事件层。 |
| `digital-bi-discovery/notebooks/data_discovery/marketing/02_campaign_attribution_discovery.ipynb` 与 `marketing/attribution_app/backend/attribution_engine.py` | 直接用 `salesforce_opportunities`、`salesforce_campaign_interacted_accounts`、`stg_salesforce_opportunity_contact_role` 去做 campaign-opportunity link、contact-role weighting、最终 attribution weight 归一化 | `Campaign Attribution Tuner` 不是空壳；它就是 analyst-facing 的归因实验面，直接放大 `CampaignMember` / `Opportunity` 的差异。 |
| `digital-bi-discovery/notebooks/data_discovery/bo/1_opportunities.ipynb` | 明确把 `gcp-digital-bi.salesforce.opportunity*`、`account`、`order`、`quote` 作为数据源，直接讨论 `stage_name`、`next_milestone_c`、`key_updates_c` 等 pipeline 语义 | `Opportunity` 这条线有真实的业务分析入口，不只是仓库里“有张表”。 |
| `dbt-dev/models/digital_bi_dbt/staging/salesforce/stg_salesforce_invoice_collection.sql` | 已明确暴露 `collections_status_c`、`collections_amount_c`、`cash_collected_c`、`marketplace_c`、`plg_bd_pool_c`、`payable_amount_usd_2_exc_tax_c` 等字段 | `Invoice_Collection__c` 对 finance 的影响已经在 staging/source 层坐实，不是只剩名字猜测。 |
| `dbt-dev/models/digital_bi_dbt/warehouse/business_operations/salesforce_orders.sql` | 当前源码会声明 `invoice_collection` CTE，但最终 `SELECT` 还没有把该 CTE 真正并进输出 | 这进一步说明 `Invoice_Collection__c` 当前最硬的 consumer surface 仍然是 staging/source 和 recurring finance outputs，而不是一个已经完整 join IC 的主 order mart。 |

这也让当前优先级更清楚了：

- `Lead`：先盯 lifecycle / account-linkage / sign-up stitching 的语义一致性。
- `CampaignMember`：先盯 `first_responded_date` / involvement / attribution 前置状态。
- `Opportunity`：先盯 pipeline / ACV / ARR / owner-team 语义。
- `Invoice_Collection__c`：先盯 source/staging 和 recurring finance outputs，不要过度假设 `salesforce_orders` 已把 IC 明细完全吃进去。

### 两个新的收敛点：PLG 主要吃 Account/Tenant，不是直接吃 Lead；collections 也不是单链

#### `PLG / signup funnel`

这轮把 `model_plg` 和 live `JOBS_BY_PROJECT` 一起对完以后，
当前最稳结论已经比前面更窄：

- `report_id = 690c8087-0697-4272-b05e-2ee37d728c15`
  是一条真实存在的 `Looker Studio` PLG 报表面。
- 它直接查询的是
  `gcp-digital-bi.model_plg.dws_tidb_cloud_marketing_funnel_1_to_3_stage_new_users_monthly_group`
  和一组 cloud signup / billing-capable user 明细表。
- 从 live job metadata 看，
  这条 report 在当前证据窗口里至少带了 6 个 datasource：
  `dws_tidb_cloud_marketing_funnel_1_to_3_stage_new_users_monthly_group`、
  `dws_daily_external_cloud_signup_active_engaged_billingcapable_user_count`、
  `dws_daily_external_cloud_billing_capable_user_detail_2023_to_day`、
  `dws_daily_external_cloud_billing_capable_user_weekly_accumulated_count`、
  `...last28days`、
  `...last90days`。
  当前观察到的 `looker_studio` 命中都集中在
  `2026-01-28`
  这一天，
  说明它更像一组固定的 PLG/signup consumer surface，
  而不是我们这次临时从 repo 名字外推出来的假链路。
- 这条 funnel SQL 自己只是把三段模型 union 在一起：
  `marketing traffic UV`
  、
  `DBaaS GA4 UV`
  、
  `TiDB Cloud Signup`
  。
- live schema 也已经把这条 funnel 的前台字段面坐实：
  `model_plg.dws_tidb_cloud_marketing_funnel_1_to_3_stage_new_users_monthly_group`
  直接带
  `year_month`,
  `traffic_funnel_type`,
  `traffic_funnel_number`,
  `user_source`,
  `utm_source`,
  `landing_page_for_uv`,
  `community_channel`,
  `region`,
  `breakdown_region_and_community_channel_or_not`,
  `internal_for_signup`,
  `new_users_count`
  。
- `TiDB Cloud Signup` 那条链继续往下读，
  主要来自
  `dws_cloud_tenants_basicinfo`
  +
  `Mixpanel`
  +
  `GA`
  ，不是直接引用
  `Lead`
  /
  `Contact`
  /
  `dim_lead`。
- 但这里有一个重要的 CRM 接口：
  `dws_cloud_tenants_basicinfo`
  会把
  `dwm_cloud_tenants`
  和
  `salesforce_accounts`
  按
  `account_id = account_number`
  拼起来。
  当前 live schema 已直接坐实它带
  `tenant_id`,
  `tenant_region`,
  `tenant_status`,
  `tenant_email`,
  `tenant_created_at`,
  `tenant_plan`,
  `tenant_lead_id`,
  `account_id`,
  `account_name`,
  `account_industry`,
  `account_segmentation`,
  `account_current_order_type`,
  `account_tam_name`,
  `org_owner_name`,
  `org_owner_email`
  ，所以这条 bridge 不是抽象“会 join 到 account”，而是已经把 tenant/account/owner 语义直接展开到前台了。
- 旁边还有一个更稳定的 tenant identity front door：
  `anls_cloud.dim_tenant`
  当前也直接带
  `tenant_id`,
  `tenant_name`,
  `org_name`,
  `account_name`,
  `tenant_email`,
  `tenant_email_domain`,
  `created_timestamp`
  。
- 更重要的是，
  `dws_cloud_tenants_basicinfo`
  现在已经不只是 repo 里被别的 SQL 依赖的桥表，
  而是一个被 `Looker Studio` 直接消费的 governed surface。
  从
  `2026-01-01`
  到当前窗口，
  它至少直接命中过 5 个 report id：
  `00675e54-cae4-4562-ae95-002a3b22b3d4`,
  `1e22be38-bbfe-4c28-9d7d-596d143c39c5`,
  `31605bff-7555-430c-9377-c26a69be7e49`,
  `eae0ca4f-c747-40ef-b34c-f7f50cb1d1a2`,
  `f9c4bd70-8ce4-487c-abb1-5518ffffd6bd`
  。
  当前 query snippet 还能直接点到这些 surface 在用的字段组合：
  `tenant_id`,
  `tenant_name`,
  `tenant_email`,
  `tenant_region`,
  `tenant_plan`,
  `account_id`,
  `account_name`,
  `account_current_order_type`
  。
- 但这些 direct consumers 的语义并不等于
  `Lead`
  被直接消费。
  目前看，
  它们更多分成
  `tenant/cluster detail`,
  `cloud billing / account-owner`,
  `tenant daily cost alert`,
  `activated-order / revrec account`
  这几类 cloud/billing surface。
  也就是说，
  `dws_cloud_tenants_basicinfo`
  的确把 CRM account/tenant 语义扩散进了 governed 报表，
  但扩散出去的第一波更像
  `cloud/billing tenant monitor`
  ，不是
  `Lead`
  dashboard。
- 如果只按 datasource 组合和字段片段来读，
  这 5 个 report id 当前最像下面几类 surface：
  `00675e54-cae4-4562-ae95-002a3b22b3d4`
  更像
  `tenant / cluster / component detail`
  ，因为最重的 datasource 是
  `dws_cloud_all_clusters_component_detail_basic_info`
  和
  `dws_cloud_tenants_project_cluster_basicinfo`
  ，并伴随
  `tenant_id`,
  `tenant_name`,
  `tenant_region`,
  `tenant_plan`,
  `tenant_email`
  。
  `1e22be38-bbfe-4c28-9d7d-596d143c39c5`
  更像
  `cloud billing / account-owner`
  面，
  因为它主要混合
  `azure_billing*`,
  `dwd_aws_prod_billing_v2`,
  `gcp_monthly_billing_with_support_cost_alloc`
  ，再带
  `account_id`,
  `tenant_id`
  。
  `31605bff-7555-430c-9377-c26a69be7e49`
  更像
  `billing + tenant bridge master surface`
  ，因为它最重的 datasource 直接就是
  `dws_cloud_tenants_basicinfo`
  ，并显式带
  `account_current_order_type`,
  `account_id`,
  `account_name`,
  `tenant_id`,
  `tenant_name`,
  `tenant_plan`,
  `tenant_region`
  ，旁边再叠加大批 billing datasource。
  `eae0ca4f-c747-40ef-b34c-f7f50cb1d1a2`
  更像
  `prod tenant daily cost alert`
  ，因为它和
  `model_billing.dws_monitor_cloud_prod_tenant_daily_cost_alert`
  强绑定。
  `f9c4bd70-8ce4-487c-abb1-5518ffffd6bd`
  更像
  `activated-order / monthly revrec by account+tenant`
  ，因为它把
  `dws_salesforce_activated_order_account_monthly_revrec_v3`
  和
  `dws_cloud_tenants_basicinfo`
  拼在一起，并显式点到
  `order_product_family`,
  `account_current_order_type`,
  `account_id`,
  `account_name`,
  `tenant_id`,
  `tenant_name`
  。
- 这里要保留一个边界：
  这些是基于
  `referenced_tables + query field snippets`
  的业务语义推断，
  不是来自 Google Drive / Looker Studio title 元数据。
  但就“哪类报表会先被 account/tenant bridge 漂移打到”这个问题而言，
  证据已经足够强。

所以当前更稳的说法是：

- `Lead`
  的 repo-visible blast radius，
  目前最硬仍然在
  `dim_lead`
  / `dws_lead_timeline`
  / `dws_icp_summary`
  这条 marketing / stitching 链。
- `PLG / signup funnel`
  当前更像
  `Account / Tenant / cloud user`
  语义面，
  而不是已经能直接坐实成
  `Lead`
  依赖面。更精确地说，它当前更像
  `tenant/account-enriched cloud funnel`
  ，其中 CRM 侧最硬的接口是
  `salesforce_accounts`
  和
  `model_tidbcloud.dws_cloud_tenants_basicinfo`
  ，不是
  `dim_lead`
  本身。
- 进一步说，
  当前最稳的 blast-radius 拆法应该是：
  `Lead`
  仍优先映射到
  `dim_lead / dws_lead_timeline / dws_icp_summary`
  ；
  `Account / Org / tenant bridge`
  则会先映射到
  `dws_cloud_tenants_basicinfo`
  及其直连的
  `cloud billing / tenant monitor / activated-order`
  报表面。
- 这也意味着：
  如果我们后面要继续找
  `Lead -> PLG`
  的更强证据，
  应该优先查
  `dim_lead`
  是否被别的 cloud / PLG 分析面再消费，
  而不是先假设
  `model_plg`
  已经直接吃了 Salesforce lead identity。

#### `Invoice_Collection__c` / collections finance 面

这轮 finance 侧的证据也收敛出一个重要边界：

- `stg_salesforce_invoice_collection`
  当然真实存在，而且字段很全；
  但当前 checked `salesforce_orders.sql`
  只是声明了
  `invoice_collection`
  CTE，
  还没把它 join 到最终输出。
- 与此同时，
  `fp_and_a`
  下面还有一条平行 collections 链：
  `salesforce_collection_rectify`
  ->
  `dwm_salesforce_collection_basic_info_v2`
  ->
  `dws_salesforce_monthly_activated_order_account_collection_detail_v2`
  ->
  `dws_salesforce_activated_order_account_collection_summary`
  ->
  `dwm_salesforce_activated_order_account_collection_finish_status_detail`
  ->
  `aws marketplace` collection-finish-status 汇总。
- 也就是说，
  collections / payable / unpaid 这类 finance 输出，
  当前并不只靠
  `Invoice_Collection__c`
  那一条 dbt staging 链。
- 另外
  `monthly_cloud_billing_revrec.py`
  这条 recurring finance 产物链，
  会直接读取
  `gcp-digital-bi.dwh_finance.salesforce_org_monthly_revrec`
  和
  `gcp-digital-bi.dwh_finance.salesforce_order_daily_view`
  ，再写出
  `sandbox_dwh_ywang.monthly_revrec_collections`
  和
  `monthly_revrec_orders`
  一类表。

从 live 使用面看：

- 暂时没找到
  `Looker Studio`
  直接查询
  `salesforce_order_daily_view`
  /
  `salesforce_org_monthly_revrec`
  /
  `monthly_revrec_collections`
  /
  `monthly_revrec_orders`
  的证据。
  按
  `2026-01-01`
  到当前窗口的
  `JOBS_BY_PROJECT`
  统计，
  这 4 张表的
  `looker_studio`
  直连命中数都是
  `0`
 。
- 但有稳定的 analyst / operator 使用面：
  `xiaopeng.zhu@pingcap.com`
  多次直接查询
  `sandbox_dwh_ywang.monthly_revrec_collections`；
  `fanfei.kong@pingcap.com`
  多次直接查询
  `dwh_finance.salesforce_order_daily_view`
  ，并查询过
  `monthly_revrec_collections_2026_05_recognised`；
  `yiming.wang@pingcap.com`
  在
  `sandbox_nexuscrm_phase1`
  上还实际跑过
  `dws_salesforce_monthly_activated_order_account_collection_detail_v2`
  这条 parity build。

所以当前最稳读法是：

- `Invoice_Collection__c`
  对 finance 的影响是真实的，
  但它现在不是一条
  `stg_invoice_collection -> 唯一主报表`
  的简单链。
- 当前至少有
  `NexusCRM / Salesforce invoice_collection`
  和
  `salesforce_collection_rectify`
  两条 collection 语义面同时存在。
- 如果要判断某个 collections 指标漂移到底是不是
  `CM parity gap`
  造成的，
  下一步必须先确认它来自哪条 collection source。

再往前推进一层，当前已经能点名到几类
`命名分析资产`
，
不只是抽象 mart：

- 私有仓库
  `pingcap-inc/digital-bi-discovery`
  里明确存在
  `notebooks/data_discovery/marketing/01_campaign_discovery.ipynb`
  和
  `02_campaign_attribution_discovery.ipynb`
- 其中
  `01_campaign_discovery`
  的 markdown 直接写明：
  `We would like to inspect the relationships between tables, and have a look at data`
  ，并列出 campaign / campaign_member / contact / opportunity 等 tables of interest
- 同仓库里还有完整的
  `marketing/attribution_app`
  ，README 标题就是
  `Campaign Attribution Tuner`
  ，并明确说它是
  `An interactive web application for tuning campaign attribution weights and visualizing their impact on attribution scores`
- 这个 app 不是空壳：
  backend `attribution_engine.py`
  会直接从 BigQuery 加载
  `dwh_business_operations.salesforce_opportunities`、
  `dwh_marketing.salesforce_campaign_interacted_accounts`、
  `dwh_marketing.salesforce_campaigns`、
  `stg_salesforce.stg_salesforce_opportunity_contact_role`
  来做 campaign-opportunity linking 和 attribution weight 计算
- frontend `App.tsx`
  和
  `AttributionChart.tsx`
  直接暴露
  `Campaign Summary`
  /
  `Opportunity Detail`
  两种视图，
  还会显示
  `Campaign Attribution by Value`

所以现在最稳的 consumer-surface 说法已经能升级成：

- `Lead Funnel / ICP`
  有
  `live mart + direct query + named analysis notebook`
- `Campaign Attribution`
  有
  `live mart + direct query + named notebook + interactive attribution app`
- 真正还弱的只剩
  `governed dashboard owner / official registry`
  这一层
  ，而不是
  `有没有具体分析资产在用`

### `Lead Funnel / Qualification`

最直接受影响：

- Looker `salesforce_lead`
- Looker `cloud-lead-pipeline-insight`
- dbt `salesforce_leads`
- dbt `dim_lead`
- dbt `dws_lead_timeline`
- dbt `dws_icp_summary`

最敏感字段：

- `LeadLifecycleStage`
- `LeadStatus`
- `LeadSource`
- `lead_mql_timestamp`
- `lead_iqm_timestamp`
- `account_id`
- `TenantStatus`
- `TiDBCloudPortalID`

### `Pipeline / Forecast / Opportunity Quality`

最直接受影响：

- Looker `salesforce_oppo`
- Looker `cloud-lead-pipeline-insight`
- dbt `salesforce_opportunities`
- dbt `dim_opportunity`
- dbt `dws_salesforce_arr_summary`
- dbt `dws_opportunity_stage_duration`
- dbt `dws_opportunity_stage_conversion_rates`
- dbt `dws_data_quality_alerting`
- dashboard `Opportunity Data Quality Monitoring`

最敏感字段：

- `forecast_category`
- `forecast_type`
- `stage_name`
- `stage_duration_days`
- `arr_amount_usd`
- `accurate_acv_amount`
- `owner_team`
- `cloud_order_type`
- `quote_service_start_date`
- `overall_start_date`

### `Campaign Attribution / ICP Analysis`

最直接受影响：

- dbt `salesforce_campaign_members`
- dbt `salesforce_campaign_attributions`
- dbt `dws_campaign_attribution`
- dbt `dws_campaign_attribution_details`
- dbt `dws_icp_summary`
- dbt `dws_lead_timeline`

最敏感字段：

- `first_responded_date`
- `campaign_member_status`
- `has_responded`
- `contact_involvement_level`
- `attribution_percentage`
- `attributed_acv`
- `attributed_arr`

这里现在也可以说得更具体了：

- `salesforce_campaign_members.sql`
  会先把 `campaign_member_status` 映射成参与度语义，
  并在缺 `first_responded_date` 时做回填
- `salesforce_campaign_attributions.sql`
  会把 contact/campaign 权重归一成 `attribution_percentage`
- `dws_campaign_attribution.sql`
  再把它乘到 `accurate_acv_amount` / `arr_amount_usd`
  上
- `dws_lead_timeline.sql`
  还会把 `lead_mql_timestamp`、`lead_iqm_timestamp`、
  `Opportunity.created_timestamp`、`launch_date`、
  `CampaignMember.first_responded_date`
  直接变成时间线事件

所以这组不是“只会打歪 attribution dashboard”，而是会同时打歪：

- 归因金额
- lead timeline
- ICP / pre-IQM / pre-opp campaign path 分析

如果继续按对象拆，现在最稳的理解是：

- `Lead`
  先看 lifecycle / `lead_mql_timestamp` / `lead_iqm_timestamp` /
  account-tenant 关联
- `Opportunity`
  先看 forecast / owner-team / ARR-ACV / stage-duration /
  quote enrichment
- `CampaignMember`
  先看 response / involvement / `first_responded_date` /
  attribution weight

### `Order / ARR / RevRec / Collections`

最直接受影响：

- dbt `salesforce_orders`
- dbt `salesforce_order_daily_view`
- dbt `salesforce_order_current_monthly_arr`
- dbt `salesforce_revrec`
- dbt `cp_order_monthly_revrec`
- dbt `salesforce_org_monthly_revrec`
- dbt `dws_salesforce_arr_summary`

最敏感字段：

- `accumulate_revenue_to_org_tenant_id`
- `order_status`
- `order_product_family`
- `revenues`
- `revenue_name`
- `revenue_status`
- `plg_bd_pool`
- `cash_collected_c`
- `payable_amount_usd_2_exc_tax_c`
- `accumulated_revenue`

### `Account / Tenant Linkage / Customer Identity`

最直接受影响：

- Looker `crm_account`
- Looker `cloud-lead-pipeline-insight`
- dbt `salesforce_accounts`
- dbt `dim_account`
- dbt `dim_tenant`
- dbt `salesforce_orgs`
- dbt `customer_surrogate_keys`
- dbt `customers`
- dbt `salesforce_org_monthly_revrec`

最敏感字段：

- `AccountID`
- `Region`
- `Segmentation`
- `TenantStatus`
- `TiDBCloudPortalID`
- `tenant_ids`
- `customer_surrogate_key`
- `accumulate_revenue_to_org_tenant_id`

## 当前最值得先修的三组

1. `Pipeline / Forecast / Opportunity Quality`
2. `Lead Funnel / Qualification`
3. `Order / ARR / RevRec / Collections`

原因不是这三组
`CM 最没能力`
，
而是：

- 报表爆炸半径最大
- 当前证据最强
- 高置信修复项最多
- 很多问题先补 `L2 pack` 就能开始收敛

## 这些报表组在业务上到底在看什么

如果不想只看模型名字，当前能落到的业务问题大概是：

| 报表组 | 业务上实际在看什么 |
|---|---|
| `Pipeline / Forecast / Opportunity Quality` | 机会卡在哪个 stage、卡了多久、forecast 属于哪类、ARR/ACV 多大、有没有过期 close date、service start date 错位、长期没 update 等数据质量问题。 |
| `Lead Funnel / Qualification` | 一个 lead 是怎么走到 `MQL`、`IQM`、建 opp、再到 customer milestone 的；不同 lead/account/opportunity 连接有没有把漏斗时间线打歪。 |
| `Campaign Attribution / ICP Analysis` | 哪些 campaign touch 真正贡献了 opp、ARR、ACV；某类 ICP campaign 是不是更容易在 IQM 前、建 opp 前触达并影响 pipeline。 |
| `Order / ARR / RevRec / Collections` | 订单服务期、累计收入、回款、递延/确认收入、tenant 月度汇总是否对得上；当前月和历史月 revrec 有没有漂。 |
| `Account / Tenant Linkage / Customer Identity` | 一个 account 实际挂了哪些 tenant、收入应该累到哪个 tenant/account、共享的 segmentation / ICP / industry 维度有没有被串歪。 |

这层说法现在不是纯口语概括，而是已经有 repo 里的 model docs / SQL 直接支撑：

- `dim_opportunity.yml`
  把 opportunity 说成
  `stage + forecast + financial + quote + task`
  的综合分析面。
- `dws_opportunity_stage_duration.yml`
  明写在分析机会生命周期和各 stage duration。
- `dws_data_quality_alerting.sql`
  直接定义了
  `Aging`,
  `No Status Update`,
  `Past Due`,
  `Service Start Date Issue`,
  `Past Due Launch`
  这些业务异常类型。
- `dws_lead_timeline.sql`
  直接发出
  `mql_milestone`,
  `iqm_milestone`,
  `pipeline_created`,
  `customer_milestone`,
  `campaign_interaction`
  这些事件。
- `dws_icp_summary.sql`
  明确在算
  `first_touch_campaign`,
  `last_touch_before_iqm`,
  `last_touch_before_opp_creation`
  和 ICP touch 统计。
- `salesforce_org_monthly_revrec.yml`
  明写是经过 reconciliation 的 tenant-month billing/revrec rows。
- `dim_org.yml`
  明写在跟踪 org / tenant 关系以及 revenue accumulation。

## 谁会先感知这些漂移

如果要把
`影响哪张报表`
再翻成
`谁最可能先发现`
，
当前最稳的说法是：

| 报表组 | 当前最强的“谁在用”证据 |
|---|---|
| `Pipeline / Forecast / Opportunity Quality` | 有一个明确 dashboard owner：`Chen Du <chen.du@pingcap.com>` 对应 `Opportunity Data Quality Monitoring`；同时 `yiming.wang@pingcap.com` 直接查 `dws_data_quality_alerting` / `rpt_data_quality_wtw_comparison`，`xiaopeng.zhu@pingcap.com` 直接查 `dws_salesforce_arr_summary`。这轮最硬的新证据是两组稳定 live `Looker Studio` surface：`report_id = 1733a75e-a1b2-4415-8732-2c053657e245` 不只是抽象地“看 data quality”，而是长期打 `dws_data_quality_alerting`、`rpt_data_quality_wtw_comparison` 和 `dws_salesforce_pipeline_data_quality_cleanup_detail_v2`，并已出现 `quote_service_start_date` 这类 quote cleanup 字段；`report_id = 837f6250-3c3d-44b9-af6f-4db9aeb30a94` 也不只是单一 ARR summary，而是长期打 `dws_salesforce_arr_summary`、global ARR forecast snapshot、region/company ACV/forecast 明细、current-month order MRRARR 和 fiscal-year quotas。另一方面，`aadb4637-a4be-41e0-a045-8df92303e595`、`0f2ad8b8-a0a5-40e1-842a-f208c6247c0b`、`d9161f0e-f04c-49dc-82e1-053ab508ce67` 当前更应读成 `lineage-backed secondary consumer`，不和前两者平级宣称为 live report-backed surface。 |
| `Lead Funnel / Qualification` | `alfred.wang@pingcap.com` 直接查 `dws_lead_timeline`；`yiming.wang@pingcap.com` 多次直接查 `dws_icp_summary`；还有 `anls_marketing.dim_lead` 的直接查询。更新到这轮，live `JOBS_BY_PROJECT` 已经把它们部分并到同一个 `Looker Studio` 消费面上：`report_id = fd12e3fc-d36f-4cc5-b2d9-9ed2808489dc` 不只在 `2026-06-23` 多次查询 `dws_icp_summary`，还在 `2026-01-08` / `2026-01-12` 查询过 `dws_lead_timeline` 和 `anls_marketing.dim_lead`。 |
| `Campaign Attribution / ICP Analysis` | `yiming.wang@pingcap.com` 多次直接查 `dws_campaign_attribution` / `dws_icp_summary`；再加上 `01_campaign_discovery`、`02_campaign_attribution_discovery`、`Campaign Attribution Tuner` 这些命名分析面。更新到这轮，live `JOBS_BY_PROJECT` 还坐实了一个带 `requestor = looker_studio` 的 attribution report surface：`report_id = 8c6f30a4-c6fe-4536-ac62-d937d0176ebd` 不只是长期查询 `dws_campaign_attribution`，它的 datasource 组合还已经坐实包含 `salesforce.account`, `salesforce.campaign`, `salesforce.campaign_member`, `salesforce.contact`, `salesforce.lead`, `salesforce.opportunity`, `salesforce.opportunity_contact_role`, `salesforce.org_c`, `salesforce.user`，并带一个额外 datasource 命中 `anls_business_operations.dim_opportunity`。 |
| `Order / ARR / RevRec / Collections` | `xiaopeng.zhu@pingcap.com`、`fanfei.kong@pingcap.com` 多次直接查 `salesforce_order_daily_view` / `salesforce_org_monthly_revrec`；`xiaopeng.zhu@pingcap.com` 直接查 `dws_salesforce_arr_summary`；还有 `revrec_discovery`、`monthly_billing_validation`、`REVENUE_CATEGORY_IMPACT_ASSESSMENT.md`。当前已确认的 governed/report-backed finance surface 里，不只 `report_id = 837f6250-3c3d-44b9-af6f-4db9aeb30a94` 的 ARR summary 面更硬，`report_id = 58339683-7a7a-4bb6-91bd-14b149572ac9` 也长期打 `dws_salesforce_order_current_monthly_mrrarr_bo_subscription_and_cloud`、`dws_salesforce_order_monthly_mrrarr_bo_subscription_and_cloud` 和 account-quarterly MRRARR pivot；相反，从 `2026-01-01` 到当前窗口，`salesforce_order_daily_view`、`salesforce_org_monthly_revrec`、`monthly_revrec_collections`、`monthly_revrec_orders` 都没有看到 `Looker Studio` 直连命中，所以 collections / payable 这组目前仍更像 analyst / script direct-query surface。 |
| `Account / Tenant Linkage / Customer Identity` | `xiaopeng.zhu@pingcap.com`、`chen.du@pingcap.com` 直接查 `salesforce_accounts`；`laura.luo@pingcap.com` 直接查 `anls_core.dim_customer` 并展开 `tenant_ids`。这轮已补到多组稳定 live `Looker Studio` account surface：`report_id = 673c89ef-fb02-4303-a9a2-5519a652051c`、`58339683-7a7a-4bb6-91bd-14b149572ac9`、`2128769b-9f86-4c7a-a9f4-8cc7491868e3`。其中 `673c89ef...` 和 `2128769b...` 不只是“account report”，它们当前 query snippet 已直接点到 `salesforce_accounts.account_number/fy26_icp/fy26_segmentation`，并混入 global ARR forecast snapshot 的 `account_id/account_name/account_industry/tenant_id/region`；`58339683...` 则持续混合 `nexuscrm_final.nexuscrm_account` / `nexuscrm_org_c`、legacy `salesforce.account` / `salesforce.org_c` / `salesforce.opportunity` / `salesforce.user`、以及 current/monthly order MRRARR 和 account-quarterly MRRARR pivot。`aadb4637-a4be-41e0-a045-8df92303e595` 当前更适合看成 opportunity/account 共用的 `lineage-backed secondary consumer`。再往 tenant bridge 一层，`model_tidbcloud.dws_cloud_tenants_basicinfo` 还被 5 个 `Looker Studio` report 直接消费：`00675e54-cae4-4562-ae95-002a3b22b3d4` 更像 `tenant/cluster/component detail`，`1e22be38-bbfe-4c28-9d7d-596d143c39c5` 更像 `cloud billing / account-owner`，`31605bff-7555-430c-9377-c26a69be7e49` 更像 `billing + tenant bridge master surface`，`eae0ca4f-c747-40ef-b34c-f7f50cb1d1a2` 更像 `prod tenant daily cost alert`，`f9c4bd70-8ce4-487c-abb1-5518ffffd6bd` 更像 `activated-order / monthly revrec by account+tenant`。其中 `31605...` 现在还能更硬一点：本机 Chrome 历史直接出现了 Looker Studio 标题 `Cloud Billing Breakdown Detail`，并带 `aws prod FY25 expense`、`gcp prod FY25 expense`、`Azure prod expense` 页面标题。字段片段能直接点到 `tenant_id`、`tenant_name`、`tenant_email`、`tenant_region`、`tenant_plan`、`account_id`、`account_name`、`account_current_order_type`。更关键的是，这轮已把 account-side 3 类缺口和 front-door 命中拆开了：`account_current_order_type` 当前是直接打到 `31605...` 和 `f9c4...`，`sales_team_name` / `owner_user_id` 当前是直接打到 `673...` 和 `212...`，而 `contract_valid*` 在这组 live front-door 里暂时还是 `0 hit`。反过来，这轮还没看到 `dim_customer`、`dim_org`、`anls_cloud.dim_tenant` 被 `Looker Studio` 直连命中，所以命名 consumer surface 目前更像 `salesforce_accounts / nexuscrm_account / dws_cloud_tenants_basicinfo`，不是这些 identity dims 自己。 |

这轮还有一个新升级：

- 我们不再只是看到
  `marketing mart 被人 direct query`
- 而是已经在 live BigQuery 作业标签里看到
  `requestor = looker_studio`
  的消费面
- 当前高置信对应关系是：
  `report_id = 8c6f30a4-c6fe-4536-ac62-d937d0176ebd`
  多次查询
  `gcp-digital-bi.dws_marketing.dws_campaign_attribution`
  ，字段片段明确包括
  `attributed_arr`、
  `campaign_name`、
  `campaign_region`、
  `contact_response_date`、
  `opportunity_created_date`、
  `opportunity_name`
- 同一个
  `report_id = 8c6f30a4-c6fe-4536-ac62-d937d0176ebd`
  还带一个额外 datasource
  `2ff3a1a3-b43c-4143-b512-2d2770d0334ft0c0d1`
  ，命中
  `gcp-digital-bi.anls_business_operations.dim_opportunity`
  ，字段片段包括
  `lead_source`、
  `mapped_stage_name`、
  `opportunity_id`、
  `opportunity_name`、
  `opportunity_record_type`、
  `region`
- 以及
  `report_id = fd12e3fc-d36f-4cc5-b2d9-9ed2808489dc`
  多次查询
  `gcp-digital-bi.dws_marketing.dws_icp_summary`
  ，字段片段明确包括
  `opportunity_id`、
  `lead_surrogate_key`、
  `region`、
  `segmentation`、
  `icp_industry_categorisation`
- 同一个
  `report_id = fd12e3fc-d36f-4cc5-b2d9-9ed2808489dc`
  还在更早的
  `2026-01-08`
  和
  `2026-01-12`
  命中过
  `gcp-digital-bi.dws_marketing.dws_lead_timeline`
  以及
  `gcp-digital-bi.anls_marketing.dim_lead`
  ，字段片段包括
  `campaign_interaction`、
  `lead_surrogate_key`、
  `region`、
  `has_oppo`、
  `won_oppo`

所以 marketing 这边的证据强度，现在已经从
`direct query + notebook/app`
进一步升级成了
`live Looker Studio report-id-backed consumer surface`
。
当前还没补上的，主要是这些 report id 的人类可读标题 / owner 映射。
这一轮也专门试了
`gcloud` 当前登录身份
（`xiaopeng.zhu@pingcap.com`）
去走
Google Drive file metadata
解析这些
`report_id`
，
但对
`8c6f30a4-c6fe-4536-ac62-d937d0176ebd`
、
`fd12e3fc-d36f-4cc5-b2d9-9ed2808489dc`
、
`837f6250-3c3d-44b9-af6f-4db9aeb30a94`
、
`1733a75e-a1b2-4415-8732-2c053657e245`
、
`690c8087-0697-4272-b05e-2ee37d728c15`
都返回了
`403`
。
所以当前更准确的边界不是
`这些 report 可能不存在`
，
而是
`当前机器的 BigQuery 观察权限足以证明 consumer surface，但不足以直接取回 Google file title/owner metadata`
。

## 高频 Report Glossary

如果后面讨论要从
`report_id`
反过来查
`它更像在看什么`
，
当前最稳的短索引可以先用下面这张表。

这里的业务语义来自
`referenced_tables + query field snippets`
，
不是 Google Drive / Looker Studio title 元数据。

| `report_id` | 当前最像在看什么 | 主 datasource / 关键字段 |
|---|---|---|
| `1733a75e-a1b2-4415-8732-2c053657e245` | `pipeline data quality / cleanup monitor` | 主要打 `dws_data_quality_alerting`、`date_spine`、`salesforce_opportunities`；字段片段以 `opportunity_name`、`region` 为主，前文也已坐实它会触达 `dws_salesforce_pipeline_data_quality_cleanup_detail_v2` 和 quote cleanup 字段。 |
| `837f6250-3c3d-44b9-af6f-4db9aeb30a94` | `ARR summary + regional/company forecast` | 主要打 `dws_salesforce_arr_summary`、`dws_fy25_regional_acv_achivement_and_forecast_detail`、current-month order MRRARR；字段片段包括 `account_id`、`account_name`、`account_industry`、`arr_amount_usd`、`arr_usd_cd_rate_current_month`、`region`。 |
| `aadb4637-a4be-41e0-a045-8df92303e595` | `opportunity snapshot / account lens` | 主要打 `salesforce_opportunities_snapshot`，并混入 legacy `salesforce.account/opportunity/org_c/user`；字段片段包括 `account_id`、`account_name`、`fy26_icp`、`fy26_segmentation`、`arr_amount_usd`、`opportunity_name`、`opportunity_product_family`、`region`。 |
| `0f2ad8b8-a0a5-40e1-842a-f208c6247c0b` | `opportunity stage duration / conversion` | 主要打 `dws_opportunity_stage_duration` 和 `salesforce_opportunities`；字段片段包括 `arr_amount_usd`、`opportunity_name`、`opportunity_product_family`、`region`。 |
| `d9161f0e-f04c-49dc-82e1-053ab508ce67` | `opportunity + account + PLG pipeline blend` | 主要打 `salesforce_opportunities`、legacy `salesforce.account/opportunity/org_c/user`，并带 `plg_pipelines` datasource；字段片段包括 `account_id`、`account_name`、`arr_amount_usd`、`mapped_stage_name`、`opportunity_name`、`region`。 |
| `fd12e3fc-d36f-4cc5-b2d9-9ed2808489dc` | `lead funnel / ICP path` | 主要打 `dws_icp_summary`，较早还打 `dws_lead_timeline + dim_lead`；字段片段包括 `lead_surrogate_key`、`account_name`、`opportunity_name`、`region`。 |
| `8c6f30a4-c6fe-4536-ac62-d937d0176ebd` | `campaign attribution / contact-opportunity touch` | 主要打 attribution 原料表与 `salesforce_opportunities`，再带 `dim_opportunity` datasource；字段片段包括 `attributed_arr`、`campaign_name`、`contact_name`、`contact_response_date`、`opportunity_name`、`mapped_stage_name`、`region`。 |
| `58339683-7a7a-4bb6-91bd-14b149572ac9` | `account + current/monthly order MRRARR composite` | 主要打 `nexuscrm_final.nexuscrm_account/org_c`、legacy `salesforce.account/...`、`dws_salesforce_order_current_monthly_mrrarr_bo_subscription_and_cloud`；字段片段包括 `account_id`、`account_name`、`account_number`、`fy26_icp`、`fy26_segmentation`、`account_industry`、`account_segmentation`、`order_product_family`、`arr_usd_cd_rate_current_month`、`mrr_usd_cd_rate_finance`。 |
| `673c89ef-fb02-4303-a9a2-5519a652051c` | `account + global ARR forecast master surface` | 主要打 `nexuscrm_final.nexuscrm_account/org_c` 和 global ARR forecast snapshots；字段片段包括 `account_id`、`account_number`、`fy26_icp`、`fy26_segmentation`、`account_industry`、`tenant_id`、`tenant_region`。 |
| `2128769b-9f86-4c7a-a9f4-8cc7491868e3` | `account + forecast variant` | 主要打 legacy `salesforce.account/opportunity/org_c/user` 和 global ARR forecast snapshots；字段片段包括 `account_number`、`fy26_icp`、`fy26_segmentation`、`account_id`、`account_name`、`account_industry`、`tenant_id`、`tenant_region`。 |
| `690c8087-0697-4272-b05e-2ee37d728c15` | `PLG signup / billing-capable cloud funnel` | 主要打 `dws_tidb_cloud_marketing_funnel_1_to_3_stage_new_users_monthly_group`、`dws_daily_external_cloud_billing_capable_user_detail_2023_to_day`、`dws_daily_external_cloud_signup_active_engaged_billingcapable_user_count`；字段片段包括 `new_users_count`、`traffic_funnel_type`、`tenant_id`、`tenant_name`、`tenant_email`、`tenant_region`。 |

## Report-First Impact Matrix

如果问题不是
`某个对象会打到哪些报表`
，
而是
`某张报表先会被哪些对象差异打到`
，
当前最稳可以先看下面这张表。

| `report_id` / 报表面 | 关键对象 | Salesforce 现网会做什么 | CM 目前已支持 | CM 当前主要差异 / 风险点 |
|---|---|---|---|---|
| `1733a75e-a1b2-4415-8732-2c053657e245` `pipeline data quality / cleanup monitor` | `Opportunity`, `Quote`, 次级 `Account` | 维护机会 stage、forecast、ARR/ACV、长期未更新/过期 close date 等质量语义；Quote 还会维护 `quote_service_start_date` / `quote_service_end_date` 这类 cleanup 关键字段 | Opportunity 主对象、公式、rollup、active validations、部分 Flow 已有；Quote enrichment 和 `QuoteNumber` 也已落地，本地 `salesforce_opportunities` 核心字段存在 | `Opportunity` 仍有 17 个 live Flow 未迁，`OpportunityTrigger` 仍是 runtime boundary；Quote 仍缺 2 条 nonstandard-term Flow，3 条 validation 只是 local inactive；所以这张报表最先被打到的是 `Opportunity/Quote parity + trigger residue` |
| `837f6250-3c3d-44b9-af6f-4db9aeb30a94` `ARR summary + regional/company forecast` | `Opportunity`, `Order`, `Order_Product__c`, `Account` | 机会侧维护 `arr_amount_usd` / `accurate_acv_amount` / forecast，订单侧维护 current-month order finance 语义，line-item 侧维护 `order_product_family` | Opportunity substrate 已在，本地 Order 已有 `Std_CreateOrderFromQuote`、payment inheritance、`Order_Default_RevRec_Entity`，line-item 也已有公式/部分 validation | `Order_Org_Auto_Set_Account_*`、`Order_Set_PLG_BD_Pool` 等 carry-over / finance Flow 未补；`OrderTrigger` 和 line-item trigger residue 仍在；所以 ARR summary 这面更多先被 `Opportunity + Order + line-item finance parity` 打到，而不是纯 revenue 表缺口 |
| `fd12e3fc-d36f-4cc5-b2d9-9ed2808489dc` `lead funnel / ICP path` | `Lead`, `CampaignMember`, `Opportunity`, 次级 `Account` / `Contact` | 维护 lead lifecycle、`lead_mql_timestamp`、`lead_iqm_timestamp`、campaign touch 到建 opp 前后的路径、lead-account stitching | Lead 公式、validation、12 条 Lead Flow 已迁；CampaignMember 已有 first/last-touch 维护 Flow；本地 `convertLead` 还已把 primary campaign attribution preview / child relink 纳入标准动作 | 22 个 live Lead Flow 未迁，`LeadTrigger` / `LeadAITrigger` 仍是 runtime boundary；`Campaign_Member_Key_Message_Update` 缺失；`Lead_StatusChangeTimestamp` 当前也只是近似承接；所以这张报表优先受 `Lead lifecycle + CampaignMember response/involvement + residual trigger` 影响 |
| `8c6f30a4-c6fe-4536-ac62-d937d0176ebd` `campaign attribution / contact-opportunity touch` | `CampaignMember`, `Contact`, `Opportunity`, `Lead`, 次级 `Campaign` / `OpportunityContactRole` | 维护 `first_responded_date`、response / involvement、lead-contact convert 后 relink、机会金额归因到 campaign/contact touch | CampaignMember 本地已有 4 条 first/last-touch Flow，下游已真实计算 `attributed_acv` / `attributed_arr`；Contact 基础对象和拼接链也在；`convertLead` 已显式读取 `CampaignMember` 做 attribution preview | `Campaign_Member_Key_Message_Update` 缺失，`Trigger_CampaignMember` 仍像 runtime boundary；Contact live Flow 当前也没看到本地 peer；所以 attribution 报表最先被 `CampaignMember response/involvement semantics + contact stitching` 打到，不该误读成 `Campaign` 主表自身大缺口 |
| `58339683-7a7a-4bb6-91bd-14b149572ac9` `account + current/monthly order MRRARR composite` | `Account`, `Org__c`, `Order`, `Order_Product__c`, 次级 `Revenue__c` | 维护 account segmentation / ICP / tenant linkage，同时维护 current/monthly order MRRARR 和 product-family 语义 | Account / Org bridge 已有，Order core create/inheritance 已有，line-item 公式也在；current front-door fields 已坐实 `account_number`、`fy26_icp`、`fy26_segmentation`、`order_product_family`、`arr_usd_cd_rate_current_month`、`mrr_usd_cd_rate_finance` | Account exact-name Flow 仍缺；Order carry-over / PLG pool parity 未补；line-item `Name` auto-number 和 trigger residue还在；所以这张报表最像 `Account/Org shared key + Order current-month finance parity` 的复合受害面 |
| `673c89ef-fb02-4303-a9a2-5519a652051c` / `2128769b-9f86-4c7a-a9f4-8cc7491868e3` `account + forecast surfaces` | `Account`, `Org__c`, `Opportunity` | 维护 account 侧 `AccountID`、ICP、Segmentation、Industry，并把机会 / forecast / tenant 维度绑到 account，同时把 owner / sales-team 邻近语义带到 forecast 面 | Account_ID auto-number、部分 Account Flow、Org bridge 都在；front-door `salesforce_accounts` / `dim_org` / `dim_customer` / `dim_tenant` 字段也已坐实 | 4 个 live Account Flow 未迁，`AccountTrigger` 仍在；当前这组 front-door 里还没有把 `Account_Current_Order_Type` 或 `contract_valid*` 打成 direct field hit，所以更稳的读法是 `account dimension / owner-governance parity` 先于 `current-order-type` 主实现 |
| `690c8087-0697-4272-b05e-2ee37d728c15` `PLG signup / billing-capable cloud funnel` | `tenant bridge`, `Org__c`，谨慎次级 `Account` / `Lead` | 通过 tenant bridge 把 cloud signup、billing-capable user、tenant identity 串起来，再受 account shared-key / finance carry-over 邻近链影响 | 当前 report-backed 直命中的最强字段片段仍是 `tenant_id`、`tenant_name`、`tenant_email`、`tenant_region`、`new_users_count`、`traffic_funnel_type`；Account / Org substrate 与 `dws_cloud_tenants_basicinfo` 主要作为依赖链解释 | 当前还没有直接证据证明这张报表吃 `Lead` front door，也还没把 `account_id` / `account_current_order_type` 打成这张 front-door 的 direct hit；所以它更像 `583...` / `673...` 清理后的次级 consumer，不要过度写成独立 account shared-key 主票 |
| `f9c4bd70-8ce4-487c-abb1-5518ffffd6bd` `activated-order / monthly revrec by account+tenant` | `Order`, `Order_Product__c`, `Account`, `Org__c`，次级 `Revenue__c` | 维护 activated-order account basic info、monthly revrec、`order_product_family`，再和 tenant/account bridge 拼起来 | Order core 和 Account/Org bridge 已在，line-item 公式已在；front-door datasource 已把 `order_product_family` 与 `account_current_order_type`、`tenant_id`、`tenant_name` 拼在一起 | `Order_Org_Auto_Set_Account_*`、finance carry-over、line-item trigger residue 仍未清；所以这张比 `salesforce_revrec` 更像先被 `Order + Account/Org + line-item` 的复合 drift 打到 |

## Report-First Gap Priority Matrix

如果要从
`哪张报表先开始排查`
直接落到
`先看哪些具体缺口`
，
当前最稳可以先用下面这张表。

| `report_id` / 报表面 | 优先排查的具体 gap | 缺口类型 | 为什么先看它 |
|---|---|---|---|
| `1733a75e-a1b2-4415-8732-2c053657e245` `pipeline data quality / cleanup monitor` | `Quote_update_nonstandard_conditions_checkbox`, `Quote_update_nonstandard_conditions_checkbox_2`, `OpportunityShareToPersalesOwner` / `OpportunityUpdateShareToPerSalOwner`, residual `OpportunityTrigger` / `QuoteTrigger` | `L2 exact-flow parity`, `activation-state / naming completion`, `runtime boundary` | 这张报表已经直接碰到 quote cleanup 和 opportunity quality 语义，所以应先查 quote service-window / nonstandard-term Flow，再查 owner-team / trigger residue。 |
| `837f6250-3c3d-44b9-af6f-4db9aeb30a94` `ARR summary + regional/company forecast` | `Order_Org_Auto_Set_Account_*`, `Order_Set_PLG_BD_Pool`, line-item trigger residue, residual `OrderTrigger` | `L2 finance carry-over parity`, `runtime boundary` | 这张表已经直接混 current-month order MRRARR 与 ARR summary，最容易先被 order/account carry-over 和 line-item finance drift 打歪。 |
| `fd12e3fc-d36f-4cc5-b2d9-9ed2808489dc` `lead funnel / ICP path` | `Lead_StatusChangeTimestamp`, Lead assignment / reminder / notification long tail, `Campaign_Member_Key_Message_Update`, residual `LeadTrigger` / `LeadAITrigger` | `semantic parity mismatch`, `L2 exact-flow parity`, `runtime boundary` | 它直接吃 `lead_mql_timestamp` / `lead_iqm_timestamp` / campaign path，所以先查 lifecycle timestamp 语义，再查 response / assignment long tail。 |
| `8c6f30a4-c6fe-4536-ac62-d937d0176ebd` `campaign attribution / contact-opportunity touch` | `Campaign_Member_Key_Message_Update`, Contact live Flow parity hole, residual `Trigger_CampaignMember`, residual Contact trigger surfaces | `L2 exact-flow parity`, `runtime boundary` | 这张表直接用 `first_responded_date`、`contact_response_date`、`attributed_arr`，所以先查 campaign-member response/involvement，再查 contact stitching。 |
| `58339683-7a7a-4bb6-91bd-14b149572ac9` `account + current/monthly order MRRARR composite` | `Account_Current_Order_Type`, `Account_Partner_Sales_Owner_Set`, `Order_Org_Auto_Set_Account_*`, `Order_Set_PLG_BD_Pool`, custom line-item `Name` auto-number / trigger residue | `L2 exact-flow parity`, `auto-number parity`, `runtime boundary` | 这是 account shared-key 和 current-month order finance 的混合面，最容易先暴露 account-current-order-type、order carry-over、line-item product-family drift。 |
| `673c89ef-fb02-4303-a9a2-5519a652051c` / `2128769b-9f86-4c7a-a9f4-8cc7491868e3` `account + forecast surfaces` | `Account_Partner_Sales_Owner_Set`, `Account_Contract_Valid_Message`, residual `AccountTrigger` | `L2 exact-flow parity`, `runtime boundary` | 这两张表直接点 `account_number` / `fy26_icp` / `fy26_segmentation` / owner-forecast 邻近字段，所以先查 account dimension / owner-governance parity，再看 trigger residue。`contract_valid*` 当前仍更像 governance 邻近项，不要过度写成这组 front-door 的强直命中。 |
| `690c8087-0697-4272-b05e-2ee37d728c15` `PLG signup / billing-capable cloud funnel` | `583...` 的 `Account_Current_Order_Type`, `#3707` 的 owner / governance parity, `Order_Org_Auto_Set_Account_*` carry-over, tenant-account bridge contamination from finance/order side | `dependent consumer`, `shared-key parity`, `L2 finance carry-over parity` | 当前还不该先按 Lead 排查；它更像 tenant/account bridge surface，而且当前最硬字段还是 `tenant_*` + funnel metric，所以默认先跟随 `583...` / `#3707` 做回归，而不是单独开一张 account 主票。 |
| `f9c4bd70-8ce4-487c-abb1-5518ffffd6bd` `activated-order / monthly revrec by account+tenant` | `Order_Org_Auto_Set_Account_*`, line-item trigger residue, `Order_Set_PLG_BD_Pool`, `RevRec_Set_PLG_BD_Pool`, `Cloud_Registration_Source_from_Org_to_Collections` | `L2 finance carry-over parity`, `runtime boundary` | 这张表直接拼 `order_product_family + account_current_order_type + tenant bridge`，所以最该先查 order/account carry-over、PLG pool、org-to-collection finance bridge。 |

## Report-First Default Remediation Layer

如果不是要看
`有哪些 gap`
，
而是要更快决定
`这张报表的默认修复入口在哪`
，
下面这张表更适合拿去排优先级。

| `report_id` / 报表面 | 默认第一修复层 | 第二修复层 | 最后才单列的真实边界 |
|---|---|---|---|
| `1733a75e-a1b2-4415-8732-2c053657e245` `pipeline data quality / cleanup monitor` | `L2 Opportunity/Quote parity` | inactive validation / owner-team naming completion | `OpportunityTrigger` / `QuoteTrigger` |
| `837f6250-3c3d-44b9-af6f-4db9aeb30a94` `ARR summary + regional/company forecast` | `L2 Order carry-over + line-item parity` | `Account` shared-key / forecast adjacency cleanup | `OrderTrigger` + line-item trigger residue |
| `fd12e3fc-d36f-4cc5-b2d9-9ed2808489dc` `lead funnel / ICP path` | `L2 Lead lifecycle parity` | `CampaignMember` response/involvement parity | `LeadTrigger` / `LeadAITrigger` |
| `8c6f30a4-c6fe-4536-ac62-d937d0176ebd` `campaign attribution / contact-opportunity touch` | `L2 CampaignMember parity` | Contact stitching parity | `Trigger_CampaignMember` + Contact trigger surfaces |
| `58339683-7a7a-4bb6-91bd-14b149572ac9` `account + current/monthly order MRRARR composite` | `L2 Account current-order-type + Order carry-over parity` | line-item / `Revenue__c.Name` auto-number completion | `AccountTrigger` + `OrderTrigger` + line-item trigger residue |
| `673c89ef-fb02-4303-a9a2-5519a652051c` / `2128769b-9f86-4c7a-a9f4-8cc7491868e3` `account + forecast surfaces` | `L2 Account owner / governance parity` | tenant bridge drift cleanup | `AccountTrigger` |
| `690c8087-0697-4272-b05e-2ee37d728c15` `PLG signup / billing-capable cloud funnel` | 依赖 `583...` / `#3707` 的主票回归 | order-side carry-over contamination cleanup | 剩余 bridge logic 若只在 trigger 中才单列 |
| `f9c4bd70-8ce4-487c-abb1-5518ffffd6bd` `activated-order / monthly revrec by account+tenant` | `L2 Order + Invoice_Collection__c carry-over parity` | `RevRec_Set_PLG_BD_Pool` + line-item parity | `OrderTrigger` / `RevenueTrigger` / line-item trigger residue |

最重要的读法是：

- `pipeline / dq`
  默认从
  `Opportunity / Quote L2 parity`
  入手
- `lead funnel / attribution`
  默认从
  `Lead / CampaignMember L2 parity`
  入手
- `ARR / revrec / account composite`
  默认从
  `Order / Account / Invoice_Collection__c carry-over parity`
  入手
- 只有当这些 parity 都清过以后还剩行为差异，
  才把残余项单列成
  `CM runtime boundary`

## Report-First Mechanism Trace Cards

如果要从
`概念级差异`
继续往下落到
`当前仓库里到底已经有什么文件`
，
下面这几张卡最适合直接拿去开 backlog。

### Trace Card A: `fd12e3fc-d36f-4cc5-b2d9-9ed2808489dc` `lead funnel / ICP path`

| 维度 | 当前证据 |
|---|---|
| Salesforce 现网会做什么 | 维护 `lead_mql_timestamp`、`lead_iqm_timestamp`、status/lifecycle 时间戳、lead-account stitching、以及 convert 前后的 campaign path。 |
| CM 当前已支持什么 | 当前树里已经能直接点到 4 个本地承接件：`packs/Salesforce-PingCAP-L2/flows/IQM_Completion_Flow.flow.json` 是 `Lead` 上 `RecordBeforeSave CreateAndUpdate`，会在 `Status = Meeting Completed` 且非 SDR 时写 `Meeting_Completed_DateTime__c`；`packs/Salesforce-PingCAP-L2/flows/Lead_Status_Duration.flow.json` 是 `Lead` 上 `RecordBeforeSave CreateAndUpdate`，在 `Status IsChanged` 时写 `Date_Status_Changed__c`；`packs/Salesforce-PingCAP-L2/actions/invocable_standard_actions.json` 里 `convertLead` 显式声明 `previewFlowDeveloperName = Std_ConvertLeadCampaignPreview`；`packs/Salesforce-PingCAP-L2/flows/Std_ConvertLeadCampaignPreview.flow.json` 还是一个纯读 Flow，会查最新 `CampaignMember` 并输出 `campaignFound/campaignName`。 |
| 当前主要差异 / 待补 / 疑似待补什么 | `Lead_StatusChangeTimestamp` 还不是 live 的窄语义，因为本地 `Lead_Status_Duration` 只要 `Status` 变化就会写时间戳；此外，当前对 `Quote_update_nonstandard_conditions_checkbox` 这类 exact-name 检索之外，`Campaign_Member_Key_Message_Update` 在 `packs/Salesforce-PingCAP-L2` 和 `packs/NOT-EDIT-final-merged-packs` 里仍是 `0 hits`，Lead 长尾 assignment/reminder/notification 也还没全部追回；剩余 `LeadTrigger` / `LeadAITrigger` 仍是 runtime boundary。 |
| 最先打到哪张报表/哪些字段 | 直接打 `salesforce_leads -> dim_lead / dws_lead_timeline / dws_icp_summary`，也就是 `fd12...` 这张前台面。当前最敏感字段还是 `lead_mql_timestamp`、`lead_iqm_timestamp`、`lead_status`、`lead_surrogate_key`、`first_touch_campaign`、`last_touch_before_iqm`、`last_touch_before_opp_creation`。 |
| 当前最稳动作 | 先把它当 `Lead lifecycle parity`，不是 `CM 不会做 Lead`。优先顺序仍然是：修窄 `Lead_StatusChangeTimestamp` 语义，再补长尾 Lead Flow，再单列 residual trigger。 |

### Trace Card B: `8c6f30a4-c6fe-4536-ac62-d937d0176ebd` `campaign attribution / contact-opportunity touch`

| 维度 | 当前证据 |
|---|---|
| Salesforce 现网会做什么 | 维护 `first_responded_date`、response/involvement、lead-contact convert 后的 relink，以及 campaign/contact 到 opportunity 的金额归因连接。 |
| CM 当前已支持什么 | 当前树里已经能直接点到 attribution 基础设施：`packs/Salesforce-PingCAP-L2/pack.json` 和 final merged pack 都明确登记了 `Lead_Set_First_And_Last_CampaignMember*` 与 `Contact_Set_First_And_Last_CampaignMember*`；`packs/Salesforce-PingCAP-L2/flows/Lead_Set_First_And_Last_CampaignMember.flow.json` 会在 `CampaignMember` 变化后回写 `Lead.First_Campaign__c / Last_Campaign__c`；`packs/Salesforce-PingCAP-L2/flows/Contact_Set_First_And_Last_CampaignMember.flow.json` 会回写 `Contact.First_Campaign__c / Last_Campaign__c`，而且专门跳过 `Lead Convert relink` 场景的重复重算；`Std_ConvertLeadCampaignPreview.flow.json` 又把 convert 前的最新 `CampaignMember` 当成标准动作 preview 输入。 |
| 当前主要差异 / 待补 / 疑似待补什么 | `Campaign_Member_Key_Message_Update` 当前在本地 pack 和 final merged pack 里仍是 `0 hits`；Contact live Flow peer 也还没看到；`Trigger_CampaignMember` 和 Contact trigger surfaces 仍留在 live runtime。 |
| 最先打到哪张报表/哪些字段 | 直接打 `salesforce_campaign_members -> salesforce_campaign_attributions / dws_campaign_attribution / dws_campaign_attribution_details`，也就是 `8c6f...` 这张 attribution 面。当前最敏感字段是 `first_responded_date`、`campaign_member_status`、`has_responded`、`is_contact_involved`、`contact_response_date`、`attributed_arr`、`attributed_acv`。 |
| 当前最稳动作 | 先按 `CampaignMember parity + Contact stitching parity` 处理，不要先把它升级成 `Campaign` 主表 gap。最直接的 L2 动作仍然是补 `Campaign_Member_Key_Message_Update`。 |

### Trace Card C: `58339683-7a7a-4bb6-91bd-14b149572ac9` `account + current/monthly order MRRARR composite`

| 维度 | 当前证据 |
|---|---|
| Salesforce 现网会做什么 | 这张面吃的是 account shared-key + order current-month finance 组合：`AccountID`、ICP/Segmentation、tenant bridge、`account_current_order_type`、`order_product_family`、current-month ARR/MRR。 |
| CM 当前已支持什么 | 当前树里已经能直接点到 3 个已落地桥件：`packs/Salesforce-PingCAP-L2/flows/Org_Set_Account.flow.json` 是 `Org__c` 上 `RecordBeforeSave CreateAndUpdate`，会在 `Lead__c` 存在且 lead 已转化后把 `ConvertedAccountId` 写进 `Org__c.Account__c`；`packs/Salesforce-PingCAP-L2/flows/Order_Default_RevRec_Entity.flow.json` 是 `Order` 上 `RecordBeforeSave CreateAndUpdate`，会按 `Opportunity.PingCAP_Contracting_Entity_EMEA_only__c` / `Account.PingCAP_Contracting_Entity__c` 默认 `PingCAP_RevRec_Entity__c`；`packs/Salesforce-PingCAP-L2/flows/Cloud_Registration_Source_from_Org_to_Order.flow.json` 是 `Order` 上 `RecordAfterSave CreateAndUpdate`，会根据 `Accumulate_revenue_to_Org__c` 回写 `Cloud_Registration_Source__c`。 |
| 当前主要差异 / 待补 / 疑似待补什么 | 当前对 `Account_Current_Order_Type`、`Account_Partner_Sales_Owner_Set`、`Order_Org_Auto_Set_Account_Create`、`Order_Set_PLG_BD_Pool` 做 current-tree 检索，在 `packs/Salesforce-PingCAP-L2` 和 `packs/NOT-EDIT-final-merged-packs` 里都是 `0 hits`；这说明 account current-order-type / order carry-over 这组仍更像 `L2 exact-flow parity backlog`。残余 `AccountTrigger` / `OrderTrigger` 和 line-item trigger logic 才是后面的真实 boundary。 |
| 最先打到哪张报表/哪些字段 | 直接打 `nexuscrm_account / nexuscrm_org_c + dws_salesforce_order_current_monthly_mrrarr_bo_subscription_and_cloud`，也就是 `583...` 这张复合面。当前最敏感字段是 `account_number`、`fy26_icp`、`fy26_segmentation`、`account_current_order_type`、`order_product_family`、`arr_usd_cd_rate_current_month`、`mrr_usd_cd_rate_finance`。 |
| 当前最稳动作 | 默认按 `Account current-order-type + Order carry-over parity` 开修，不要一上来就把它定成 runtime 缺陷。真正该单列的还是清完这些 exact-name parity 以后剩下的 trigger residue。 |

### Trace Card D: `f9c4bd70-8ce4-487c-abb1-5518ffffd6bd` `activated-order / monthly revrec by account+tenant`

| 维度 | 当前证据 |
|---|---|
| Salesforce 现网会做什么 | 这张面把 activated-order、monthly revrec、tenant/account bridge 和 `order_product_family` 拼在一起，同时还会受 org-to-collection / PLG pool / revrec bridge 影响。 |
| CM 当前已支持什么 | 当前树里已经不只是有一个空对象定义。`packs/Salesforce-PingCAP-L2/objects/Invoice_Collection__c.json` 本地已经带了大量 active helper 字段：`Payment_Status__c` 会按 `CollectionsStatus__c + Payable_Date__c` 算 `Collected / Due / Receivable`，`From_Marketplace__c` 会把 `Marketplace__c` 映射成云市场标签，`Uncollected_Amount_USD__c` / `Uncollected_Amount__c` 会按 `CollectionsStatus__c != 'Received'` 计算未回款；同时 `Order` 侧已经真实消费它：`packs/Salesforce-PingCAP-L2/objects/Order.json` 上有 `Cash_Collected_Amount_USD__c`、`Cash_Collected_Amount__c` 两个只在 `Invoice_Collection__c.CollectionsStatus__c = 'Collected'` 时生效的 rollup，还有 `Payable_Amount_USD_exc_tax__c`、`Latest_Payable_Date__c`、`Accumulated_Payable_Amount__c` 这些从 `Invoice_Collection__c` 聚过来的汇总。再加上 `Cloud_Registration_Source_from_Org_to_Order.flow.json` 和 `Order_Default_RevRec_Entity.flow.json`，说明本地其实已经有一整条“order finance snapshot”基础设施。 |
| 当前主要差异 / 待补 / 疑似待补什么 | live 侧高价值 exact-name 缺口现在已经很具体：`Collection_Set_PLG_BD_Pool`、`Collection_Amount_and_Payable_Amount_exc_tax`、`Collection_Amount_and_Payable_Amount_exc_tax_Update`、`Cloud_Registration_Source_from_Org_to_Collections` 当前在本地 pack / final merged pack 里仍是 `0 hits`；`Invoice_Collection__c.Name` auto-number 也仍缺。这里最关键的不是“会不会显示集合编号”，而是：如果 local 没有把 `PLG_BD_Pool__c`、`Collections_Amount_USD_exc_tax__c`、`Collections_Amount_exc_tax__c`、`Payable_Amount_USD2_exc_tax__c`、`Marketplace__c` 按 live 语义维护好，`Order` 侧那些 rollup 就会在错误状态、错误时点或错误维度上聚合。剩余 `OrderTrigger` / `RevenueTrigger` / line-item trigger 才是后续 runtime 边界。 |
| 最先打到哪张报表/哪些字段 | 直接打 `f9c4...` 自己，以及它背后的 `model_tidbcloud.dws_cloud_tenants_basicinfo`、`salesforce_order_daily_view`、`salesforce_org_monthly_revrec`、`monthly_revrec_collections` 这组 finance front-door。当前最敏感字段可以更具体地写成：`tenant_id`、`tenant_name`、`account_current_order_type`、`order_product_family`、`mrr_usd_cd_rate_finance`，再加上 collections 链上的 `collections_status_c`、`invoice_status_c`、`cash_collected_c`、`payable_amount_usd_2_exc_tax_c`、`plg_bd_pool_c`、`marketplace_c`。 |
| 当前最稳动作 | 默认先补 `Invoice_Collection__c carry-over / helper-field parity`，再补 `Order + RevRec` 邻近的 exact-name parity，最后才把 residual finance trigger 逻辑单列出来。换句话说，这张报表当前更像被 `collections status / exc-tax helper / org-to-marketplace bridge` 打歪，而不是先被 `Name auto-number` 打歪。 |

### Trace Card E: `1733a75e-a1b2-4415-8732-2c053657e245` `pipeline data quality / cleanup monitor`

| 维度 | 当前证据 |
|---|---|
| Salesforce 现网会做什么 | 这张面吃的是 `Opportunity` 的 stage / forecast / close-date / launch-date / owner-team / cloud-order-type 语义，再叠加 `Quote` 的 service-window 和 nonstandard-term / commercial validation 语义。 |
| CM 当前已支持什么 | 当前树里已经能直接点到多条 `Opportunity` 本地承接件：`packs/Salesforce-PingCAP-L2/flows/Std_OpportunityStageDerivedFields.flow.json` 是 `Opportunity` 上 `RecordBeforeSave CreateAndUpdate`，在 `StageName IsChanged` 时回写 `Probability`、`ForecastCategory`、`ForecastCategoryName`；`packs/Salesforce-PingCAP-L2/flows/Opportunity_Cloud_Order_Type_Set.flow.json` 是 `Opportunity` 上 `RecordBeforeSave CreateAndUpdate`，会在特定 open opportunity 条件下清理 `Cloud_Order_Type__c`；`packs/Salesforce-PingCAP-L2/flows/Opportunity_Close_Date_Auto_Set.flow.json` 会同步 `CloseDate`、`Close_Date__c`、`Launch_Date__c`；此外 `packs/Salesforce-PingCAP-L2/pack.json` / final merged pack 里还明确登记了 `Opportunity_Auto_To_Launch_Stage`、`Opportunity_Pricebook_Default`。`Quote` 这边虽然 exact-name Flow 还缺，但 3 条关键 validation 其实已经 `present but inactive`：`PingCAP_Contract_Entity_EMEA_only`、`Customer_s_Hardware_Configuration`、`Details_of_vCPU_Calculation`、`Version_of_TiDB` 在本地 validation JSON 里都能看到且 `active: false`。 |
| 当前主要差异 / 待补 / 疑似待补什么 | `Quote_update_nonstandard_conditions_checkbox`、`Quote_update_nonstandard_conditions_checkbox_2`、`OpportunityShareToPersalesOwner`、`OpportunityUpdateShareToPerSalOwner` 当前在 `packs/Salesforce-PingCAP-L2` 和 final merged pack 里仍是 `0 hits`；也就是说，当前最显眼的不是 substrate 缺失，而是 `Opportunity/Quote exact-name parity + inactive validation activation-state mismatch`。剩余 `OpportunityTrigger` / `QuoteTrigger` 才是后面的 runtime boundary。 |
| 最先打到哪张报表/哪些字段 | 直接打 `1733...` 这张 data-quality 面，以及背后的 `dws_data_quality_alerting`、`rpt_data_quality_wtw_comparison`、`dws_salesforce_pipeline_data_quality_cleanup_detail_v2`。当前最敏感字段是 `stage_name`、`forecast_category`、`probability`、`close_date`、`launch_date`、`quote_service_start_date`、`quote_service_end_date`、以及 nonstandard-term / quote cleanup 相关字段。 |
| 当前最稳动作 | 先按 `Opportunity/Quote L2 parity` 处理。优先顺序仍然是：补 2 条 Quote exact-name Flow、对齐 inactive validation、再看 owner-team / trigger residue。 |

### Trace Card F: `690c8087-0697-4272-b05e-2ee37d728c15` `PLG signup / billing-capable cloud funnel`

| 维度 | 当前证据 |
|---|---|
| Salesforce 现网会做什么 | 这张面主要不是直接吃 `Lead`，而是吃 `Account / Org / tenant bridge`：`AccountID`、`account_current_order_type`、tenant identity、tenant-account bridge、以及 account-side segmentation / owner 语义，再和 cloud signup / billing-capable user 数据拼起来。 |
| CM 当前已支持什么 | 当前树里已经能直接点到两条 shared-key 承接件：`packs/Salesforce-PingCAP-L2/autonumber/counters.json` 和 `formats.json` 已明确配置 `Account.Account_ID__c` auto-number；`packs/Salesforce-PingCAP-L2/flows/Org_Set_Account.flow.json` 则在 `Org__c` 上 `RecordBeforeSave CreateAndUpdate`，当 `Lead__c` 存在且 lead 已转化时把 `ConvertedAccountId` 带到 `Org__c.Account__c`。这说明 account key 和 org/account bridge 在本地并不是空白。 |
| 当前主要差异 / 待补 / 疑似待补什么 | 当前对 `Account_Current_Order_Type`、`Account_Partner_Sales_Owner_Set`、`Account_Contract_Valid_Message` 做 current-tree 检索，在本地 pack 和 final merged pack 里都是 `0 hits`；但 `690...` 当前最强的 report-backed 字段片段仍是 `tenant_*` + funnel metric，没有把这些 account exact-name 机制打成 direct front-door 字段。所以它更像 `583...` 与 `#3707` 清理后的 dependent consumer，而不是要先单开的 `Lead` 或 `Account` 主票。 |
| 最先打到哪张报表/哪些字段 | 直接打 `690...` 背后的 `model_plg` funnel datasources。当前最敏感字段是 `new_users_count`、`traffic_funnel_type`、`tenant_id`、`tenant_name`、`tenant_email`、`tenant_region`；`account_id` / `account_current_order_type` 当前更适合作为依赖链邻近观察。 |
| 当前最稳动作 | 默认先跟随 `583...` 与 `#3707` 做回归，不要从 `Lead` 开始排，也不要先把它单开成 account shared-key 主票。只有依赖清完后仍漂，再单独查 order-side carry-over 或 residual bridge logic。 |

### Trace Card G: `837f6250-3c3d-44b9-af6f-4db9aeb30a94` `ARR summary + regional/company forecast`

| 维度 | 当前证据 |
|---|---|
| Salesforce 现网会做什么 | 这张面把 `Opportunity` 的 ARR / forecast 语义，`Order` 的 current-month finance 语义，`Revenue__c` 的 revrec / confirmed revenue 语义，以及 line-item 的 `product_family / net_fees / service window` 组合在一起。 |
| CM 当前已支持什么 | 当前树里已经能直接点到一组比较扎实的本地 finance 承接件：`packs/Salesforce-PingCAP-L2/flows/Order_Default_RevRec_Entity.flow.json` 会在 `Order` 上 before-save 默认 `PingCAP_RevRec_Entity__c`；`packs/Salesforce-PingCAP-L2/objects/Order.json` 已有对 `Revenue__c` 的 rollup，例如 `Accumulated_Credit_Amount__c`、`Accumulated_Revenue_Before_Adjust__c`、`Recognized_Revenue_Amount_USD__c` / `Recognized_Revenue_Amount__c`，也有对 `Order_Product__c` 的 rollup，比如 `Count_Product_Lines__c`；`packs/Salesforce-PingCAP-L2/objects/Order_Product__c.json` 已明确带 active 公式 `Product_Family__c`、`Product_Name__c`、`List_Price_Subtotal__c`、`Surplus__c`，以及 active rollup `Manday__c`；标准 line-item 这边也已有 active before-save Flow：`OpportunityLineItem_Product2_Autofill_From_Pricebook`、`OpportunityLineItem_ListPrice_Autofill_From_Pricebook`、`OpportunityLineItem_Net_Fees_Autocalc.flow.json`、`QuoteLineItem_Net_Fees_Autocalc.flow.json`。另外 `Order_Product__c` 还有 active validation `Canotlowerthanthequotedprice`。 |
| 当前主要差异 / 待补 / 疑似待补什么 | 当前对 `Order_Org_Auto_Set_Account_Create`、`Order_Org_Auto_Set_Account_Update`、`Order_Set_PLG_BD_Pool`、`contractOpportunityInset`、`RevRec_Set_PLG_BD_Pool` 做 current-tree 检索，在本地 pack 和 final merged pack 里仍是 `0 hits`；同时 `Revenue__c.Name` 与 custom line-item `Name` auto-number 仍未补。这里要特别保留边界：当前稳定支持证据主要来自 `标准 OpportunityLineItem / QuoteLineItem Flow` 和 `custom Order_Product__c / Revenue__c formula-rollup`，不能直接把它夸大成“custom line-item 全链路 exact-flow parity 已经齐了”。剩余 `OrderTrigger` / `RevenueTrigger` / custom line-item trigger residue 仍是 runtime boundary。 |
| 最先打到哪张报表/哪些字段 | 直接打 `837...` 这张 ARR/forecast 复合面，以及它背后的 `dws_salesforce_arr_summary`、current-month order MRRARR datasources。当前最敏感字段是 `arr_amount_usd`、`accurate_acv_amount`、`order_product_family`、`arr_usd_cd_rate_current_month`、`mrr_usd_cd_rate_finance`、`Recognized_Revenue_Amount__c`、`Amount_Before_Adjust__c`。 |
| 当前最稳动作 | 默认先按 `Order carry-over + Revenue parity + line-item parity` 处理。优先顺序仍然是：补 order/account carry-over exact-name Flow、补 `RevRec_Set_PLG_BD_Pool`、再补 custom `Name` auto-number，最后才把 residual finance trigger / custom line-item trigger 逻辑单列出来。 |

## L2 Parity Backlog Shortlist

如果现在要把研究结果直接转成
`先补哪几个`
，
最值得先开的不是一张超长总表，
而是下面这张短清单。

| 优先级 | exact-name gap / 机制 | 最先打到哪张报表 | 为什么先补 | 默认修复层 |
|---|---|---|---|---|
| `P1` | `Quote_update_nonstandard_conditions_checkbox` | `1733...` `pipeline data quality / cleanup monitor` | 直接碰 quote cleanup / nonstandard-term 语义，已经进入前台 quality 面 | `L2 Flow parity` |
| `P1` | `Quote_update_nonstandard_conditions_checkbox_2` | `1733...` `pipeline data quality / cleanup monitor` | 同上，是 `1733...` 最直接的 Quote exact-name 缺口之一 | `L2 Flow parity` |
| `P1` | `OpportunityShareToPersalesOwner` / `OpportunityUpdateShareToPerSalOwner` | `1733...`，次级 `aadb...` / `0f2...` | 会改 owner-team / opportunity quality 语义，且当前本地仍是 `0 hits` | `L2 Flow parity`，清完再看 `OpportunityTrigger` |
| `P1` | `Lead_StatusChangeTimestamp` 语义收窄 | `fd12...` `lead funnel / ICP path` | 当前不是完全缺失，而是本地 `Lead_Status_Duration` 语义过宽；直接影响 lifecycle 时间戳口径 | `L2 Flow parity` |
| `P1` | `Campaign_Member_Key_Message_Update` | `8c6f...` `campaign attribution / contact-opportunity touch`，次级 `fd12...` | attribution / response 语义目前最明确的 single-name missing Flow，影响最大且名字最确定 | `L2 Flow parity` |
| `P1` | `Account_Current_Order_Type` | `583...` `account + current/monthly order MRRARR composite`，次级 `690...` / `f9c4...` / `31605...` | 当前 account/tenant/shared-key 这条线最常出现、最像 current-month finance 与 tenant-bridge 复合面的漂移入口；`673... / 212...` 当前不再作为这条主实现的 front-door 证据 | `L2 Flow parity` |
| `P1` | `Order_Org_Auto_Set_Account_Create` / `Order_Org_Auto_Set_Account_Update` | `583...`、`837...`、`f9c4...` | 这是 order/account carry-over 的核心缺口，跨 current-month MRRARR、ARR summary、tenant bridge 三个面 | `L2 finance carry-over parity` |
| `P1` | `Order_Set_PLG_BD_Pool` | `837...`、`583...`、`f9c4...` | 会同时影响 finance segmentation 和 collections / revrec 邻近链路 | `L2 finance carry-over parity` |
| `P1` | `Collection_Set_PLG_BD_Pool` | `f9c4...`，次级 `salesforce_order_daily_view` / `monthly_revrec_collections` | 已明确证明本地 collections helper/rollup 在用，缺这条会直接让 pool 维度聚歪 | `L2 finance carry-over parity` |
| `P1` | `Collection_Amount_and_Payable_Amount_exc_tax` | `f9c4...`，次级 `salesforce_order_daily_view` / `salesforce_org_monthly_revrec` | 直接决定 exc-tax helper 字段 create 腿，影响 payable / collections 指标 | `L2 finance carry-over parity` |
| `P1` | `Collection_Amount_and_Payable_Amount_exc_tax_Update` | `f9c4...`，次级 `salesforce_order_daily_view` / `salesforce_org_monthly_revrec` | 同上，但更关键在 update 后口径是否持续正确 | `L2 finance carry-over parity` |
| `P1` | `Cloud_Registration_Source_from_Org_to_Collections` | `f9c4...`，次级 `690...` | 本地 order 有 peer flow，collections 这条仍 `0 hits`，直接影响 marketplace / tenant attribution | `L2 finance carry-over parity` |
| `P1` | `RevRec_Set_PLG_BD_Pool` | `837...`，次级 `f9c4...` | 是 revenue/revrec 侧最明确的 single-name finance exact gap | `L2 Flow parity` |
| `P2` | `Account_Partner_Sales_Owner_Set` | `673...`、`212...`，次级 `583...` | shared dimension 邻近缺口，但当前更像 owner / governance forecast 面先感知到的 parity hole | `L2 Flow parity` |
| `P2` | `Account_Contract_Valid_Message` | `673...` / `212...` | 更偏 account-governance / forecast surface，不如 current-order-type 直接打 current MRRARR 面 | `L2 Flow parity` |
| `P2` | `Revenue__c.Name` | `837...` 邻近 finance 链路 | 该补，但对核心 finance 指标的直接扭曲低于 status/carry-over helper 缺口 | `L2 auto-number parity` |
| `P2` | `Invoice_Collection__c.Name` | `f9c4...` 邻近 finance 链路 | 该补，但当前更像 record identity / notice parity，不是 metrics first-order driver | `L2 auto-number parity` |
| `P2` | custom line-item `Name` auto-number | `837...` / `583...` / `f9c4...` | 该补，但当前 line-item 更大的风险还是 carry-over / trigger residue，不是编号本身 | `L2 auto-number parity` |

使用原则：

- `P1`
  默认先开
  `L2 pack parity`
  项，不要先升级成 runtime 需求
- 只有同一报表面的
  `P1/P2 exact-name parity`
  清完以后还剩差异，
  才把 residual
  `Trigger`
  逻辑单列成
  `CM runtime boundary`

## Issue-Ready Backlog View

如果下一步是开 issue / 排期，
下面这张表最实用。

它只保留 4 个动作字段：

- 建议 owner 层
- 建议验收字段
- 本地先看哪些文件
- 什么时候才升级成 runtime 问题

| exact-name gap / 机制 | 建议 owner 层 | 建议验收字段 | 本地先看哪些文件 | 什么时候才升级成 runtime |
|---|---|---|---|---|
| `Quote_update_nonstandard_conditions_checkbox` | `L2 pack Flow` | `quote_service_start_date`, `quote_service_end_date`, nonstandard-term / cleanup 邻近字段在 `1733...` 面恢复稳定 | `packs/Salesforce-PingCAP-L2/objects/Quote.json`, `packs/Salesforce-PingCAP-L2/validation/standard_validation_rules.json`, `packs/Salesforce-PingCAP-L2/flows/Opportunity_Close_Date_Auto_Set.flow.json` | 同组 Quote exact-name parity 与 inactive validation 清完后仍有差异 |
| `Quote_update_nonstandard_conditions_checkbox_2` | `L2 pack Flow` | 同上；重点看 `1733...` cleanup 面是否仍漏 quote commercial 语义 | `packs/Salesforce-PingCAP-L2/objects/Quote.json`, `packs/Salesforce-PingCAP-L2/validation/standard_validation_rules.json` | 同上 |
| `OpportunityShareToPersalesOwner` / `OpportunityUpdateShareToPerSalOwner` | `L2 pack Flow` | `owner_team`, opportunity quality / owner-share 邻近语义在 `1733...`、`aadb...`、`0f2...` 稳定 | `packs/Salesforce-PingCAP-L2/flows/Std_OpportunityStageDerivedFields.flow.json`, `packs/Salesforce-PingCAP-L2/flows/Opportunity_Cloud_Order_Type_Set.flow.json`, `packs/Salesforce-PingCAP-L2/flows/Opportunity_Close_Date_Auto_Set.flow.json`, `packs/Salesforce-PingCAP-L2/pack.json` | exact-name Flow 补后仍需 Apex 才能完成 owner-share 语义 |
| `Lead_StatusChangeTimestamp` 语义收窄 | `L2 pack Flow` | `lead_status`, `lead_mql_timestamp`, `lead_iqm_timestamp`, lifecycle timestamp 语义在 `fd12...` / `dws_lead_timeline` 不再过宽 | `packs/Salesforce-PingCAP-L2/flows/Lead_Status_Duration.flow.json`, `packs/Salesforce-PingCAP-L2/flows/IQM_Completion_Flow.flow.json`, `packs/Salesforce-PingCAP-L2/objects/Lead.json` | 收窄本地 Flow 后仍有 lifecycle 行为只能由 trigger 承担 |
| `Campaign_Member_Key_Message_Update` | `L2 pack Flow` | `first_responded_date`, `campaign_member_status`, `contact_response_date`, `attributed_arr` 在 `8c6f...` 恢复稳定 | `packs/Salesforce-PingCAP-L2/flows/Lead_Set_First_And_Last_CampaignMember.flow.json`, `packs/Salesforce-PingCAP-L2/flows/Contact_Set_First_And_Last_CampaignMember.flow.json`, `packs/Salesforce-PingCAP-L2/flows/Std_ConvertLeadCampaignPreview.flow.json` | 同组 parity 补完后仍有 `Trigger_CampaignMember` 残余 |
| `Account_Current_Order_Type` | `L2 pack Flow` | `account_current_order_type`, `account_id`, `tenant_id`, `order_product_family` 在 `583...` / `f9c4...` / `31605...` 稳定，并把 `690...` 的 tenant-bridge 邻近漂移压下去 | `packs/Salesforce-PingCAP-L2/objects/Account.json`, `packs/Salesforce-PingCAP-L2/flows/Org_Set_Account.flow.json`, `packs/Salesforce-PingCAP-L2/autonumber/counters.json`, `packs/Salesforce-PingCAP-L2/autonumber/formats.json` | account-side exact-name parity 清完后 shared-key 仍漂 |
| `Order_Org_Auto_Set_Account_Create` / `Order_Org_Auto_Set_Account_Update` | `L2 pack Flow` | `account_id`, `accumulate_revenue_to_org_tenant_id`, `account_current_order_type`, `order_product_family` 在 `583...` / `837...` / `f9c4...` 稳定 | `packs/Salesforce-PingCAP-L2/objects/Order.json`, `packs/Salesforce-PingCAP-L2/flows/Cloud_Registration_Source_from_Org_to_Order.flow.json`, `packs/Salesforce-PingCAP-L2/flows/Order_Default_RevRec_Entity.flow.json` | carry-over 补后仍需 trigger 才能完成 account/org bridge |
| `Order_Set_PLG_BD_Pool` | `L2 pack Flow` | `plg_bd_pool`, finance segmentation 邻近字段在 `837...` / `583...` / `f9c4...` 恢复稳定 | `packs/Salesforce-PingCAP-L2/objects/Order.json`, `packs/Salesforce-PingCAP-L2/objects/Invoice_Collection__c.json`, `packs/Salesforce-PingCAP-L2/objects/Revenue__c.json` | 同组 order/revrec/collection carry-over 都补后仍有分群漂移 |
| `Collection_Set_PLG_BD_Pool` | `L2 pack Flow` | `plg_bd_pool_c`, `collections_status_c`, order-side cash/payable 聚合在 `f9c4...` / `monthly_revrec_collections` 稳定 | `packs/Salesforce-PingCAP-L2/objects/Invoice_Collection__c.json`, `packs/Salesforce-PingCAP-L2/objects/Order.json`, `packs/Salesforce-PingCAP-L2/validation/standard_validation_rules.json` | collection helper parity 补后仍有 metrics 漂移 |
| `Collection_Amount_and_Payable_Amount_exc_tax` / `_Update` | `L2 pack Flow` | `collections_amount_exc_tax_c`, `collections_amount_usd_exc_tax_c`, `payable_amount_usd_2_exc_tax_c`, `cash_collected_c` 在 `f9c4...` / `salesforce_order_daily_view` / `salesforce_org_monthly_revrec` 稳定 | `packs/Salesforce-PingCAP-L2/objects/Invoice_Collection__c.json`, `packs/Salesforce-PingCAP-L2/objects/Order.json`, `packs/Salesforce-PingCAP-L2/validation/standard_validation_rules.json` | helper-field parity 补后仍有 collected/payable timing 漂移 |
| `Cloud_Registration_Source_from_Org_to_Collections` | `L2 pack Flow` | `marketplace_c`, `tenant_id`, `account_current_order_type`、cloud-registration 邻近字段在 `f9c4...` / `690...` 稳定 | `packs/Salesforce-PingCAP-L2/objects/Invoice_Collection__c.json`, `packs/Salesforce-PingCAP-L2/objects/Order.json`, `packs/Salesforce-PingCAP-L2/flows/Cloud_Registration_Source_from_Org_to_Order.flow.json` | org-to-marketplace carry-over 补后仍有 tenant bridge 漂移 |
| `RevRec_Set_PLG_BD_Pool` | `L2 pack Flow` | `revenue_status`, `amount_before_adjust`, `Recognized_Revenue_Amount__c`, `arr_usd_cd_rate_current_month`, `mrr_usd_cd_rate_finance` 在 `837...` / `f9c4...` 稳定 | `packs/Salesforce-PingCAP-L2/objects/Revenue__c.json`, `packs/Salesforce-PingCAP-L2/objects/Order.json`, `packs/Salesforce-PingCAP-L2/flows/Order_Default_RevRec_Entity.flow.json` | revrec parity 补后仍有 revenue-side residual behavior |

一句话 owner 规则：

- 这张表里的行，默认 owner 都是
  `PingCAP L2 pack parity`
- 只有当
  `验收字段`
  在相应报表面还不稳定，
  且同组 exact-name parity 已补齐，
  才把它升级成
  `L0/L1/runtime` 问题

一句话使用方式：

- `pipeline / dq` 先看 `Opportunity + Quote`
- `lead funnel / attribution` 先看 `Lead + CampaignMember + Contact`
- `ARR / revrec / account composite` 先看 `Order + Account/Org + line-item`
- `PLG cloud funnel` 先看 `tenant/account bridge`，不要默认从 `Lead` 开始

## Report-Surface Issue Packs

如果下一步真的要开 issue，
最省摩擦的方式不是按对象开，
而是按
`front-door 报表面`
开一组小包。

下面这张表只保留
`现在就适合开的 L2 parity 项`
。

| 报表面 | 现在打成一包最合适的 issue | 建议先验收哪些字段 | 默认 owner 层 |
|---|---|---|---|
| `1733...` `pipeline data quality / cleanup monitor` | `Quote_update_nonstandard_conditions_checkbox`、`Quote_update_nonstandard_conditions_checkbox_2`、`OpportunityShareToPersalesOwner` / `OpportunityUpdateShareToPerSalOwner` | `quote_service_start_date`、`quote_service_end_date`、`owner_team`、opportunity quality / cleanup 邻近字段 | `PingCAP L2 Opportunity/Quote parity` |
| `8c6f...` `campaign attribution / contact-opportunity touch` | `Campaign_Member_Key_Message_Update` | `first_responded_date`、`campaign_member_status`、`contact_response_date`、`attributed_arr` | `PingCAP L2 CampaignMember parity` |
| `583...` `account + current/monthly order MRRARR composite` | `Account_Current_Order_Type`、`Account_Partner_Sales_Owner_Set`、`Order_Org_Auto_Set_Account_Create` / `_Update`、`Order_Set_PLG_BD_Pool` | `account_current_order_type`、`account_id`、`tenant_id`、`order_product_family`、`arr_usd_cd_rate_current_month`、`mrr_usd_cd_rate_finance` | `PingCAP L2 Account/Order parity` |
| `837...` `ARR summary + regional/company forecast` | `Order_Org_Auto_Set_Account_Create` / `_Update`、`Order_Set_PLG_BD_Pool`、`RevRec_Set_PLG_BD_Pool` | `arr_amount_usd`、`accurate_acv_amount`、`arr_usd_cd_rate_current_month`、`mrr_usd_cd_rate_finance`、`Recognized_Revenue_Amount__c`、`Amount_Before_Adjust__c` | `PingCAP L2 finance carry-over parity` |
| `f9c4...` `activated-order / monthly revrec by account+tenant` | `Order_Org_Auto_Set_Account_Create` / `_Update`、`Order_Set_PLG_BD_Pool`、`Collection_Set_PLG_BD_Pool`、`Collection_Amount_and_Payable_Amount_exc_tax` / `_Update`、`Cloud_Registration_Source_from_Org_to_Collections`、`RevRec_Set_PLG_BD_Pool` | `order_product_family`、`account_current_order_type`、`tenant_id`、`plg_bd_pool_c`、`collections_amount_exc_tax_c`、`payable_amount_usd_2_exc_tax_c`、`cash_collected_c`、`marketplace_c` | `PingCAP L2 Order/IC/Revenue parity` |

一个实用规则：

- 同一张报表面里，
  先把这张表里的
  `L2 parity`
  小包开完
- 再看同面 residual
  `trigger/runtime`
  要不要单列出来

这样开 issue 的好处是：

- `1733...`
  不会把 Quote cleanup、Opportunity owner-share、trigger residue 混成一张大杂烩票
- `8c6f...`
  会先把最确定的
  `Campaign_Member_Key_Message_Update`
  独立出来
- `583... / 837... / f9c4...`
  会自然形成
  `Account/Order/Collection/Revenue`
  的 finance carry-over 包，
  比按单对象散开更接近真实前台 blast radius

## Issue Drafts: First Two Report Surfaces

如果下一步要真的去开票，
当前最成熟、最不需要再补背景说明的，
就是下面这两包。

### Draft 1: `1733...` `pipeline data quality / cleanup monitor`

建议标题：

`[L2 Parity] Restore Opportunity/Quote cleanup semantics for report 1733 pipeline data quality surface`

建议问题定义：

- `1733...`
  这张前台 data-quality / cleanup 面，
  当前直接消费
  `Opportunity`
  的 stage / forecast / owner-team / close/launch 语义，
  以及
  `Quote`
  的 service-window / nonstandard-term 邻近语义。
- 本地 substrate 已有，
  但当前树里对
  `Quote_update_nonstandard_conditions_checkbox`
  、
  `Quote_update_nonstandard_conditions_checkbox_2`
  、
  `OpportunityShareToPersalesOwner`
  /
  `OpportunityUpdateShareToPerSalOwner`
  仍是
  `0 hits`
  。
- 因此这张报表当前更像
  `L2 Opportunity/Quote exact-flow parity`
  缺口，
  不是
  `CM runtime 不会做 pipeline semantics`
  。

建议 scope：

- 补齐
  `Quote_update_nonstandard_conditions_checkbox`
  和
  `_2`
  的 L2 parity。
- 补齐
  `OpportunityShareToPersalesOwner`
  与高置信 sibling
  `OpportunityUpdateShareToPerSalOwner`
  的 L2 parity。
- 对齐已存在但 inactive 的 Quote/Opportunity 邻近 validation 激活态，
  前提是确认 PingCAP 当前口径仍需与 live 一致。
- 本 issue 不直接承诺清空
  `OpportunityTrigger` /
  `QuoteTrigger`
  残余逻辑；
  只有同面 exact-flow parity 补完后仍有稳定残差，才升级 runtime。

建议验收字段：

- `owner_team`
- `stage_name`
- `forecast_category`
- `probability`
- `close_date`
- `launch_date`
- `quote_service_start_date`
- `quote_service_end_date`
- nonstandard-term / quote cleanup 邻近字段

建议本地先看：

- `packs/Salesforce-PingCAP-L2/flows/Std_OpportunityStageDerivedFields.flow.json`
- `packs/Salesforce-PingCAP-L2/flows/Opportunity_Cloud_Order_Type_Set.flow.json`
- `packs/Salesforce-PingCAP-L2/flows/Opportunity_Close_Date_Auto_Set.flow.json`
- `packs/Salesforce-PingCAP-L2/objects/Quote.json`
- `packs/Salesforce-PingCAP-L2/validation/standard_validation_rules.json`

什么时候才升级成 runtime：

- 当以上 exact-name Flow parity 与相关 activation-state mismatch 清完后，
  `1733...`
  仍稳定出现
  `owner_team`
  /
  quote cleanup
  语义漂移，
  再单列
  `OpportunityTrigger` /
  `QuoteTrigger`
  runtime 设计题。

### Draft 2: `8c6f...` `campaign attribution / contact-opportunity touch`

建议标题：

`[L2 Parity] Restore CampaignMember response/involvement semantics for report 8c6f attribution surface`

建议问题定义：

- `8c6f...`
  这张 attribution 前台面，
  直接吃
  `CampaignMember`
  的
  `first_responded_date`
  、
  response / involvement、
  `contact_response_date`
  和
  `attributed_arr`
  这条链。
- 本地 `CampaignMember` first/last-touch substrate 已在，
  `convertLead`
  也已显式支持 attribution preview / child relink；
  当前最确定的缺口仍是
  `Campaign_Member_Key_Message_Update`
  在本地 pack 与 final merged pack 中
  `0 hits`
  。
- 因此这张报表当前最适合先开成
  `L2 CampaignMember exact-flow parity`
  issue，
  不要一上来就把它扩成
  `Campaign` 主表 gap
  或
  `CM runtime`
  题。

建议 scope：

- 补齐
  `Campaign_Member_Key_Message_Update`
  的 L2 parity。
- 用同一张前台面验证 response/involvement 语义是否恢复稳定。
- Contact stitching / residual `Trigger_CampaignMember` /
  Contact trigger surface
  先明确记成后续升级条件，不并入本票。

建议验收字段：

- `first_responded_date`
- `campaign_member_status`
- `has_responded`
- `is_contact_involved`
- `contact_involvement_level`
- `contact_response_date`
- `attributed_arr`
- `attributed_acv`

建议本地先看：

- `packs/Salesforce-PingCAP-L2/flows/Lead_Set_First_And_Last_CampaignMember.flow.json`
- `packs/Salesforce-PingCAP-L2/flows/Contact_Set_First_And_Last_CampaignMember.flow.json`
- `packs/Salesforce-PingCAP-L2/flows/Std_ConvertLeadCampaignPreview.flow.json`
- `packs/Salesforce-PingCAP-L2/actions/invocable_standard_actions.json`
- `packs/Salesforce-PingCAP-L2/objects/CampaignMember.json`

什么时候才升级成 runtime：

- 当
  `Campaign_Member_Key_Message_Update`
  parity 补齐后，
  `8c6f...`
  仍稳定出现
  `first_responded_date`
  /
  response / involvement / attribution
  漂移，
  再把 residual
  `Trigger_CampaignMember`
  或 Contact trigger surface 单列成 runtime 题。

### Draft 3: `583...` `account + current/monthly order MRRARR composite`

建议标题：

`[L2 Parity] Restore Account/Order shared-key semantics for report 583 current-month MRRARR surface`

建议问题定义：

- `583...`
  这张前台复合面，
  直接吃
  `Account`
  shared-key、
  `Org`
  bridge、
  `Order`
  current-month finance，
  以及
  `order_product_family`
  这条链。
- 当前本地桥件并不是空白，
  但
  `Account_Current_Order_Type`
  、
  `Account_Partner_Sales_Owner_Set`
  、
  `Order_Org_Auto_Set_Account_Create`
  /
  `_Update`
  、
  `Order_Set_PLG_BD_Pool`
  仍是
  `0 hits`
  。
- 因此这张报表当前最像
  `L2 Account/Order exact-flow parity`
  缺口，
  不是先开
  `AccountTrigger` /
  `OrderTrigger`
  runtime 票。

建议 scope：

- 补齐
  `Account_Current_Order_Type`
  parity。
- 补齐
  `Account_Partner_Sales_Owner_Set`
  parity。
- 补齐
  `Order_Org_Auto_Set_Account_Create`
  /
  `_Update`
  parity。
- 补齐
  `Order_Set_PLG_BD_Pool`
  parity。
- custom line-item `Name` auto-number
  与 residual trigger
  不并入本票，保留为后续升级条件。

建议验收字段：

- `account_number`
- `fy26_icp`
- `fy26_segmentation`
- `account_current_order_type`
- `account_id`
- `tenant_id`
- `order_product_family`
- `arr_usd_cd_rate_current_month`
- `mrr_usd_cd_rate_finance`

建议本地先看：

- `packs/Salesforce-PingCAP-L2/objects/Account.json`
- `packs/Salesforce-PingCAP-L2/flows/Org_Set_Account.flow.json`
- `packs/Salesforce-PingCAP-L2/objects/Order.json`
- `packs/Salesforce-PingCAP-L2/flows/Cloud_Registration_Source_from_Org_to_Order.flow.json`
- `packs/Salesforce-PingCAP-L2/flows/Order_Default_RevRec_Entity.flow.json`

什么时候才升级成 runtime：

- 当以上 account/order exact-flow parity 清完后，
  `583...`
  仍稳定出现
  `account_current_order_type`
  /
  `order_product_family`
  /
  current-month MRRARR
  漂移，
  再把 residual
  `AccountTrigger`
  /
  `OrderTrigger`
  /
  line-item trigger
  单列成 runtime 题。

### Draft 4: `837...` `ARR summary + regional/company forecast`

建议标题：

`[L2 Parity] Restore Order/Revenue finance carry-over semantics for report 837 ARR summary surface`

建议问题定义：

- `837...`
  这张 ARR / forecast 复合面，
  把
  `Opportunity`
  的 ARR/forecast、
  `Order`
  的 current-month finance，
  `Revenue__c`
  的 revrec helper，
  以及 line-item product-family
  混在同一个 front-door surface。
- 当前本地已经有
  `Order_Default_RevRec_Entity`
  、
  `Order`
  对
  `Revenue__c`
  的 rollup、
  和 custom line-item 公式/rollup；
  但
  `Order_Org_Auto_Set_Account_Create`
  /
  `_Update`
  、
  `Order_Set_PLG_BD_Pool`
  、
  `RevRec_Set_PLG_BD_Pool`
  仍是
  `0 hits`
  。
- 所以这张报表当前最像
  `L2 finance carry-over + revrec parity`
  缺口，
  不是先开
  `RevenueTrigger`
  runtime 票。

建议 scope：

- 补齐
  `Order_Org_Auto_Set_Account_Create`
  /
  `_Update`
  parity。
- 补齐
  `Order_Set_PLG_BD_Pool`
  parity。
- 补齐
  `RevRec_Set_PLG_BD_Pool`
  parity。
- `Revenue__c.Name`
  和 custom line-item `Name`
  auto-number 不并入本票，
  保留为后续 metadata parity 条目。

建议验收字段：

- `arr_amount_usd`
- `accurate_acv_amount`
- `order_product_family`
- `arr_usd_cd_rate_current_month`
- `mrr_usd_cd_rate_finance`
- `Recognized_Revenue_Amount__c`
- `Amount_Before_Adjust__c`

建议本地先看：

- `packs/Salesforce-PingCAP-L2/objects/Order.json`
- `packs/Salesforce-PingCAP-L2/objects/Revenue__c.json`
- `packs/Salesforce-PingCAP-L2/objects/Order_Product__c.json`
- `packs/Salesforce-PingCAP-L2/flows/Order_Default_RevRec_Entity.flow.json`
- `packs/Salesforce-PingCAP-L2/flows/Cloud_Registration_Source_from_Org_to_Order.flow.json`

什么时候才升级成 runtime：

- 当 order/revenue exact-flow parity 清完后，
  `837...`
  仍稳定出现
  `Recognized_Revenue_Amount__c`
  /
  `Amount_Before_Adjust__c`
  /
  `order_product_family`
  漂移，
  再把 residual
  `OrderTrigger`
  /
  `RevenueTrigger`
  /
  custom line-item trigger
  单列成 runtime 题。

### Draft 5: `f9c4...` `activated-order / monthly revrec by account+tenant`

建议标题：

`[L2 Parity] Restore Order/Invoice Collection/Revenue bridge semantics for report f9c4 activated-order revrec surface`

建议问题定义：

- `f9c4...`
  这张 front-door finance 面，
  直接把
  activated-order、
  monthly revrec、
  tenant/account bridge、
  `order_product_family`
  和 collections helper
  拼在一起。
- 当前本地 `Invoice_Collection__c`
  helper 字段和 `Order`
  侧 rollup 已经不少，
  但 live 高价值 exact-name 缺口仍很清楚：
  `Collection_Set_PLG_BD_Pool`
  、
  `Collection_Amount_and_Payable_Amount_exc_tax`
  /
  `_Update`
  、
  `Cloud_Registration_Source_from_Org_to_Collections`
  、
  以及同组
  `Order_Org_Auto_Set_Account_*`
  /
  `Order_Set_PLG_BD_Pool`
  /
  `RevRec_Set_PLG_BD_Pool`
  。
- 所以这张报表当前最像
  `L2 Order/IC/Revenue carry-over parity`
  缺口，
  不是先开
  `OrderTrigger` /
  `RevenueTrigger`
  runtime 票。

建议 scope：

- 补齐
  `Order_Org_Auto_Set_Account_Create`
  /
  `_Update`
  parity。
- 补齐
  `Order_Set_PLG_BD_Pool`
  parity。
- 补齐
  `Collection_Set_PLG_BD_Pool`
  parity。
- 补齐
  `Collection_Amount_and_Payable_Amount_exc_tax`
  /
  `_Update`
  parity。
- 补齐
  `Cloud_Registration_Source_from_Org_to_Collections`
  parity。
- 补齐
  `RevRec_Set_PLG_BD_Pool`
  parity。
- `Invoice_Collection__c.Name`
  auto-number 不并入本票。

建议验收字段：

- `tenant_id`
- `tenant_name`
- `account_current_order_type`
- `order_product_family`
- `mrr_usd_cd_rate_finance`
- `collections_status_c`
- `invoice_status_c`
- `cash_collected_c`
- `collections_amount_exc_tax_c`
- `payable_amount_usd_2_exc_tax_c`
- `plg_bd_pool_c`
- `marketplace_c`

建议本地先看：

- `packs/Salesforce-PingCAP-L2/objects/Invoice_Collection__c.json`
- `packs/Salesforce-PingCAP-L2/objects/Order.json`
- `packs/Salesforce-PingCAP-L2/objects/Revenue__c.json`
- `packs/Salesforce-PingCAP-L2/flows/Cloud_Registration_Source_from_Org_to_Order.flow.json`
- `packs/Salesforce-PingCAP-L2/flows/Order_Default_RevRec_Entity.flow.json`

什么时候才升级成 runtime：

- 当 order / collection / revrec exact-flow parity 清完后，
  `f9c4...`
  仍稳定出现
  collections helper
  /
  marketplace bridge
  /
  monthly revrec
  漂移，
  再把 residual
  `OrderTrigger`
  /
  `RevenueTrigger`
  /
  line-item trigger
  单列成 runtime 题。

### Draft 6: `fd12...` `lead funnel / ICP path`

建议标题：

`[L2 Parity] Narrow Lead lifecycle timestamp semantics for report fd12 lead funnel surface`

建议问题定义：

- `fd12...`
  这张前台 lead funnel / ICP 面，
  直接吃
  `Lead`
  lifecycle、
  `lead_mql_timestamp`、
  `lead_iqm_timestamp`、
  campaign path、
  以及 lead-account stitching。
- 当前本地 `Lead` substrate 已在：
  `IQM_Completion_Flow`
  、
  `Lead_Status_Duration`
  、
  `Std_ConvertLeadCampaignPreview`
  都已落地。
- 但
  `Lead_StatusChangeTimestamp`
  目前仍只是近似承接，
  因为本地 `Lead_Status_Duration`
  只要
  `Status IsChanged`
  就写时间戳，
  而 live 语义更窄；
  同时 Lead 长尾 assignment / reminder / notification parity 仍未完全追回。
- 所以这张报表当前最像
  `L2 Lead lifecycle parity`
  缺口，
  不是先开
  `LeadTrigger` /
  `LeadAITrigger`
  runtime 票。

建议 scope：

- 先把
  `Lead_StatusChangeTimestamp`
  的本地语义收窄到接近 live。
- 在同一票里记录 Lead 长尾 assignment / reminder / notification parity
  仍需继续追回，
  但不承诺一次性清完所有长尾 Lead Flow。
- `Campaign_Member_Key_Message_Update`
  不并入本票，
  继续保留在
  `8c6f...`
  attribution 包里。

建议验收字段：

- `lead_status`
- `lead_mql_timestamp`
- `lead_iqm_timestamp`
- `lead_surrogate_key`
- `first_touch_campaign`
- `last_touch_before_iqm`
- `last_touch_before_opp_creation`

建议本地先看：

- `packs/Salesforce-PingCAP-L2/flows/Lead_Status_Duration.flow.json`
- `packs/Salesforce-PingCAP-L2/flows/IQM_Completion_Flow.flow.json`
- `packs/Salesforce-PingCAP-L2/flows/Std_ConvertLeadCampaignPreview.flow.json`
- `packs/Salesforce-PingCAP-L2/actions/invocable_standard_actions.json`
- `packs/Salesforce-PingCAP-L2/objects/Lead.json`

什么时候才升级成 runtime：

- 当
  `Lead_StatusChangeTimestamp`
  语义收窄、
  且同面 Lead lifecycle 邻近 parity 清理后，
  `fd12...`
  仍稳定出现
  lifecycle timestamp
  /
  lead path
  漂移，
  再把 residual
  `LeadTrigger`
  /
  `LeadAITrigger`
  单列成 runtime 题。

### Draft 7: `690...` `PLG signup / billing-capable cloud funnel`

建议标题：

`[L2 Parity] Restore Account/Org tenant-bridge semantics for report 690 PLG signup surface`

建议问题定义：

- `690...`
  这张 PLG / billing-capable cloud funnel 面，
  当前没有强证据说明它直接吃
  `Lead`
  front door；
  更像是先吃
  `Account / Org / tenant bridge`
  再和 cloud signup / billing-capable user 拼起来。
- 本地 shared-key substrate 已在：
  `Account_ID__c`
  auto-number、
  `Org_Set_Account`
  以及下游
  `dws_cloud_tenants_basicinfo`
  都已经成立。
- 但
  `Account_Current_Order_Type`
  、
  `Account_Partner_Sales_Owner_Set`
  、
  `Account_Contract_Valid_Message`
  仍是
  `0 hits`
  ，
  同时 order-side carry-over 也可能反向污染 tenant/account bridge。
- 所以这张报表当前最像
  `Account/Org shared-key parity + order-side contamination cleanup`
  问题，
  不是先开
  `Lead`
  或泛化 runtime 票。

建议 scope：

- 先补
  `Account_Current_Order_Type`
  parity。
- 记录
  `Account_Partner_Sales_Owner_Set`
  与
  `Account_Contract_Valid_Message`
  作为同面邻近 parity。
- 把
  `Order_Org_Auto_Set_Account_*`
  对 tenant bridge 的回流污染
  明确写成本票依赖/邻近项，
  但不把所有 finance carry-over 一次性并进来。

建议验收字段：

- `tenant_id`
- `tenant_name`
- `tenant_email`
- `tenant_region`
- `account_id`
- `account_name`
- `account_current_order_type`
- `account_segmentation`

建议本地先看：

- `packs/Salesforce-PingCAP-L2/objects/Account.json`
- `packs/Salesforce-PingCAP-L2/autonumber/counters.json`
- `packs/Salesforce-PingCAP-L2/autonumber/formats.json`
- `packs/Salesforce-PingCAP-L2/flows/Org_Set_Account.flow.json`
- `packs/Salesforce-PingCAP-L2/flows/Cloud_Registration_Source_from_Org_to_Order.flow.json`

什么时候才升级成 runtime：

- 当
  `Account_Current_Order_Type`
  和同面 shared-key parity 清理后，
  `690...`
  仍稳定出现
  tenant/account bridge
  漂移，
  再把 residual
  `AccountTrigger`
  或只存在于 trigger 的 bridge logic
  单列成 runtime 题。

### Draft 8: `673... / 212...` `account + forecast surfaces`

建议标题：

`[L2 Parity] Restore Account dimension governance semantics for 673/212 forecast surfaces`

建议问题定义：

- `673...`
  和
  `212...`
  这两张 front-door account / forecast 面，
  当前直接点
  `account_number`
  、
  `fy26_icp`
  、
  `fy26_segmentation`
  、
  `account_id`
  、
  `account_name`
  、
  `account_industry`
  、
  `tenant_id`
  、
  `tenant_region`
  这组 shared-dimension / forecast 字段。
- 本地 account/org substrate 已在：
  `Account_ID__c`
  auto-number、
  `Org_Set_Account`
  、
  `salesforce_accounts`
  /
  `dim_org`
  /
  `dim_tenant`
  这组链路都已有明确证据。
- 但
  `Account_Contract_Valid_Message`
  、
  `Account_Current_Order_Type`
  、
  `Account_Partner_Sales_Owner_Set`
  当前仍是
  `0 hits`
  ，
  因此这两张报表当前最像
  `L2 Account dimension / governance parity`
  缺口，
  不是先开
  `AccountTrigger`
  runtime 票。

建议 scope：

- 补齐
  `Account_Current_Order_Type`
  parity。
- 补齐
  `Account_Partner_Sales_Owner_Set`
  parity。
- 补齐
  `Account_Contract_Valid_Message`
  /
  `_1`
  邻近的 account-governance parity。
- tenant bridge 邻近漂移保留为第二层 cleanup，
  不把所有 order-side carry-over 一次性并入本票。

建议验收字段：

- `account_number`
- `fy26_icp`
- `fy26_segmentation`
- `account_id`
- `account_name`
- `account_industry`
- `tenant_id`
- `tenant_region`
- `account_current_order_type`
- account contract-valid / governance 邻近字段

建议本地先看：

- `packs/Salesforce-PingCAP-L2/objects/Account.json`
- `packs/Salesforce-PingCAP-L2/autonumber/counters.json`
- `packs/Salesforce-PingCAP-L2/autonumber/formats.json`
- `packs/Salesforce-PingCAP-L2/flows/Org_Set_Account.flow.json`
- `packs/Salesforce-PingCAP-L2/objects/Contract.json`

什么时候才升级成 runtime：

- 当 account-side exact-flow parity 清理后，
  `673... / 212...`
  仍稳定出现
  account dimension
  /
  forecast snapshot
  /
  governance
  漂移，
  再把 residual
  `AccountTrigger`
  单列成 runtime 题。

再补一个这轮宽扫后的边界结论：

- 按 `2026-01-01` 到 `2026-07-01`
  的
  `JOBS_BY_PROJECT`
  去扫
  `requestor = looker_studio`
  且命中
  `dws_marketing.*`
  / `dwh_marketing.*`
  / `anls_marketing.*`
  的作业，
  当前稳定只看到上面这两张 marketing report surface：
  `fd12...`
  和
  `8c6f...`
- 其中
  `fd12...`
  会直接命中 marketing mart
  `dws_icp_summary`
  ，以及早期的
  `dws_lead_timeline` /
  `anls_marketing.dim_lead`
- `8c6f...`
  虽然业务语义上是 marketing attribution，
  但在
  `referenced_tables`
  里更常展开成
  `salesforce campaign / campaign_member / contact / lead / opportunity_contact_role / org_c / account`
  和
  `dwh_business_operations.salesforce_opportunities`
  这类底层依赖，
  不一定保留
  `dws_marketing.dws_campaign_attribution`
  这一层名字
- 当前没有看到
  `requestor = looker_studio`
  直接命中
  `gcp-digital-bi.dwh_marketing.salesforce_leads`
  的证据

所以现在最稳的读法是：

- governed marketing surface 已经基本收敛到
  `fd12...`
  和
  `8c6f...`
  这两条
- `salesforce_leads`
  更像上游 warehouse / mart 供给层，
  而不是已经被直接坐实的 Looker Studio 前台 surface

还有一个现在值得单独记住的本地支持信号：

- `packs/Salesforce-PingCAP-L2/actions/invocable_standard_actions.json`
  里的 `convertLead`
  已显式声明
  `previewFlowDeveloperName = Std_ConvertLeadCampaignPreview`
- 同一动作还给 `CampaignMember`
  开了内部读取范围，理由写得很直接：
  `Lead Convert owns lookup of campaign memberships for primary campaign attribution and child relink after conversion.`

这说明在
`Lead -> Contact / Account / Opportunity`
转换这条链上，
CM 已经把
`campaign attribution preview`
和
`child relink`
当成标准动作的一部分承接了，
不应再把 attribution 语义整体误读成
`CM 完全没接`。

所以现在如果要用一句话讲：

- `Opportunity / Quote`
  的问题最容易先被 pipeline-quality / forecast / ARR summary 使用者看到。
- `Lead / CampaignMember`
  的问题最容易先被 lead timeline / ICP / attribution 分析使用者看到。
- `Order / Revenue__c / Invoice_Collection__c / Org__c`
  的问题最容易先被 revrec / billing / finance summary 使用者看到。
- `Account / Org__c`
  的问题最容易先被 account segmentation / tenant lookup / customer identity 使用者看到。

这里也要保留边界：

- 这些用户证据代表
  `谁在直接查询当前面`
  ，不是完整的 owner registry
- 但它已经明显强于
  `只知道某个 mart 会受影响`
  这种纯抽象说法

## 5. 我们当前最确定什么

下面这些结论，当前证据强度最高：

1. `CM 不是平台空白`
   已经有明确本地证据表明：
   formula / validation / rollup / record-triggered Flow /
   部分 auto-number
   都在本地 pack 中真实存在并被使用。
2. `当前多数 gap 不是纯能力缺口`
   最常见的还是：
   `activation-state mismatch`
   和
   `exact named missing mechanisms`。
3. `三组最值得先修`
   仍然是：
   `Pipeline / Forecast / Opportunity Quality`
   `Lead Funnel / Qualification`
   `Order / ARR / RevRec / Collections`
   因为它们的爆炸半径和证据强度都最高。
4. `真实平台边界主要在 Apex`
   现阶段最像
   `CM 目前真没支持`
   的，仍然是 live Salesforce 里还没迁出的
   `Apex trigger`
   逻辑。
5. `本地有 / 本地没有`
   已经能落到文件级证据：
   一批关键 Flow / validation / auto-number 已确认 `FOUND`，
   另一批 exact-name gap 已确认 `MISSING`。

## 6. 还没有完全闭环什么

下面这些不是没有结论，而是要明确它们的证据边界：

1. `完整 dashboard / owner 清单`
   当前 repo 里明确写出来的 dashboard 只有一个：
   `Opportunity Data Quality Monitoring`。
   owner 也明确写在 dbt exposure 里：
   `Chen Du <chen.du@pingcap.com>`。
   进一步核对 clone 下来的 BI repo 以后，这个边界还能说得更具体：
   `digital-bi-dbt` 当前 checkout 里只有一个
   `dbt/models/**/exposures.yml`
   ，也就是 business-operations 这份；
   `looker-schema` 当前 checkout 里也没有额外的 CRM
   `.dashboard.lookml`
   文件。
   当前 checked-out Looker repo 里，CRM 相关的直接 Explore 入口也只有
   3 个：
   `crm_account`、
   `salesforce_oppo`、
   和 `cloud-lead-pipeline-insight` 里的 `salesforce_lead`。
   其他报表组目前更多还是靠
   `Looker Explore 名字 + dbt mart lineage`
   来定位影响面。
2. `营销与财务的 owner 级消费面`
   `Campaign Attribution / ICP Analysis`
   和
   `Order / ARR / RevRec / Collections`
   的业务语义已经很清楚，
   但还没在当前 repo 快照里拿到完整 owner 级报表清单。
   不过两组现在证据强度已经不一样了：
   marketing 这边当前 clone 下来的 marts 目录基本还是
   `SQL models only`
   ，没有额外 exposure/schema/owner 元数据层；
   finance 这边在 repo 外层还能拿到
   `pingcap-datalake`
   的 curated contract / orchestration 证据，
   以及
   `netforce-hub`
   对 `monthly_revrec_orders` / `monthly_revrec_collections`
   的直接查询代码；
   而且在 `digital-bi-dbt` 自己的 finance 目录里，
   `monthly_cloud_revrec/sources.yml`
   已经把
   `monthly_revrec_orders`
   /
   `monthly_revrec_collections`
   定义成 Python-model source，
   `monthly_cloud_billing_revrec.py`
   还会直接读取
   `salesforce_org_monthly_revrec`
   和
   `salesforce_order_daily_view`
   再把结果落回这些 revrec outputs；
   而且这条链现在已经能落到字段级：
   `salesforce_org_monthly_revrec`
   先把
   `accumulate_revenue_to_org_tenant_id`,
   `account_id`,
   `region`,
   `payment_type`,
   `invoice_amount`
   这些 org-month 语义拼好，
   `salesforce_order_daily_view`
   再提供
   `order_service_start_date`,
   `order_service_end_date`,
   `accumulated_revenue`,
   `accumulated_revenue_before_adjust`,
   `accumulated_credit_amount`,
   `order_net_fees`
   这些 order-day 语义，
   最后
   `monthly_cloud_billing_revrec.py`
   写成
   `monthly_revrec_collections`
   的
   `payment_type`,
   `invoice_amount`,
   `collections_from`
   和
   `monthly_revrec_orders`
   的
   `revenue_amount`,
   `adjusted_revenue_amount`,
   `billing_allocation_amount`,
   `is_order_closing`
   等输出列；
   另外
   `cp_order_monthly_revrec`
   还有一个很重要的时间分层：
   historical months 走
   `salesforce_revrec`
   ，current month 优先走
   `monthly_revrec_orders`
   ，而且同一
   `order_id + bill_month`
   如果两边都有数据，会优先取
   `monthly_revrec_orders`
   这侧。
   所以 finance 线的症状不能只按“哪个模型坏了”看，
   还要先区分
   `历史月 revenue 语义漂移`
   还是
   `当月 billing/order allocation 语义漂移`；
   marketing 这边当前仍主要停在
   `Looker Explore + dbt mart semantics`
   这一层。
3. `Lead / Opportunity / Invoice_Collection` 的剩余 Flow 长尾
   我们已经拿到一部分 exact-name gap，
   但还有一部分 reminder / notification / assignment /
   invoice-notice 类 Flow 仍然属于
   `name clue / unresolved`
   状态。
   不过这轮定名核对后，证据强度又收紧了一层：
   `Lead_StatusChangeTimestamp`
   不该再读成单纯 unresolved 候选了：
   历史 `MetaDrivenPlatform4AI`
   tenant flow JSON 和 `picklist_tags.json`
   已经把 live 语义补实成
   `Lead` 上的 `RecordBeforeSave` `CreateAndUpdate` Flow，
   仅当 `Status` 进入 `working_or_later` 时才写
   `Date_Status_Changed__c`；
   当前本地 pack 虽然没有同名定义，
   但已经有一条 active 的
   `Lead_Status_Duration`
   会在 `Status IsChanged`
   时一律重写 `Date_Status_Changed__c`。
   所以它更像
   `CM 已支持 + 本地有近似承接，但语义过宽的 parity mismatch`
   ，不是默认应归到
   `CM 真没能力`
   或
   `名字还没搞清楚`
   的那类；
   当前 checked-out BI 证据里，
   最直接命中的字段仍是
   `stg_salesforce_lead.date_status_changed`；
   但这轮对
   `digital-bi-dbt`
   /
   `looker-schema`
   的 repo 内搜索并没有把它继续坐实到
   `salesforce_leads.sql`、
   `dws_lead_timeline.sql`、
   `dws_icp_summary.sql`
   或 Looker `salesforce_lead`，
   所以更稳说法应是
   `staging/raw parity 已证实，命名 marketing mart blast radius 仍待补证`
   ，而不是直接把它说成这些 marketing 模型的已确认驱动字段；
   而且这条边界不是只来自当前 checkout：
   后续对
   `ywang-official/digital-bi-dbt`
   和
   `pingcap-inc/dbt-dev`
   的 GitHub REST code search
   也只在
   `stg_salesforce_lead.sql`
   命中
   `date_status_changed`；
   相比之下，
   `lead_mql_timestamp` /
   `lead_iqm_timestamp` /
   `attributed_arr` /
   `first_touch_campaign`
   这些字段则能继续命中
   `salesforce_leads.sql`、
   `dws_lead_timeline.sql`、
   `dws_campaign_attribution.sql`
   和
   `dws_icp_summary.sql`，
   所以这次边界是有 cross-repo 佐证的；
   而且这条边界现在还有 live BigQuery 佐证：
   `gcp-digital-bi`
   `us-west2`
   下的
   `dwh_marketing.salesforce_leads`
   真实 schema
   只看到
   `lead_mql_timestamp`,
   `lead_iqm_timestamp`,
   `lead_status`,
   `contact_status`
   ，没有
   `date_status_changed`
   或
   `most_recent_working_status_date`；
   与此同时，
   `dws_marketing.dws_lead_timeline`
   有
   `734,525`
   行，
   `dws_marketing.dws_icp_summary`
   有
   `1,861`
   行，
   说明这条营销分析链是真实在跑的，但当前直接承接的确不是
   `date_status_changed`
   这列；
   `Opportunity_Stage_To_Lunched`
   则应改读成
   `本地已存在但 runtime 有 bug 的高信号面`
   ，不再算 unresolved exact-name gap；
   `OpportunityShareToPersalesOwner`
   现在变成最强的 Opportunity exact-name 未补候选，
   因为 `migration_audit.csv` #1749 直接点名了它，
   历史 `MetaDrivenPlatform4AI` trigger automation 设计文档也把它列进了
   `Opportunity` 的 `RecordAfterSave` 生产 flow 清单，
   但这里要带一个新的 caveat：
   `#1749` 的修复 commit 说明这条 exact flow 本身是
   `recordTriggerType=Create`
   ，PATCH/update 场景应走 sibling
   `OpportunityUpdateShareToPerSalOwner`；
   所以当前最稳读法不是“#1749 直接证明 update flow 缺失”，
   而是“历史生产里至少确认存在一条 create-flow，
   且很可能还有一条 update-sibling，
   当前本地 pack 仍未找到 exact-name peer”；
   这条的 BI 影响证据目前更偏
   `owner/access/team attribution`
   而不是 `ARR/stage` 主指标本身，
   因为当前 checkout 里更硬的 owner-team 下游是
   `salesforce_opportunities.opt_owner_role_c -> owner_team`
   以及 bizops 侧
   `dws_data_quality_alerting`
   /
   `rpt_data_quality_wtw_comparison`
   ，而不是 marketing 侧
   `dws_campaign_attribution`
   /
   `dws_icp_summary`
   直接消费 `owner_team`。
   另外，marketing 侧的 dashboard/owner 边界也又收紧了一层：
   remote
   `pingcap-inc/looker-schema`
   repo-head
   仍然只有同样的 7 个 LookML 文件，
   remote
   `pingcap-inc/dbt-dev`
   也仍只有 business-operations 的
   `exposures.yml`
   ，没有额外的 marketing exposure / schema-owner 层。
   再加上一条 live BigQuery naming caveat：
   当前 warehouse 里真正存在的是
   `dwh_marketing.salesforce_leads`
   和
   `dwh_business_operations.salesforce_opportunities`
   ，以及旧风格
   `salesforce_lead_rectify`
   /
   `salesforce_oppo_rectify`
   view；
   当前 checkout 里的 LookML
   `salesforce_lead`
   /
   `salesforce_oppo`
   更像 legacy/alias 命名，不应直接当成 live warehouse 真名。
   不过 live warehouse 这边也补到了两条更硬的真实消费链：
   `anls_business_operations.dim_opportunity`
   是一个直接以
   `dwh_business_operations.salesforce_opportunities`
   为 base 的 live view，
   最近还确实被
   `xiaopeng.zhu@pingcap.com`
   查询了
   `forecast_category`,
   `mapped_stage_name`,
   `arr_amount_usd`,
   `accurate_acv_amount`,
   `owner_team`,
   `cloud_order_type`,
   quote/task/history
   等字段；
   另一边
   `dwh_plg.plg_contacts`
   /
   `dwh_plg.plg_accounts`
   两个 live view
   会直接用到
   `dwh_marketing.salesforce_leads`
   ，说明 Lead 这条线除了
   `dws_marketing`
   的漏斗/归因语义外，
   还会继续流到 PLG account/contact sourcing。
   这条边界这轮也进一步补上了：
   当前
   `JOBS_BY_PROJECT`
   已经能直接看到
   `yiming.wang@pingcap.com`
   在
   `2026-06-23`
   查询
   `dws_marketing.dws_campaign_attribution`
   的
   `attributed_arr`,
   `campaign_name`,
   `campaign_region`,
   `contact_response_date`,
   `opportunity_contact_role`,
   `opportunity_created_date`
   等列；
   同一天也直接查询了
   `dws_marketing.dws_icp_summary`
   的
   `region`,
   `segmentation`,
   `icp_industry_categorisation`,
   `lead_surrogate_key`,
   `opportunity_id`,
   `arr_amount`
   等列；
   更早的
   `2026-01-08`
   /
   `2026-01-12`
   还能看到
   `dws_marketing.dws_lead_timeline`
   被直接拿来按
   `campaign_interaction`
   /
   `pipeline_created`
   /
   `customer_milestone`
   做聚合，
   `2026-03-25`
   `alfred.wang@pingcap.com`
   还直接跑过
   `SELECT * FROM dws_marketing.dws_lead_timeline LIMIT 5`；
   再往上一层，
   `2026-05-20`
   的作业还显示
   `anls_marketing.dim_lead`
   被直接 join
   `fact_cloud_events`
   做
   `sign_up_timestamp`
   /
   `campaign_name`
   分析。
   所以 marketing 这条线现在已经不只是
   `live object existence + row counts`
   ，而是已经有
   `直接用户查询`
   证据；
   当前真正还偏弱的，
   是这几张 mart 对应到
   `哪一个命名 dashboard / explore / owner`
   的元数据层。
   pipeline / finance 这边这轮也继续补强了：
   `yiming.wang@pingcap.com`
   在
   `2026-05-04`
   /
   `2026-05-07`
   直接查询了
   `dws_business_operations.dws_data_quality_alerting`
   和
   `rpt_data_quality_wtw_comparison`
   ，字段包括
   `issue_type`,
   `owner_team`,
   `region`,
   `cloud_order_type`,
   `opportunity_name`,
   `opportunity_number`,
   `stage_name`,
   `weeks_elapsed`,
   `wtw_type`
   等；
   这说明
   `OpportunityShareToPersalesOwner`
   这类偏
   `owner/access/team attribution`
   的差异，
   确实有非常近的 live consumer，
   不需要只靠一个 exposure 名字来推。
   另一边
   `xiaopeng.zhu@pingcap.com`
   在
   `2026-07-07`
   直接查询了
   `model_fp_and_a.dws_salesforce_arr_summary`
   的
   `monthly_total_arr`,
   `order_region`,
   `revrec_month`,
   `fiscal_year`,
   `fiscal_quarter_of_year`,
   `quarter_arr_total_quota`
   等列；
   `xiaopeng.zhu@pingcap.com`
   和
   `fanfei.kong@pingcap.com`
   还在
   `2026-07-01`
   到
   `2026-07-05`
   之间直接查询了
   `dwh_finance.salesforce_order_daily_view`
   和
   `dwh_finance.salesforce_org_monthly_revrec`
   ，关注的就是
   `order_number`,
   `account_id`,
   `accumulate_revenue_to_org_tenant_id`,
   `order_service_start_date`,
   `order_service_end_date`,
   `order_net_fees`,
   `tenant_id`,
   `total_amount`,
   `actual_revenue_recognition_date`,
   `raw_byoc_amount`
   这些 finance / revrec 核心列。
   所以 Order / Org / Revenue / Invoice_Collection__c
   这条线现在也不该只写成
   `会影响某些下游模型`
   ，而应改成
   `会直接打到当前被真实用户查询的 order-day / org-month / ARR summary 面`。
   再往“命名 surface”这层补一格，
   私有 repo
   `pingcap-inc/digital-bi-discovery`
   现在也给出了几组可直接引用的 analyst/discovery 名字：
   `Data Discovery for Salesforce Opportunities`，
   `revrec_discovery`，
   `monthly_billing_validation`，
   `01_campaign_discovery`，
   `02_campaign_attribution_discovery`，
   以及一个可部署的
   `Campaign Attribution Tuner`
   app。
   它们不是正式的 governed dashboard 清单，
   但已经明显强于“只有 dbt model 名字”：
   `1_opportunities.ipynb`
   明写在研究 Salesforce
   `opportunity`
   的 process flow / data quality；
   `revrec_discovery.ipynb`
   直接查
   Salesforce `order` / `order_product_c` / `revenue_c`；
   `Campaign Attribution Tuner`
   的 backend 直接读
   `dwh_business_operations.salesforce_opportunities`,
   `dwh_marketing.salesforce_campaign_interacted_accounts`,
   `salesforce_campaigns`,
   `stg_salesforce_opportunity_contact_role`
   来调 attribution 权重。
   所以现在如果要回答
   `对哪张报表/分析面有影响`
   ，已经可以把一部分答案从
   `某个 mart`
   升级成
   `具体 discovery notebook / attribution app / data-quality dashboard`
   这一层了。
   finance 这边还有一个额外很实用的 named artifact：
   `pingcap-inc/dbt-dev/REVENUE_CATEGORY_IMPACT_ASSESSMENT.md`。
   它不是 dashboard，
   但它把 revrec-category 变化的 downstream blast radius
   明确写成了
   `70` 个模型的清单，
   其中直接点到
   `dws_salesforce_arr_summary`,
   `dws_salesforce_order_monthly_revrec_usd_v2`,
   `dws_salesforce_order_product_monthly_revrec_usd_v2`
   以及多条 account/order monthly revrec 面。
   这对
   `Revenue__c / Order / Org__c / Invoice_Collection__c`
   这条线尤其有帮助，
   因为它把
   `影响哪些 finance 输出`
   说成了一个现成的 named impact-assessment，
   不需要我们完全自己从 SQL 重新数一遍。
   反过来，
   org-wide GitHub code search
   对
   `salesforce_lead`,
   `salesforce_oppo`,
   `crm_account`,
   `cloud-lead-pipeline-insight`,
   `dws_salesforce_arr_summary`,
   `salesforce_order_daily_view`,
   `dws_data_quality_alerting`,
   `rpt_data_quality_wtw_comparison`
   这些关键词并没有挖出更多 governed dashboard config，
   这也进一步说明：
   当前最现实的 owner-facing 证据结构是
   `少量正式 dashboard metadata`
   +
   `更多 named discovery notebooks / named impact docs / live direct queries`。
   与此同时，`Invoice_Collection__c`
   这边这轮已经把 4 条 flow 名字基本补齐：
   `Collection_Set_PLG_BD_Pool`、
   `Collection_Amount_and_Payable_Amount_exc_tax`、
   `Collection_Amount_and_Payable_Amount_exc_tax_Update`、
   `Cloud_Registration_Source_from_Org_to_Collections`。
   而且它们已经不只是“名字恢复”：
   历史 dumped fixture metadata 说明
   `Collection_Set_PLG_BD_Pool`
   是 `RecordBeforeSave CreateAndUpdate`
   ，会把
   `Account__r.PLG_BD_Pool__c`
   赋到
   `Invoice_Collection__c.PLG_BD_Pool__c`；
   `Collection_Amount_and_Payable_Amount_exc_tax`
   / `_Update`
   是 `RecordAfterSave`
   的 create/update 两条腿，
   会维护
   `Collections_Amount_USD_exc_tax__c`、
   `Collections_Amount_exc_tax__c`、
   `Payable_Amount_USD2_exc_tax__c`；
   `Cloud_Registration_Source_from_Org_to_Collections`
   是 `RecordAfterSave Create`
   ，会根据 org lookup 把 org-derived source 数据写到
   `Invoice_Collection__c.Marketplace__c`。
   而且本地已经有
   `Cloud_Registration_Source_from_Org_to_Order`
   这条同家族 `Order` Flow，
   所以现在更像
   `Collections 这一腿没补齐 / 仍有 dispatch 问题`
   ，而不是 `CM 完全不会表达这类 carry-over`。
   反过来，invoice/lead/opportunity 的 email template 名字虽然很有用，
   但当前更应该读成
   `notification-surface evidence`
   ，不是已经确认的 WorkflowAlert / Flow 绑定。
   另外，`Invoice_Collection__c` 这组剩余缺口现在也更像是
   `carry-over / 状态切换 / 通知`
   类逻辑，而不是基本公式能力本身缺失：
   本地对象定义已经有大量 payable / payment-status / uncollected amount
   公式，以及 `Actual_Billing_Date__c` validation 对齐。
   更具体地说，`Order` 本地元数据已经有按
   `Invoice_Collection__c.CollectionsStatus__c = 'Collected'`
   过滤的 rollup，
   所以 live IC Flow 缺口更可能直接影响
   `collections 何时被计入 order-level cash/payable metrics`
   ，不只是通知有没有发出去。
   同时，这轮还补上了一个 current-checkout 级别的证据边界：
   `stg_salesforce_invoice_collection.sql`
   的 source/staging 消费面是明确存在的，
   但 checked-out `salesforce_orders.sql`
   只是声明了 `invoice_collection` CTE，
   当前并没有把它 join 进最终结果。
   所以关于 `Invoice_Collection__c`
   的报表影响，当前最强的 confirmed direct consumer surface
   仍然是
   `stg_salesforce_invoice_collection`
   本身，
   再加上本地 `Order` 元数据里的 IC rollup
   和 `monthly_cloud_billing_revrec.py`
   这种 recurring finance output 链路；
   不宜把它说成“当前 dbt 的 order mart 已经显式吃完所有 IC 明细”。
4. `Apex 替代工作量`
   我们已经知道哪几个 trigger surface 是边界，
   但还没有逐条拆完
   `每段 Apex 逻辑到底该改写成哪种 Flow / metadata-action`
   的实施设计。

## 6.1 报告里的 gap 不是都等于 CM 真缺能力

这一轮最需要固定下来的读法是：

- 报告列的是
  `Salesforce vs CM 的 BI 风险差异面`
- 不是
  `CM 差异来源总表`
- 只有当差异清到最后只剩
  `trigger-only / runtime-only`
  行为时，
  才更应该升级成
  `CM 真边界`

下面这张表可以直接拿去跟别人对齐：

| 典型项 | 当前最稳分类 | 是否应直接说成 `CM 目前做不到` | 先影响哪组报表 |
|---|---|---|---|
| `Lead_StatusChangeTimestamp` | `semantic parity mismatch` | `否`。本地已有 `Lead_Status_Duration`，问题是时间戳收窄条件不对，不是 CM 不会写 lead status timestamp | `fd12...` lead funnel / ICP path，次级 `dwh_marketing.salesforce_leads` staging 供给 |
| `Campaign_Member_Key_Message_Update` | `L2 exact-flow parity` | `否`。本地已有 `CampaignMember` first/last-touch 体系和 `convertLead` attribution preview，缺的是一条同名补齐 Flow | `8c6f...` attribution，次级 `fd12...` |
| `Quote_update_nonstandard_conditions_checkbox` / `_2` | `L2 exact-flow parity` | `否`。Quote 字段、validation 邻近件都在，缺的是 exact-name commercial helper Flow | `1733...` pipeline data quality / cleanup |
| `Account_Current_Order_Type` | `L2 exact-flow parity` | `否`。`Account.Current_Order_Type__c` 字段已在，本地 account/org shared-key substrate 也在 | `583...`，次级 `690...` / `f9c4...` / `31605...` |
| `Order_Org_Auto_Set_Account_*` | `L2 finance carry-over parity` | `否`。本地已有 `Org_Set_Account`、`Order_Default_RevRec_Entity`、`Cloud_Registration_Source_from_Org_to_Order` 这些同家族承接件 | `583...`、`837...`、`f9c4...` |
| `Collection_Set_PLG_BD_Pool` / `Collection_Amount_and_Payable_Amount_exc_tax*` / `Cloud_Registration_Source_from_Org_to_Collections` | `L2 finance carry-over parity` | `否`。`Invoice_Collection__c` helper 字段、`Order` 侧 rollup、同家族 `Order` Flow 都已存在，当前更像 collections 这一腿未补齐 | `f9c4...`，次级 `salesforce_order_daily_view` / `salesforce_org_monthly_revrec` |
| `Revenue__c.Name` / `Invoice_Collection__c.Name` / custom line-item `Name` | `auto-number parity missing` | `通常否`。这是 metadata parity，不是 substrate 空白 | `837...`、`f9c4...` 邻近 finance 链路 |
| `LeadTrigger` / `LeadAITrigger` | `runtime boundary` | `是，比较接近`。这是当前最像 live Apex-only 的真实边界之一 | `fd12...`，以及 `dws_lead_timeline` / `dws_icp_summary` 邻近语义 |
| `OpportunityTrigger` / `QuoteTrigger` | `runtime boundary` | `是，比较接近`。先清完 L2 parity，再单列 residual trigger | `1733...`、`837...`、`0f2...` |
| `OrderTrigger` / `RevenueTrigger` / custom line-item trigger surfaces | `runtime boundary` | `是，比较接近`。finance 线清完 carry-over 以后剩下的才是真边界 | `837...`、`f9c4...`、current/monthly revrec outputs |
| `AccountTrigger` / `Trigger_CampaignMember` | `runtime boundary candidate` | `谨慎说`。先清 account/campaign-member 的 exact-name parity，再决定是不是 runtime 真边界 | `583...` / `690...` / `8c6f...` |

一条简单使用规则：

- 报表里看到
  `同名 Flow / validation / auto-number`
  缺口，
  默认先读成
  `CM 已支持，但 PingCAP L2 还没补齐`
- 报表里看到
  `字段已在、本地已有同家族 peer、但语义条件更宽/更窄`
  ，默认先读成
  `semantic parity mismatch`
- 只有当
  `本地 pack parity 清完`
  以后仍然必须依赖 live Apex / runtime，
  才升级成
  `CM 真边界`

## 6.2 长尾残余里，哪些是报表优先，哪些更偏操作优先

当前最容易被混淆的是：

- `Lead assignment`
- `Opportunity share / owner-team`
- `Invoice / collection notice`

这三类都属于“业务上有感知”的机制，
但它们对 BI 的优先级并不一样。

| 长尾机制 | Salesforce 会做什么 | CM 当前已支持什么 | 当前主要差异 / 待补 / 疑似待补什么 | 更像先打哪里 |
|---|---|---|---|---|
| `Lead_Assignment_Rule_modification_for_NA_EMEA` | 按 `Company/Region/AccountStatus` 查找匹配 Account，然后在 `Sales owner直派`、`regional SDR`、`regional default owner` 之间路由 Lead，并在部分分支回写 `AE__c` / `Owner_Profile__c` | 这条现在不该再算未支持。本地 `packs/Salesforce-PingCAP-L2/pack.json` 已登记同名 Flow；`staging-inspection/docs/lead-case-business-spec.md` 已把 routing 逻辑写实；`staging-inspection/config/cases/flow-regression/lead/*.json` 还明确记录了 `14` 个 assignment regression 用例在 `2026-06-15` staging 实跑 `PASS` | 更像历史 flow-engine bug / staging 回归对象，不是当前报表 gap 主轴。仍需关注相关 engine bug（如 cross-record assignment / formula resource），但那是“已支持机制的稳定性”问题，不是“缺这条业务 Flow” | `操作面优先`。它会间接影响 lead owner / SDR 归属，但当前更像 lead routing 正确性与销售流程可用性，不是这轮最前排 BI 缺口 |
| `OpportunityShareToPersalesOwner` / `OpportunityUpdateShareToPerSalOwner` | 在 opportunity create / update 后维护 presales-owner share / owner-team 邻近语义，保证机会被相应角色看到、并让 owner-team 相关分析口径稳定 | CM 已有 `Opportunity` stage/forecast/close-date/cloud-order-type 这类核心 before-save parity；live warehouse 侧也已真实消费 `owner_team`、`cloud_order_type`、`stage_name` 这组字段 | 当前本地仍未找到这两个 exact-name peer。`migration_audit.csv` #1749 已点名 create 腿，update 腿仍是高置信 sibling；所以这条是“未补齐的近报表面 Flow”，不是泛泛的权限细节 | `报表优先`。它最先打 `dws_data_quality_alerting`、`rpt_data_quality_wtw_comparison`、`anls_business_operations.dim_opportunity` 这类 owner-team / dq surface，而不是先打 marketing attribution |
| `Collected_Notice_to_Sales` / `Invoice_Issued_Notice` / `Invoice_Notice` 等 IC 邮件模板 | 在 collection collected、invoice issued/application/notice 这些状态变化时触发通知，让销售或财务及时知道金额、日期、订单、账户发生了什么 | 当前本地 baseline seed 已有 active email template 记录；迁移出的 `TEMPLATE_CATALOG.md` 也坐实这些 template 名字和字段线索 | 这些 template 现在仍更像 `notification-surface evidence`，还不足以单独证明 live `WorkflowAlert / ProcessAction / Flow binding`。它们不该和 `Collection_Set_PLG_BD_Pool`、`Collection_Amount_and_Payable_Amount_exc_tax*`、`Cloud_Registration_Source_from_Org_to_Collections` 这种 metrics-first Flow 混读 | `操作面优先`。它们优先影响通知体验；真正先打 finance 报表的还是 IC 的 pool / exc-tax / marketplace carry-over Flow 家族 |

一条更直接的落地规则：

- `Lead assignment`
  现在默认读成
  `已支持且已回归验证`
- `Opportunity share / owner-team`
  现在默认读成
  `仍是报表近邻 parity gap`
- `Invoice notice template`
  现在默认读成
  `业务通知线索`
  ，不要替代
  `IC finance helper Flow`
  本身

## 6.3 `Account_Current_Order_Type` 和 `Order_Org_Auto_Set_Account_*` 不是普通边角料

这组机制现在值得单独拎出来，
因为它们并不是
`有空再补`
的 shared-dimension 小差异，
而是已经进入
`front-door account / tenant / current-month MRRARR`
消费面的高信号项。

| 机制 | Salesforce 会做什么 | CM 当前已支持什么 | 当前主要差异 / 待补 / 疑似待补什么 | 最先打哪组报表 / front door |
|---|---|---|---|---|
| `Account_Current_Order_Type` | 在 `Account` 侧持续维护 current-order-type 维度，让 account、tenant、cloud billing、current-month MRRARR 和 finance/account bridge surface 在同一口径下看当前订单类型 | 本地并不是空白：`packs/Salesforce-PingCAP-L2/objects/Account.json` 已有 `Current_Order_Type__c` picklist 字段；`Org_Set_Account` 已把 lead-converted account 关联带到 `Org__c`；shared-dimension 下游也已真实消费 `account_current_order_type` | 当前 checkout 里仍没有同名 local Flow peer；但这条又不只是“名字没补到仓库”。`migration_audit.csv` #2199 还显示它在某些环境里出现过 `Flow row exists` 但 `FlowVersionId: referenced Flow record is not accessible` 的 scheduler retry-storm。最稳读法因此不是“CM 完全不会做”，而是：当前 tree 里缺 exact-name parity，同时跨环境还暴露过 `dispatch/accessibility` 风险 | 最先打 `583...`、`f9c4...`、`31605...` 和 `model_tidbcloud.dws_cloud_tenants_basicinfo` 这类直接带 `account_current_order_type` 的 front door；`690...` 更适合作为次级 tenant-funnel consumer 回归面，而 `673...` / `212...` 当前不再作为这条的 direct field evidence |
| `Order_Org_Auto_Set_Account_Create` / `_Update` | 在 order create/update 时把 order、org、account、tenant 的 carry-over 关系补齐，避免 order finance 事实和 tenant/account bridge 断开 | 本地已经有同家族 bridge substrate：`Org_Set_Account.flow.json` 会把 `Lead__r.ConvertedAccountId -> Org__c.Account__c`；`Cloud_Registration_Source_from_Org_to_Order.flow.json` 会在 `Order` 上按 `Accumulate_revenue_to_Org__c` lookup `Org__c` 并写 `Cloud_Registration_Source__c`；`Order_Default_RevRec_Entity` 也已把 contracting entity 默认逻辑落地 | 当前 checkout 里仍未找到这两条 exact-name peer，所以 order/account/org carry-over 仍有直接缺口。现在最稳读法仍是 `L2 finance carry-over parity`，但它不是“只有 Order 页上一个字段错了”，而是会把 account/tenant 对齐和 current-month finance 口径一起打歪 | 最先打 `583...`、`837...`、`f9c4...`，再外溢到 `salesforce_order_daily_view`、`salesforce_org_monthly_revrec`、`cp_order_monthly_revrec` |

这里最重要的分层是：

- `Account_Current_Order_Type`
  不再只是
  `current-tree missing flow`
  这么简单
- `Order_Org_Auto_Set_Account_*`
  也不只是
  `order object 本地还差两条 flow`
  这么简单

更准确地说：

- 前者已经有
  `field 已在 + downstream front door 已在 + 某些环境出现过 flow row 可见性/调度问题`
  的混合信号
- 后者已经有
  `同家族 bridge flow 已在 + finance/front-door 已真实消费 carry-over 字段`
  的混合信号

所以这两组都应该优先按
`报表近邻 parity / dispatch risk`
处理，
而不是当成低优先级元数据扫尾。

## 6.4 `Revenue__c` 和 line-item 层要拆成两半看

finance 明细层现在最容易被一句
`line-item 还没补齐`
说糊。
但当前 evidence 更支持拆成两半：

- `标准 OpportunityLineItem / QuoteLineItem 计算链`
  已经支持得比较实
- `custom Opportunity_Product__c / Order_Product__c / Quote_Product__c`
  则是
  `公式/rollup 已在`
  和
  `legacy shadow / auto-number / trigger residue`
  混合存在

| 机制层 | Salesforce 会做什么 | CM 当前已支持什么 | 当前主要差异 / 待补 / 疑似待补什么 | 最先打哪组报表 |
|---|---|---|---|---|
| 标准 `OpportunityLineItem` net-fees / product-family 链 | 在商机标准行项目上补 `Product2`、`ListPrice`、`Net_fees`、term 相关语义，供机会产品族、cloud/order type、ARR/ACV 邻近逻辑继续消费 | 本地这条链已经相对扎实：`OpportunityLineItem_Product2_Autofill_From_Pricebook`、`OpportunityLineItem_ListPrice_Autofill_From_Pricebook`、`OpportunityLineItem_Net_Fees_Autocalc` 都是 active；其中 `OpportunityLineItem_Net_Fees_Autocalc` 还是 `RecordBeforeSave CreateAndUpdate`，按 `Product2.Family` 把 `Net_fees__c` 分成 `UNP * Qty` 或 `UNP * Qty * Term` 两类计算 | 当前更像 residual trigger / legacy consumer 侧问题，而不是标准 OLI 主链完全没支持 | 先打 `0f2...` 的 `opportunity_product_family` 邻近面，次级 `837...` 的 ARR/forecast |
| 标准 `QuoteLineItem` net-fees 链 | 在报价标准行项目上按产品族和 term 维护 annualized / passthrough 的 `Net_fees__c`，为 quote-to-order 和 commercial 分析提供基底 | 本地 `QuoteLineItem_Net_Fees_Autocalc` 已 active；会在 `TES / TiDB Cloud 且 Term > 12` 时 annualize，否则 passthrough `Net_Fees_Total__c` | 当前这条更像已支持基座，不是 finance 报表最前排 gap；更大的风险还是 quote exact-name commercial helper Flow 缺失 | 先打 quote/opportunity 邻近面，再间接外溢到 order/ARR |
| custom `Order_Product__c` | 维护 `order_product_family`、`product_name`、`list_price_subtotal`、`manday`、`surplus`、`net_fees` 等 order-line 语义，供 current/monthly MRRARR、order-day、ARR summary 直接消费 | 本地 `Order_Product__c.json` 已有 active 公式 `Product_Family__c`、`Product_Name__c`、`List_Price_Subtotal__c`、`Surplus__c`，active rollup `Manday__c`，以及 active validation `Canotlowerthanthequotedprice`；所以 custom order-line 不是空对象 | `Name` auto-number 仍缺；更重要的是它仍和 `OrderTrigger` / finance carry-over / custom line-item residue 同组存在，不能宣称“order-line 全链路 parity 已齐” | 先打 `583...`、`837...`、`f9c4...`，以及 `salesforce_order_daily_view` / `cp_order_monthly_revrec` |
| custom `Opportunity_Product__c` | 作为 legacy opp-product 语义承接体，继续支撑一些旧 Opportunity Flow / validation 对产品族、服务期、recalculate 的读取 | 本地对象公式已在：`Product_Family__c`、`Product_Name__c`、`NetFees__c`、`Valid_days__c` 都 active | 这里的真实边界比 `Order_Product__c` 更强：本地还有一个 `UN-READY` 的 `OpportunityLineItem_Legacy_Product_Shadow.flow.json`，它明写了目标是“给仍查询 `Opportunity_Product__c` 的 legacy flows 做 OLI -> shadow 1:1 镜像”。这说明 custom opp-product 目前仍带明显的 legacy bridge / trigger residue 风险，而不是纯 metadata parity | 最先打 `0f2...` 的 opportunity-stage/product-family 面，次级 `1733...` / `837...` |
| `Revenue__c` | 维护 revrec 明细、`amount_before_adjust`、`credit_amount`、exchange rate、PLG pool 以及 order-level recognized/deferred revenue 聚合输入 | 本地 `Revenue__c` 对象已有多条公式，`Order` 侧也已真实 roll up `Accumulated_Revenue_Before_Adjust__c`、`Recognized_Revenue_Amount__c` 等；`PLG_BD_Pool__c` 字段本身也在 | 当前最明确缺口仍是 `RevRec_Set_PLG_BD_Pool` 和 `Revenue__c.Name` auto-number；再往后才是 `RevenueTrigger` 残余。也就是说，现阶段不是“CM 不会建 revrec”，而是 revrec 侧 exact-name helper 和 identity parity 还没补完 | 先打 `837...`，次级 `f9c4...` 与 `salesforce_revrec` / `monthly_revrec_orders` |

这层最稳的读法是：

- `标准 OLI / QLI`
  现在已经更像
  `已支持的基础计算链`
- `custom Order_Product__c`
  现在更像
  `公式/rollup 已有，但仍有 auto-number + trigger residue`
- `custom Opportunity_Product__c`
  现在更像
  `legacy shadow 仍未完全收口`
- `Revenue__c`
  现在更像
  `revrec substrate 已在，但 PLG pool / Name parity 未补完`

## 6.5 finance 明细层里，谁先直接打前台报表

如果只问
`Revenue__c / line-item 哪些差异会先被报表看到`
，
当前最稳不是把它们并排看，
而是先按
`front-door 直接性`
排序。

| 对象/层 | 当前更像什么角色 | 最先被谁看到 | 为什么 |
|---|---|---|---|
| `Order_Product__c` | `front-door finance line` | `583...`、`837...`、`f9c4...`，以及 `salesforce_order_daily_view` / `cp_order_monthly_revrec` | `order_product_family`、服务期、`net_fees` 会直接进 current/monthly MRRARR、ARR summary、order-day 语义，所以 custom order-line 的 drift 往往先在前台 composite 报表暴露 |
| `Revenue__c` | `nested revrec feed` | 先是 `salesforce_revrec`、`salesforce_orders.revenues`、`monthly_revrec_orders` / `salesforce_org_monthly_revrec`，再间接进 `837...` / `f9c4...` | 当前 evidence 更支持 revenue 先作为 finance 明细供给层被 recurring revrec / direct-query 消费，然后再外溢到 ARR/tenant front door；它不是最先被 Looker 命名 dashboard 直接看见的那层 |
| `Opportunity_Product__c` | `legacy opp-product bridge` | `0f2...`，次级 `1733...` / `837...` | 它的风险不只是字段空缺，而是旧 Opportunity Flow 仍可能读取 custom opp-product；所以更先暴露在 opportunity stage / product-family / launch validation 邻近面 |
| `Quote_Product__c` | `commercial helper relay` | 先经 quote/opportunity 邻近面，再间接外溢到 order/ARR | 当前最稳读法仍是：它主要通过 quote commercial 语义影响 opportunity / order，下游 finance 不一定最先直接读它 |

一句话：

- `order_product_family`
  这类 line-item 语义
  往往比
  `revenue_amount / credit_amount`
  更早在命名报表面暴露
- `Revenue__c`
  更像
  `finance 明细供给层`
  ，先被 recurring revrec / direct query 看见
- `Opportunity_Product__c`
  的风险重点不是“少个字段”，
  而是
  `legacy shadow 是否还在喂旧 Flow`

## 6.6 `Contract / governing-contract` 这条线更像策略分叉，不只是漏迁

这条线当前最容易被说成：

- `Contract 还缺几条 Flow`
- `Order contract validation 没补齐`

但从本地证据看，
更准确的读法是：

- `Contract` 对象本身确实还有 parity gap
- 但 `Order 激活时到底由谁来当 contract authority`
  这件事，
  已经被 PingCAP 明确改成了
  `Account-level governing-contract policy`
  ，不是单纯漏迁

| 维度 | 当前证据 |
|---|---|
| Salesforce 现网会做什么 | 标准 Salesforce-compatible 读法仍是：`Order.ContractId` 是 activation authority。`Order_Activate_Contract_*` 这组规则会检查 linked Contract 是否存在、是否 Effective/Activated、以及日期是否覆盖 Order 服务期；`Contract` 自身则维护 `ContractNumber`、`Status/StatusCode`、effective/activated 时间语义。 |
| PingCAP 本地已支持什么 | 本地 `Contract` 不是空白：已有 `ContractNumber` auto-number；`Contract_Archived_Status_Autopromote.flow.json` 会把 `Approved + Archived__c=true` 的合同 before-save 提升到 `Effective`；`Std_ContractActivateStamp.flow.json` 会把业务状态映射到标准 `StatusCode` 并在 `Activated/Effective` 时回写 `ActivatedDate` / `ActivatedById`。`Account` 对象上也已有 `Contract_Valid_Date__c`、`Contract_Valid_Days__c`、`Contract_Valid__c` 这组治理字段。更关键的是，ADR 和 PRD 已经把 PingCAP 规则钉死成 `Account-level governing-contract validation`：Cloud 看覆盖的 CSA/CSAO，OP 看覆盖的 MA，创建时忽略 Contract 状态，激活时要求 Effective governing Contract。 |
| 当前主要差异 / 待补 / 疑似待补什么 | `Contract` 这边仍有 2 条 live Flow 本地没看到：`Auto_Expire_Contract`、`Contract_Update_Account_Contract_Valid`；contract trigger 也仍是 runtime residue。另一方面，`Account_Contract_Valid_Message` / `_1` 这组 Account Flow 仍缺，所以本地 contract-valid 提示/治理链并没有完全补齐。 |
| 哪些不该再算成“普通 gap” | `Order_Activate_Contract_Status`、`Order_Activate_Contract_Start`、`Order_Activate_Contract_End`、`Order_Activate_Requires_Contract` 这 4 条 local inactive 规则，以及 `Order_Create_Requires_Effective_CSA_MA_Contract` 这个旧名字，不该再默认算成 “CM 没做到 Salesforce validation”。本地 `validation/standard_validation_rules.json` 已明确把前 4 条写成 `Disabled for PingCAP: activation validates Account-level governing Contracts instead of Order.ContractId.`；ADR / PRD 也把这次策略分叉说明白了。 |
| 最先打到哪组报表 / front door | 这条线更像先打 `salesforce_orders`、`salesforce_order_daily_view`、`cp_order_monthly_revrec`、`dws_salesforce_arr_summary`，因为 order activation / service-period / governing-contract eligibility 会直接影响 order-day 和 ARR 口径；次级才会打到 account governance / forecast 邻近面，比如 `673...` / `212...` 上的 account-governance 语义。`Contract` 自己则更常以 `contract_id` / `ContractNumber` / contract-valid 语义进入 `salesforce_opportunities`、`stg_salesforce_order`、`stg_salesforce_quote`、`stg_salesforce_revenue`、`stg_salesforce_invoice_collection` 这些跨对象链路。 |

这条线最稳的结论不是：

- `Contract 还有缺口，所以先补回 Salesforce ContractId 模型`

而是：

- `Contract object parity`
  和
  `PingCAP governing-contract policy`
  要分开看
- 前者仍有 Flow / trigger 缺口
- 后者已经是明确的本地策略替代，
  不能默认回滚成
  `Order.ContractId-authoritative`

## 6.7 `Account_Contract_Valid_Message` 更像 account-governance 提示链缺口

如果把 contract/governing-contract 再往下拆，
有一条很容易被跟
`Order activation policy`
混在一起：

- `Account_Contract_Valid_Message`

当前更稳的读法是：

- 它不是
  `Order.ContractId authority`
  的替代策略本身
- 它更像
  `Account contract-valid governance / reminder / warning`
  这一条提示链没补齐

| 维度 | 当前证据 |
|---|---|
| Salesforce 现网会做什么 | 现网 `Account` 不只是承载 `ICP`、`Segmentation`、`Open_Pipeline_ACV__c`，也会维护 `Contract_Valid_Date__c`、`Contract_Valid_Days__c`、`Contract_Valid__c` 这类 contract-health 字段；live 审计里还明确把 `Account_Contract_Valid_Message` / `_1` 列成缺失的 exact-name Account Flow，另外 contract 侧 live 还有 `Contract_Update_Account_Contract_Valid`。 |
| PingCAP 本地已支持什么 | 本地 `Account` 对象基座已经在：`Contract_Valid_Date__c`、`Contract_Valid_Days__c = Contract_Valid_Date__c - Today()`、`Contract_Valid__c` 都已存在；curated Account layout 也把这几个字段直接放进 `PartnerInfo` 区块，说明这不只是后台 helper，而是 operator-facing governance 字段。更进一步，live Salesforce 的 `Contract_Update_Account_Contract_Valid` fixture 现在也能具体还原：它在 `Contract` 的 `CreateAndUpdate / RecordAfterSave` 上，通过 `AccountId + Status='Effective' + Contract_Number__c contains 'PNA'` 找 contract，再把 `Contract_Number__c`、`Contract_Valid_Date__c = EndDate`、`Contract_Valid__c = true` 回写到 `Account`。这说明本地并不是不知道这些字段长什么样，而是缺少同名治理回写链。 |
| 当前主要差异 / 待补 / 疑似待补什么 | 当前本地仍没有 `Account_Contract_Valid_Message` / `_1` 的 exact-name peer；`Contract_Update_Account_Contract_Valid` 也仍未在本地看到。因此当前最像缺的不是 contract object 本身，而是 `contract 变化 -> account contract-valid 状态/提醒` 这条治理提示链。 |
| 最先打到哪组报表 / front door | 这条现在最稳的边界最好分四层讲。第一层，`warehouse/modeling consumer` 已经存在：live BigQuery 里，`yiming.wang@pingcap.com` 多次在 `sandbox_nexuscrm_phase1` 里构建 `stg_salesforce_account` / `stg_salesforce__account_tmp` / `fivetran_dbt_ods_account`，直接读 `nexuscrm_final.nexuscrm_account` 的 `contract_valid*`；`chen.du@pingcap.com` 也有少量直接命中 `salesforce.account` 的查询。第二层，repo 侧当前能坐实的是 `staging/schema preservation`：`pingcap-inc/dbt-dev` 的 `stg_salesforce_account.sql` 和 completion test 明确保留了 `contract_valid* / contract_number_c / current_effective_pna_c`，但命名 warehouse model `salesforce_accounts.sql` 当前并未投影 `contract_valid*`，`salesforce_orders.sql` 的 account join 也没有用到这组字段。反过来，同 repo 的 `dwm_cloud_tenants.sql` 已明确带 `account_current_order_type`，而 `dws_cloud_tenants_basicinfo.sql` 通过 `c.*` 继续把它带进命名 tenant 模型链，这说明 current-order-type 与 contract-valid 的 repo-side blast radius 当前不是同一档。第三层，已经补到一层更弱的 `Looker Studio exploratory evidence`：`2026-01-14 11:30:26`，`chen.du@pingcap.com` 有一批 `requestor = looker_studio` 的 `salesforce.account` 字段探索，其中直接扫到 `contract_valid_c` / `contract_valid_date_c` / `contract_valid_days_c`。更关键的是，这一秒共有 `51` 条、且是 `51` 个 distinct query，样本里每条都在扫不同 account 字段四元组，所以它更像 datasource/schema exploration burst，而不是保存好的命名报表执行；这批作业也只有 `requestor` label，没有 `report_id` / `datasource_id`。第四层，当前 account family 的 `report-backed front-door` 里仍然没有 `contract_valid*` 的字段级直命中，所以它暂时更像 `crm_account`、`salesforce_accounts`、`dim_account`、`dim_tenant` 和 `673...` / `212...` 这类 account-governance 邻近面，而不是像 `account_current_order_type` 那样已经坐实到 `31605...` / `f9c4...` 的前台字段。 |

一句话：

- `Order governing-contract policy`
  决定
  `order 能不能激活 / 进入 finance truth`
- `Account_Contract_Valid_Message`
  更像决定
  `account 维度上怎么提示 contract health / governance risk`

所以这条最适合继续归在
`account dimension / governance parity`
，
而不是并回
`Order activation replacement policy`

## 6.8 现在最适合直接开的三类 issue

如果下一步不是继续研究，
而是要把这份结论直接转成 backlog，
最稳的开法不是把所有差异都开成
`CM runtime gap`
。

当前更适合直接分成下面三类：

| issue 类别 | 现在最该开的项 | 最先影响哪张报表 | 为什么现在就能开 |
|---|---|---|---|
| `A. 直接开 L2 parity issue` | `Quote_update_nonstandard_conditions_checkbox` / `_2`、`Campaign_Member_Key_Message_Update`、`Account_Current_Order_Type`、`Order_Org_Auto_Set_Account_*`、`Order_Set_PLG_BD_Pool`、`Collection_*`、`RevRec_Set_PLG_BD_Pool` | `1733...`、`8c6f...`、`583...`、`837...`、`f9c4...` | exact-name 缺口、报表面清楚、本地已有邻近 substrate，最像 `pack parity backlog` |
| `B. 先不要开成 runtime issue` | `Lead_StatusChangeTimestamp`、`OpportunityShareToPersalesOwner` / `OpportunityUpdateShareToPerSalOwner`、`Account_Contract_Valid_Message`、`Revenue__c.Name`、`Invoice_Collection__c.Name`、custom line-item `Name` | `fd12...`、`1733...`、`673...` / `212...`、`837...`、`f9c4...` | 这些要么是 `semantic mismatch`，要么是 `L2 exact-flow / auto-number parity`，现在直接开 runtime 会过早放大问题层级 |
| `C. 可以单列 CM runtime boundary issue` | `LeadTrigger` / `LeadAITrigger`、`OpportunityTrigger` / `QuoteTrigger`、`OrderTrigger` / `RevenueTrigger` / custom line-item trigger surfaces | `fd12...`、`1733...`、`837...`、`f9c4...` | 这些已经不是单条缺名 Flow，而是明确只剩 live trigger/runtime 残余逻辑，值得单列设计改写题 |

更实用的执行规则是：

1. 先开
   `A. L2 parity`
   类 issue，
   因为它们和报表 drift 的连接最直接。
2. 对
   `B. 先不要开成 runtime`
   这类项，默认继续按
   `语义收窄 / exact-flow parity / auto-number parity`
   做。
3. 只有当同一报表面的
   `A + B`
   清完以后仍有稳定残差，
   才把它升级成
   `C. runtime boundary`
   issue。

一句话：

- `1733...`、`8c6f...`、`583...`、`837...`、`f9c4...`
  这几张 front-door 报表，
  当前最值得先开的是
  `L2 parity`
  issue
- 真正直接开
  `CM runtime`
  的，
  仍然主要是
  `Lead/Opportunity/Order/Revenue + custom line-item`
  的 residual trigger 面

## 7. 最稳的使用方式

如果只是要同步结论：

- 优先用这份最终结论版

如果要看报表组层面的摘要：

- 看一页稿

如果要看机制、文件、触发语义证据：

- 看长报告对应章节

如果要继续做实现 backlog：

- 从长报告里的
  `Report-Group Mechanism Map`
  和
  `实施 Backlog 草案`
  ，以及
  `6.8 现在最适合直接开的三类 issue`
  开始

## 最稳的口径

如果要一句话跟别人同步，最稳的版本是：

`Salesforce 现网还在持续补很多报表语义；CM 已经支持并落地了一部分，但当前最大的差异仍然是 pack parity、激活态不对齐，以及少量仍在 Apex trigger 里的真实 runtime 边界。`

## 相关文档

- 详细研究：
  [salesforce-common-object-create-automation-audit-2026-07-07.md](/Users/amber/ai/nexuscrm-pingcap-pack/docs/salesforce-common-object-create-automation-audit-2026-07-07.md)
- 一页稿：
  [salesforce-common-object-create-automation-onepager-2026-07-07.md](/Users/amber/ai/nexuscrm-pingcap-pack/docs/salesforce-common-object-create-automation-onepager-2026-07-07.md)
