dsh-data-domain-knowledge 0.1.0-alpha.6 → 0.1.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +180 -58
- package/cordis.patch.yml +27 -25
- package/eval/README.md +2 -2
- package/eval/datasets/diagnosis-cases/cases.md +899 -0
- package/eval/evaluate-retrieval.mjs +1 -1
- package/lib/client.js +6849 -5966
- package/lib/doc-page.js +20 -14
- package/lib/pages.js +21351 -0
- package/lib/types/axis-contract.d.ts +9 -0
- package/lib/types/axis-contract.d.ts.map +1 -0
- package/lib/types/axis-contract.js +35 -0
- package/lib/types/axis-contract.js.map +1 -0
- package/lib/types/axis-registry.d.ts +304 -0
- package/lib/types/axis-registry.d.ts.map +1 -0
- package/lib/types/axis-registry.js +744 -0
- package/lib/types/axis-registry.js.map +1 -0
- package/lib/types/card-organize.d.ts +315 -0
- package/lib/types/card-organize.d.ts.map +1 -0
- package/lib/types/card-organize.js +668 -0
- package/lib/types/card-organize.js.map +1 -0
- package/lib/types/config-schema.d.ts +6 -8
- package/lib/types/config-schema.d.ts.map +1 -1
- package/lib/types/config-schema.js +5 -7
- package/lib/types/config-schema.js.map +1 -1
- package/lib/types/convert/host.d.ts.map +1 -1
- package/lib/types/convert/host.js +6 -43
- package/lib/types/convert/host.js.map +1 -1
- package/lib/types/convert/ingest.d.ts +14 -19
- package/lib/types/convert/ingest.d.ts.map +1 -1
- package/lib/types/convert/ingest.js +114 -40
- package/lib/types/convert/ingest.js.map +1 -1
- package/lib/types/convert/settings-schema.d.ts +2 -2
- package/lib/types/convert/settings-schema.d.ts.map +1 -1
- package/lib/types/convert/settings-schema.js +2 -2
- package/lib/types/convert/settings-schema.js.map +1 -1
- package/lib/types/diagnosis/cards.d.ts +26 -8
- package/lib/types/diagnosis/cards.d.ts.map +1 -1
- package/lib/types/diagnosis/cards.js +29 -10
- package/lib/types/diagnosis/cards.js.map +1 -1
- package/lib/types/diagnosis/schema.d.ts +1 -1
- package/lib/types/diagnosis/seed-source.d.ts +0 -9
- package/lib/types/diagnosis/seed-source.d.ts.map +1 -1
- package/lib/types/diagnosis/seed-source.js +2 -4
- package/lib/types/diagnosis/seed-source.js.map +1 -1
- package/lib/types/diagnosis/seed.d.ts +2 -2
- package/lib/types/diagnosis/seed.js +2 -2
- package/lib/types/diagnosis/store.d.ts +10 -5
- package/lib/types/diagnosis/store.d.ts.map +1 -1
- package/lib/types/diagnosis/store.js +18 -18
- package/lib/types/diagnosis/store.js.map +1 -1
- package/lib/types/extract-model.d.ts +7 -7
- package/lib/types/extract-model.d.ts.map +1 -1
- package/lib/types/extract-model.js +14 -10
- package/lib/types/extract-model.js.map +1 -1
- package/lib/types/extract.d.ts +2 -2
- package/lib/types/extract.js +2 -2
- package/lib/types/extraction-runs.d.ts +97 -0
- package/lib/types/extraction-runs.d.ts.map +1 -0
- package/lib/types/extraction-runs.js +169 -0
- package/lib/types/extraction-runs.js.map +1 -0
- package/lib/types/fs-atomic.d.ts.map +1 -1
- package/lib/types/fs-atomic.js +1 -2
- package/lib/types/fs-atomic.js.map +1 -1
- package/lib/types/fts.d.ts +2 -3
- package/lib/types/fts.d.ts.map +1 -1
- package/lib/types/index.d.ts +6 -10
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +761 -178
- package/lib/types/index.js.map +1 -1
- package/lib/types/intent/engine.d.ts +11 -5
- package/lib/types/intent/engine.d.ts.map +1 -1
- package/lib/types/intent/engine.js +29 -80
- package/lib/types/intent/engine.js.map +1 -1
- package/lib/types/intent/host.d.ts +8 -25
- package/lib/types/intent/host.d.ts.map +1 -1
- package/lib/types/intent/host.js +26 -211
- package/lib/types/intent/host.js.map +1 -1
- package/lib/types/intent/preset-tools.d.ts +2 -2
- package/lib/types/intent/preset-tools.js +3 -3
- package/lib/types/intent/store.d.ts +16 -58
- package/lib/types/intent/store.d.ts.map +1 -1
- package/lib/types/intent/store.js +202 -102
- package/lib/types/intent/store.js.map +1 -1
- package/lib/types/intent/tools.d.ts +6 -11
- package/lib/types/intent/tools.d.ts.map +1 -1
- package/lib/types/intent/tools.js +8 -28
- package/lib/types/intent/tools.js.map +1 -1
- package/lib/types/intent/types.d.ts +9 -35
- package/lib/types/intent/types.d.ts.map +1 -1
- package/lib/types/intent/types.js +2 -8
- package/lib/types/intent/types.js.map +1 -1
- package/lib/types/knowledge-bases.d.ts +8 -117
- package/lib/types/knowledge-bases.d.ts.map +1 -1
- package/lib/types/knowledge-bases.js +21 -674
- package/lib/types/knowledge-bases.js.map +1 -1
- package/lib/types/knowledge.d.ts +550 -0
- package/lib/types/knowledge.d.ts.map +1 -0
- package/lib/types/knowledge.js +1213 -0
- package/lib/types/knowledge.js.map +1 -0
- package/lib/types/layout.d.ts +102 -28
- package/lib/types/layout.d.ts.map +1 -1
- package/lib/types/layout.js +104 -28
- package/lib/types/layout.js.map +1 -1
- package/lib/types/migrate.d.ts.map +1 -1
- package/lib/types/migrate.js +47 -4
- package/lib/types/migrate.js.map +1 -1
- package/lib/types/model-text.d.ts +1 -1
- package/lib/types/model-text.js +1 -1
- package/lib/types/oplog.d.ts +98 -0
- package/lib/types/oplog.d.ts.map +1 -0
- package/lib/types/oplog.js +178 -0
- package/lib/types/oplog.js.map +1 -0
- package/lib/types/present.d.ts +0 -3
- package/lib/types/present.d.ts.map +1 -1
- package/lib/types/present.js +6 -7
- package/lib/types/present.js.map +1 -1
- package/lib/types/query-analysis.d.ts +37 -0
- package/lib/types/query-analysis.d.ts.map +1 -0
- package/lib/types/query-analysis.js +103 -0
- package/lib/types/query-analysis.js.map +1 -0
- package/lib/types/recall-rank.d.ts +2 -2
- package/lib/types/recall-rank.d.ts.map +1 -1
- package/lib/types/recall-rank.js +3 -3
- package/lib/types/recall-rank.js.map +1 -1
- package/lib/types/runtime.d.ts +1057 -203
- package/lib/types/runtime.d.ts.map +1 -1
- package/lib/types/runtime.js +4518 -1316
- package/lib/types/runtime.js.map +1 -1
- package/lib/types/settings-schema.d.ts +6 -14
- package/lib/types/settings-schema.d.ts.map +1 -1
- package/lib/types/settings-schema.js +5 -7
- package/lib/types/settings-schema.js.map +1 -1
- package/lib/types/source-images.d.ts +33 -0
- package/lib/types/source-images.d.ts.map +1 -1
- package/lib/types/source-images.js +56 -0
- package/lib/types/source-images.js.map +1 -1
- package/lib/types/store/derived.d.ts +145 -0
- package/lib/types/store/derived.d.ts.map +1 -0
- package/lib/types/store/derived.js +295 -0
- package/lib/types/store/derived.js.map +1 -0
- package/lib/types/store/knowledge-db.d.ts +404 -0
- package/lib/types/store/knowledge-db.d.ts.map +1 -0
- package/lib/types/store/knowledge-db.js +1198 -0
- package/lib/types/store/knowledge-db.js.map +1 -0
- package/lib/types/store/migrate.d.ts +172 -0
- package/lib/types/store/migrate.d.ts.map +1 -0
- package/lib/types/store/migrate.js +498 -0
- package/lib/types/store/migrate.js.map +1 -0
- package/lib/types/store/views.d.ts +118 -0
- package/lib/types/store/views.d.ts.map +1 -0
- package/lib/types/store/views.js +237 -0
- package/lib/types/store/views.js.map +1 -0
- package/lib/types/types.d.ts +331 -253
- package/lib/types/types.d.ts.map +1 -1
- package/lib/types/types.js +26 -350
- package/lib/types/types.js.map +1 -1
- package/lib/types/wiki-finalize.d.ts +48 -31
- package/lib/types/wiki-finalize.d.ts.map +1 -1
- package/lib/types/wiki-finalize.js +65 -39
- package/lib/types/wiki-finalize.js.map +1 -1
- package/lib/types/wiki-materialize.d.ts +84 -0
- package/lib/types/wiki-materialize.d.ts.map +1 -0
- package/lib/types/wiki-materialize.js +171 -0
- package/lib/types/wiki-materialize.js.map +1 -0
- package/lib/types/wiki-trial-types.d.ts +298 -0
- package/lib/types/wiki-trial-types.d.ts.map +1 -0
- package/lib/types/wiki-trial-types.js +18 -0
- package/lib/types/wiki-trial-types.js.map +1 -0
- package/lib/types/wiki-trial.d.ts +255 -0
- package/lib/types/wiki-trial.d.ts.map +1 -0
- package/lib/types/wiki-trial.js +1191 -0
- package/lib/types/wiki-trial.js.map +1 -0
- package/lib/types/wiki-types.d.ts +15 -17
- package/lib/types/wiki-types.d.ts.map +1 -1
- package/lib/types/wiki-types.js +46 -70
- package/lib/types/wiki-types.js.map +1 -1
- package/package.json +8 -5
- package/preset/tita-data-agent/agent.cordis.yml +23 -20
- package/scripts/doctor.mjs +5 -9
- package/scripts/e2e-pipeline.mjs +0 -3
- package/src/axis-contract.ts +35 -0
- package/src/axis-registry.ts +880 -0
- package/src/card-organize.ts +836 -0
- package/src/client/AgentPresetCard.tsx +3 -3
- package/src/client/AttributionEventGuide.tsx +175 -0
- package/src/client/AxisMatrix.tsx +389 -0
- package/src/client/AxisRegistrySection.tsx +394 -0
- package/src/client/CompileDialogs.tsx +265 -0
- package/src/client/DeleteDocumentDialog.tsx +198 -0
- package/src/client/DirectoryPicker.tsx +12 -78
- package/src/client/ExpansionGraph.tsx +251 -0
- package/src/client/ImportFilesDialog.tsx +331 -0
- package/src/client/InfoHint.tsx +40 -5
- package/src/client/{IntentLogicTab.tsx → IntentLogic.tsx} +33 -26
- package/src/client/IntentTab.tsx +152 -589
- package/src/client/KnowledgeBaseTab.tsx +1774 -754
- package/src/client/KnowledgeLayerSection.tsx +629 -0
- package/src/client/KnowledgePanel.tsx +78 -22
- package/src/client/KnowledgeStepRail.tsx +17 -12
- package/src/client/KnowledgeToolRow.tsx +299 -126
- package/src/client/ListPager.tsx +81 -0
- package/src/client/NodeSettings.tsx +28 -48
- package/src/client/OperationLogTab.tsx +295 -0
- package/src/client/PreviewSections.tsx +431 -62
- package/src/client/RecallPanel.tsx +376 -105
- package/src/client/RelatedGraph.tsx +221 -0
- package/src/client/TabGuide.tsx +439 -0
- package/src/client/TrialReportView.tsx +449 -0
- package/src/client/TypeDefinitionDrawer.tsx +38 -285
- package/src/client/WikiCardPreview.tsx +277 -0
- package/src/client/WikiCardReview.tsx +93 -104
- package/src/client/WikiCardRow.tsx +121 -0
- package/src/client/WikiFlowPanel.tsx +577 -0
- package/src/client/WikiTrialRun.tsx +216 -0
- package/src/client/agent-preset.ts +3 -3
- package/src/client/arch/AgentArchitectureGraph.tsx +2 -2
- package/src/client/arch/NodeLogicPanel.tsx +2 -2
- package/src/client/arch/ProblemDetailPanel.tsx +2 -2
- package/src/client/arch/model.ts +147 -16
- package/src/client/architecture.tsx +79 -75
- package/src/client/asset-images.ts +30 -3
- package/src/client/attribution/AttributionGraph.tsx +2 -2
- package/src/client/attribution/AttributionTab.tsx +41 -11
- package/src/client/attribution/CaseView.tsx +2 -2
- package/src/client/attribution/GraphStage.tsx +1 -1
- package/src/client/attribution/RunView.tsx +2 -2
- package/src/client/attribution/StageChrome.tsx +2 -2
- package/src/client/attribution/ViewSwitch.tsx +2 -2
- package/src/client/axis-lookup.ts +74 -0
- package/src/client/config-scope.ts +2 -2
- package/src/client/convert/ConvertPanel.tsx +11 -54
- package/src/client/doc-page.css +2 -2
- package/src/client/doc-page.tsx +8 -11
- package/src/client/graph/edges.ts +42 -0
- package/src/client/graph/expansion.ts +71 -0
- package/src/client/graph/layout.ts +112 -99
- package/src/client/graph/related.ts +235 -0
- package/src/client/index.ts +12 -6
- package/src/client/ledger.tsx +436 -0
- package/src/client/pages.css +461 -0
- package/src/client/pages.tsx +255 -0
- package/src/client/preview-citations.ts +145 -0
- package/src/client/problem-domains.ts +5 -5
- package/src/client/styles.css +1692 -189
- package/src/client/useFitScale.ts +10 -10
- package/src/client/wiki-trial.ts +414 -0
- package/src/config-schema.ts +6 -10
- package/src/convert/host.ts +6 -44
- package/src/convert/ingest.ts +128 -55
- package/src/convert/settings-schema.ts +2 -2
- package/src/diagnosis/cards.ts +42 -11
- package/src/diagnosis/schema.ts +1 -1
- package/src/diagnosis/seed-source.ts +2 -13
- package/src/diagnosis/seed.ts +2 -2
- package/src/diagnosis/store.ts +18 -18
- package/src/extract-model.ts +15 -11
- package/src/extract.ts +4 -4
- package/src/extraction-runs.ts +216 -0
- package/src/fs-atomic.ts +1 -2
- package/src/fts.ts +2 -2
- package/src/index.ts +717 -173
- package/src/intent/README.md +27 -50
- package/src/intent/engine.ts +28 -78
- package/src/intent/host.ts +30 -218
- package/src/intent/preset-tools.ts +3 -3
- package/src/intent/store.ts +180 -105
- package/src/intent/tools.ts +8 -35
- package/src/intent/types.ts +9 -32
- package/src/knowledge-bases.ts +29 -672
- package/src/knowledge.ts +1524 -0
- package/src/layout.ts +106 -29
- package/src/migrate.ts +45 -4
- package/src/model-text.ts +1 -1
- package/src/oplog.ts +214 -0
- package/src/present.ts +9 -10
- package/src/python/embedding_worker.py +17 -2
- package/src/query-analysis.ts +135 -0
- package/src/recall-rank.ts +4 -4
- package/src/runtime.ts +4662 -1267
- package/src/settings-schema.ts +5 -7
- package/src/source-images.ts +55 -0
- package/src/store/derived.ts +316 -0
- package/src/store/knowledge-db.ts +1375 -0
- package/src/store/migrate.ts +590 -0
- package/src/store/views.ts +313 -0
- package/src/types.ts +338 -554
- package/src/wiki-finalize.ts +72 -43
- package/src/wiki-materialize.ts +213 -0
- package/src/wiki-trial-types.ts +293 -0
- package/src/wiki-trial.ts +1319 -0
- package/src/wiki-types.ts +47 -78
- package/lib/types/intent/settings-schema.d.ts +0 -59
- package/lib/types/intent/settings-schema.d.ts.map +0 -1
- package/lib/types/intent/settings-schema.js +0 -57
- package/lib/types/intent/settings-schema.js.map +0 -1
- package/src/client/KnowledgeGraphView.tsx +0 -306
- package/src/client/WikiFlowCard.tsx +0 -188
- package/src/client/WikiTypeEditor.tsx +0 -434
- package/src/client/graph.css +0 -113
- package/src/client/wiki-type-groups.ts +0 -86
- package/src/intent/settings-schema.ts +0 -63
|
@@ -0,0 +1,899 @@
|
|
|
1
|
+
# 智能归因排查案例集 · CASE-004 ~ CASE-015
|
|
2
|
+
|
|
3
|
+
**状态**:草稿,待人评审。评审通过后这批案例要落两处 —— seed 数据(`src/diagnosis/seed.ts`)与排查侧标定集。
|
|
4
|
+
|
|
5
|
+
**配套**:[20260926-智能归因图谱.md](../../../../../docs/prd/20260926-智能归因图谱.md)(节点 / 边 / 指标)、
|
|
6
|
+
[20260926-知识召回与问题排查-评测方案.md](../../../../../docs/prd/20260926-知识召回与问题排查-评测方案.md)(这套标定集的用途与规模)。
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 0. 为什么是这 12 条
|
|
11
|
+
|
|
12
|
+
现有 seed 只有 3 个案例,覆盖 3 个子类;`problem-classes.ts` 登记了 **4 大类 / 15 子类**,
|
|
13
|
+
也就是说 **12 个子类零样本**,其中 `不一致` 和 `粒度` 两个大类**完全没有样本**。
|
|
14
|
+
一份没有反例的分类表,校验不出边界,也算不出先验。
|
|
15
|
+
|
|
16
|
+
| 大类 | 子类总数 | 已有样本 | 本批补 |
|
|
17
|
+
| --- | --- | --- | --- |
|
|
18
|
+
| 缺失 | 3 | 1(CASE-001) | 2 |
|
|
19
|
+
| 偏差 | 4 | 2(CASE-002/003) | 2 |
|
|
20
|
+
| 不一致 | 4 | 0 | 4 |
|
|
21
|
+
| 粒度 | 4 | 0 | 4 |
|
|
22
|
+
| **合计** | **15** | **3** | **12** |
|
|
23
|
+
|
|
24
|
+
补完之后 **15 / 15 全覆盖**。覆盖矩阵见 [附录 B](#附录-b覆盖率矩阵)。
|
|
25
|
+
|
|
26
|
+
案例的机制不是编的,词表对着两处真实来源核过:Monte Carlo 开源的
|
|
27
|
+
[Common Root Cause Catalog](https://github.com/monte-carlo-data/mc-agent-toolkit/blob/main/skills/analyze-root-cause/references/common-root-causes.md)
|
|
28
|
+
(pipeline scheduling failure / upstream cascade / query regression / JOIN cardinality change /
|
|
29
|
+
late-arriving data / schema drift 等),以及评测方案 §6.4 记的五类根因切面。
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 1. 链条:现象 → 现象验证 → 假设原因 → 检查点 → 证据 → 根因
|
|
34
|
+
|
|
35
|
+
### 1.1 为什么要加「现象验证」
|
|
36
|
+
|
|
37
|
+
原设计的第一跳是 `现象 → 假设`(`S1 → H1`)。**这一跳丢了一步**:在问「为什么这个数不对」之前,
|
|
38
|
+
得先回答「这个数是不是真的不对」。
|
|
39
|
+
|
|
40
|
+
这两种情况必须分开,因为它们的出口完全不同:
|
|
41
|
+
|
|
42
|
+
| | 现象验证不成立 | 原因假设被否定 |
|
|
43
|
+
| --- | --- | --- |
|
|
44
|
+
| 回答的问题 | 这个异常是不是真的、值不值得归因 | 在异常成立的前提下,原因在哪一环 |
|
|
45
|
+
| 结论 | **关单**,不进归因 | 换下一条假设 |
|
|
46
|
+
| 例子 | 基期是大促日,对比不公平 | 「上游未产出」被分区行数正常否定 |
|
|
47
|
+
|
|
48
|
+
日常场景:报警说「今日 GMV 跌了 40%」。先别看链路,先看**昨天是不是双十一**。
|
|
49
|
+
是,那就关单 —— 这不是数据事故,是对比事故。跳过这一步的代价是拿一次误报去烧一整轮排查。
|
|
50
|
+
|
|
51
|
+
### 1.2 现象验证的五个维度
|
|
52
|
+
|
|
53
|
+
每条案例按需要挑几维,不要求全跑。
|
|
54
|
+
|
|
55
|
+
| 代号 | 验什么 | 典型手段 | 不成立意味着 |
|
|
56
|
+
| --- | --- | --- | --- |
|
|
57
|
+
| `观测` | 我读到的数对不对 | 换入口重查、直连明细、核对查询条件与统计时区 | 现象是查询或展示写错造成的 |
|
|
58
|
+
| `基期` | 对比公不公平 | 同口径版本、同天数、同类日(工作日 / 节假日 / 大促) | 现象是「对比错了」,数据没变 |
|
|
59
|
+
| `时点` | 到产出时点了吗 | 观测时点 vs 任务 SLA 承诺时点 | 看早了,等一会儿就正常 |
|
|
60
|
+
| `噪声` | 幅度超没超正常波动 | 与历史 30 / 90 天波动区间比 | 落在正常波动内,不构成异常 |
|
|
61
|
+
| `业务` | 业务侧有没有解释 | 问活动 / 投放 / 规则变更 | 现象成立,但根因在业务侧,不进数据归因 |
|
|
62
|
+
|
|
63
|
+
`时点` 和「任务失败未产出」是两件事:前者是**还没到点**,后者是**过了点还没出来**。后者的根因是故障,前者不是。
|
|
64
|
+
|
|
65
|
+
### 1.3 编号规则
|
|
66
|
+
|
|
67
|
+
沿用 seed 已有的 `T<n>.<m>` 形态,只加一个 `0` 号位:
|
|
68
|
+
|
|
69
|
+
| 编号 | 含义 |
|
|
70
|
+
| --- | --- |
|
|
71
|
+
| `T0.x` | **现象验证**的检查点,挂在现象节点上 |
|
|
72
|
+
| `E0.x` | `T0.x` 产出的证据 |
|
|
73
|
+
| `T<n>.x`(n≥1) | 原因假设 `H<n>` 下面的检查点,与 seed 一致 |
|
|
74
|
+
|
|
75
|
+
`E0.x` 的 `supports` / `refutes` 指向**现象节点**而不是假设节点 —— 这是链条上唯一需要改 schema 的地方,见 [附录 D](#附录-d这批案例要求-schema-改什么)。
|
|
76
|
+
|
|
77
|
+
### 1.4 每条案例的格式
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
元信息表 → ① 现象 ② 现象验证 ③ 假设原因 ④ 检查点 ⑤ 证据 ⑥ 根因与修复 ⑦ 写回
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`④ 检查点` 的严格判据沿用 0021 §4.1 的硬性约束:一个检查点必须能回答
|
|
84
|
+
**谁、用什么、多久、看到什么算真、看到什么算假**。回答不了就不是检查点。
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 2. 案例
|
|
89
|
+
|
|
90
|
+
### CASE-004 · 「用户活跃日报」整页空白
|
|
91
|
+
|
|
92
|
+
| 项 | 值 |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| 子类 | `missing-no-partition` · 分区 / 表未产出 |
|
|
95
|
+
| 形态 / 时间模式 | `zero` · 单日 |
|
|
96
|
+
| 现象 | 2026-09-14 08:10,用户活跃日报整页空白,接口返回 `[]`(不是 0) |
|
|
97
|
+
| 真实路径 | `S → T0.2(时点) → H1 → T1.2 → E2 → C1` |
|
|
98
|
+
| 耗时 | 38 分钟(其中 20 分钟被 `T1.1` 返回的 success 带偏) |
|
|
99
|
+
| 根因 | `ads_user_active_1d` 分区字段类型从 `string` 改成 `date`,写入时隐式转换失败被静默吞掉,任务返回 success 但没产出分区 |
|
|
100
|
+
|
|
101
|
+
**① 现象**:`ads_user_active_1d / dt=2026-09-14` 整表不存在,下游「用户活跃日报」返回空数组。
|
|
102
|
+
其余日期正常,总活跃口径(另一个报表,读 `dws_user_active_1d`)正常。
|
|
103
|
+
|
|
104
|
+
**② 现象验证**
|
|
105
|
+
|
|
106
|
+
| 编号 | 维度 | 怎么验 | 成本 | 自动化 | 成立判据 | 不成立判据 | 结论 |
|
|
107
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
108
|
+
| `T0.1` | `观测` | 直连 `show partitions ads_user_active_1d` | 1 min | 自动 | 分区列表里没有 `dt=2026-09-14` | 分区在、行数为 0(那是另一类) | **成立**(是真缺失,不是前端问题) |
|
|
109
|
+
| `T0.2` | `时点` | 比对 SLA 承诺时点与当前时点 | 1 min | 自动 | 当前时点 > SLA(08:00) | 当前时点 < SLA | **成立**(是真缺失,不是看早了) |
|
|
110
|
+
| `T0.3` | `基期` | —— | —— | —— | 缺失类不做幅度比对 | —— | 不适用 |
|
|
111
|
+
|
|
112
|
+
**③ 假设原因**
|
|
113
|
+
|
|
114
|
+
| 编号 | 假设(一句可判真假的话) | 失败原因 | 结论 |
|
|
115
|
+
| --- | --- | --- | --- |
|
|
116
|
+
| `H1` | 上游分区未产出 → 本表无输入 | 上游未产出 | **确认** |
|
|
117
|
+
| `H2` | 任务报错未产出 | 数据处理 | 被 `T1.1` 否定(实例 success) |
|
|
118
|
+
| `H3` | 读取方权限被收 → 我看到的是空的 | 权限与过滤 | 被 `T1.3` 否定(换账号查仍是空) |
|
|
119
|
+
|
|
120
|
+
**④ 检查点**
|
|
121
|
+
|
|
122
|
+
| 编号 | 检查 | 资产 | 成本 | 自动化 | 看到什么算真 | 看到什么算假 | 结论 |
|
|
123
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
124
|
+
| `T1.1` | 查本任务当日实例状态 | 调度:`ads_user_active_1d` | 1 min | 自动 | 状态 failed | 状态 success → **排除 H2** | success,H2 被否定 |
|
|
125
|
+
| `T1.2` | 对比 DDL 的分区字段定义与写入语句 | `ads_user_active_1d` | 3 min | 人工 | 类型不一致 | 类型一致 | **命中**:DDL 是 `date`,写入按 `string` 传参 |
|
|
126
|
+
| `T1.3` | 换账号 / 换引擎重查同一分区 | `ads_user_active_1d` | 2 min | 人工 | 能查到数据 | 仍查不到 | 仍查不到,H3 被否定 |
|
|
127
|
+
|
|
128
|
+
**⑤ 证据**
|
|
129
|
+
|
|
130
|
+
| 编号 | 来源 | 看到什么 | 为什么算数 |
|
|
131
|
+
| --- | --- | --- | --- |
|
|
132
|
+
| `E1` | `T1.1` | `success`,无报错 | 算数:调度日志与任务日志一致。**但这条证据只能否定 H2,不能证明 H1** —— 它给不出「为什么没产出」 |
|
|
133
|
+
| `E2` | `T1.2` | 建表 DDL 的 `dt` 是 `date`,写入侧 `partition(dt='2026-09-14')` 传字符串,Spark 隐式转换失败后**没有抛错**,静默跳过写入 | 算数:DDL 变更记录 + 任务日志双证 |
|
|
134
|
+
|
|
135
|
+
**⑥ 根因与修复**:`C1` —— 分区字段类型变更未同步写入逻辑,写入失败被静默吞掉。
|
|
136
|
+
修复:写入侧显式 `cast`;同时给该任务补一条「产出后校验分区存在」的断言,让「成功但没产出」不再可能。
|
|
137
|
+
|
|
138
|
+
**⑦ 写回**
|
|
139
|
+
|
|
140
|
+
- `H1` 命中 +1;新增 `refutes`(`E1` → `H2`,`because` = 「实例 success」)
|
|
141
|
+
- **新增误导边**:`T1.1`(1 min,自动,返回 success)→ 看起来排除了上游问题,实际给不出结论。这是本批第二条「便宜检查没有结论」的边,与 CASE-001 的 `T7.1` 同类
|
|
142
|
+
- 新增检查点卡片 `T1.2`:判据是「对比 DDL 类型与写入传参类型是否一致」
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
### CASE-005 · 支付转化率为 0,但上游分区正常
|
|
147
|
+
|
|
148
|
+
| 项 | 值 |
|
|
149
|
+
| --- | --- |
|
|
150
|
+
| 子类 | `missing-job-failed` · 任务报错未产出 |
|
|
151
|
+
| 形态 / 时间模式 | `error` · 单日 |
|
|
152
|
+
| 现象 | 2026-09-20 09:00,支付转化率 = 0;`dwd_pay_di / dt=2026-09-19` 分区存在但行数 0 |
|
|
153
|
+
| 真实路径 | `S → T0.2(时点) → H1 → T1.1✗ → H2 → T2.2 → E2 → C1` |
|
|
154
|
+
| 耗时 | 26 分钟 |
|
|
155
|
+
| 根因 | 源表字段改名(schema drift),下游任务编译失败;调度器的「预建分区」步骤先成功了,留下一个空分区,告警只配在「分区不存在」上所以没响 |
|
|
156
|
+
|
|
157
|
+
**① 现象**:支付转化率 = 0(前一日 38.2%)。分区在、行数为 0,不是分区缺失。
|
|
158
|
+
|
|
159
|
+
**② 现象验证**
|
|
160
|
+
|
|
161
|
+
| 编号 | 维度 | 怎么验 | 成本 | 自动化 | 成立判据 | 不成立判据 | 结论 |
|
|
162
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
163
|
+
| `T0.1` | `观测` | 直连 `select count(*)` | 1 min | 自动 | 行数为 0 | 行数正常 → 是展示层问题 | **成立** |
|
|
164
|
+
| `T0.2` | `时点` | 比对 SLA(07:30) | 1 min | 自动 | 已过 SLA | 未到 SLA | **成立** |
|
|
165
|
+
| `T0.3` | `噪声` | —— | —— | —— | 为 0 不做幅度比对 | —— | 不适用 |
|
|
166
|
+
|
|
167
|
+
**③ 假设原因**
|
|
168
|
+
|
|
169
|
+
| 编号 | 假设 | 失败原因 | 结论 |
|
|
170
|
+
| --- | --- | --- | --- |
|
|
171
|
+
| `H1` | 上游 `ods_pay_sync` 未产出 | 上游未产出 | 被 `T1.1` 否定(上游 success、行数 1,240 万) |
|
|
172
|
+
| `H2` | 本任务报错未产出 | 数据处理 | **确认** |
|
|
173
|
+
| `H3` | 权限被收 | 权限与过滤 | 未走到 |
|
|
174
|
+
|
|
175
|
+
**④ 检查点**
|
|
176
|
+
|
|
177
|
+
| 编号 | 检查 | 资产 | 成本 | 自动化 | 真 / 假判据 | 结论 |
|
|
178
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
179
|
+
| `T1.1` | 查上游 `ods_pay_sync` 实例与行数 | 调度、`ods_pay_sync` | 1 min | 自动 | 真:上游 failed 或行数 0 | 上游 success、行数正常 → H1 否定 |
|
|
180
|
+
| `T2.1` | 查本任务实例状态与日志尾部 | `dwd_pay_di` | 1 min | 自动 | 真:failed / 有异常栈 | **failed**,`AnalysisException: cannot resolve 'shop_id'` |
|
|
181
|
+
| `T2.2` | 对比源表当前 schema 与任务里引用的字段 | `ods_pay_sync` | 3 min | 人工 | 真:字段缺失或改名 | **命中**:源表 09-18 把 `shop_id` 改名为 `shop_code` |
|
|
182
|
+
|
|
183
|
+
**⑤ 证据**
|
|
184
|
+
|
|
185
|
+
| 编号 | 来源 | 看到什么 | 为什么算数 |
|
|
186
|
+
| --- | --- | --- | --- |
|
|
187
|
+
| `E1` | `T1.1` | 上游 success、1,240 万行 | 算数:直接读上游分区行数,不依赖下游 |
|
|
188
|
+
| `E2` | `T2.2` | 源表 DDL 变更记录:`shop_id` → `shop_code`,09-18 生效 | 算数:DDL 历史 + 任务报错栈里的字段名对得上 |
|
|
189
|
+
|
|
190
|
+
**⑥ 根因与修复**:`C1` —— 源系统 schema drift 导致下游编译失败。
|
|
191
|
+
修复:任务改用 `select * except(...)` 之外的模式前先加 schema 契约检查;**并把告警从「分区不存在」改成「分区行数 < 阈值」**,否则空分区永远不告警。
|
|
192
|
+
|
|
193
|
+
**⑦ 写回**
|
|
194
|
+
|
|
195
|
+
- `H2` 命中 +1;新增 `refutes`(`E1` → `H1`)
|
|
196
|
+
- **新增误导边**:`分区存在` 这个事实本身会让人排除「没产出」—— 分区存在和分区有数据是两件事
|
|
197
|
+
- 新增一条**告警配置反例**:只配「分区不存在」的告警对空分区无效
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
### CASE-006 · GMV 连续 5 天缓降 18%
|
|
202
|
+
|
|
203
|
+
| 项 | 值 |
|
|
204
|
+
| --- | --- |
|
|
205
|
+
| 子类 | `deviation-drop-slow` · 缓降 |
|
|
206
|
+
| 形态 / 时间模式 | `low` · `drop-slow` |
|
|
207
|
+
| 现象 | GMV 每日环比约 -4%,5 天累计 -18%(128 万 → 105 万),无单日骤降 |
|
|
208
|
+
| 真实路径 | `S → T0.1(业务) → H3 → T3.1✗ → H4 → T4.2 → E3 → C1` |
|
|
209
|
+
| 耗时 | 51 分钟 |
|
|
210
|
+
| 根因 | 支付系统灰度升级引入新枚举值 `paid_v2`,`dwd_ord_di` 的 `where pay_status in ('paid','shipped')` 没覆盖它;灰度按渠道推进,所以表现为**缓降**而非骤降 |
|
|
211
|
+
|
|
212
|
+
**① 现象**:GMV 从 09-15 起每日环比 -4%~-6%,连续 5 天,累计 -18%。单看每一天都不像异常。
|
|
213
|
+
|
|
214
|
+
**② 现象验证**
|
|
215
|
+
|
|
216
|
+
| 编号 | 维度 | 怎么验 | 成本 | 自动化 | 成立判据 | 不成立判据 | 结论 |
|
|
217
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
218
|
+
| `T0.1` | `业务` | 问运营:有没有停投放、改活动规则 | 5 min | 人工 | 业务无变更 | 业务确有变更 → 关单 | **成立**(运营确认无变更) |
|
|
219
|
+
| `T0.2` | `基期` | 查去年同期同窗口 | 2 min | 自动 | 去年同期平稳 | 去年同期也在降 → 季节性 | **成立**(去年 -0.8%/天) |
|
|
220
|
+
| `T0.3` | `噪声` | 与历史 30 天波动区间比 | 2 min | 自动 | 累计跌幅超出区间 | 在区间内 → 关单 | **成立**(历史区间 ±5%,本次 -18%) |
|
|
221
|
+
| `T0.4` | `观测` | 直连 `dwd_ord_di` 复核 | 2 min | 自动 | 数值一致 | 不一致 → 展示层问题 | **成立** |
|
|
222
|
+
|
|
223
|
+
**③ 假设原因**
|
|
224
|
+
|
|
225
|
+
| 编号 | 假设 | 失败原因 | 结论 |
|
|
226
|
+
| --- | --- | --- | --- |
|
|
227
|
+
| `H3` | 维表映射丢失,`unknown` 占比升高 | 数据处理 | **部分支持但不是主因**(量级差 10 倍) |
|
|
228
|
+
| `H4` | 加工逻辑过滤掉了部分有效数据 | 数据处理 | **确认** |
|
|
229
|
+
| `H5` | 上游源数据本身在减少 | 上游未产出 | 被 `T4.1` 否定(源数据平稳) |
|
|
230
|
+
|
|
231
|
+
**④ 检查点**
|
|
232
|
+
|
|
233
|
+
| 编号 | 检查 | 资产 | 成本 | 自动化 | 真 / 假判据 | 结论 |
|
|
234
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
235
|
+
| `T3.1` | 按天统计 `unknown` 占比 | `dim_channel_df`、`dwd_ord_di` | 2 min | 自动 | 真:占比升幅与跌幅同量级 | 0.2% → 1.8%,**与 -18% 差一个量级** → 不是主因 |
|
|
236
|
+
| `T4.1` | 对比 `ods_order_sync` 与 `dwd_ord_di` 的分渠道行数 | `ods_order_sync`、`dwd_ord_di` | 3 min | 自动 | 真:上游也降 | 上游平稳 → H5 否定 |
|
|
237
|
+
| `T4.2` | 查 `dwd_ord_di` 的 `where` 条件与最近变更 | `dwd_ord_di` | 3 min | 人工 | 真:过滤条件近期有变更 | **命中**:09-15 加了 `pay_status in ('paid','shipped')` |
|
|
238
|
+
| `T4.3` | 查源数据里 `pay_status` 的全部取值分布 | `ods_pay_di` | 2 min | 自动 | 真:出现枚举外的值 | **命中**:`paid_v2` 占比从 0.5% 升到 17% |
|
|
239
|
+
|
|
240
|
+
**⑤ 证据**
|
|
241
|
+
|
|
242
|
+
| 编号 | 来源 | 看到什么 | 为什么算数 |
|
|
243
|
+
| --- | --- | --- | --- |
|
|
244
|
+
| `E3` | `T4.2` + `T4.3` | 过滤条件只认两个状态值,而源里出现了第三个;`paid_v2` 的分布时间曲线与跌幅曲线形状一致 | 算数:两条独立证据交叉印证,且**时间曲线吻合**才算数 —— 只看「有第三个值」不够 |
|
|
245
|
+
|
|
246
|
+
**⑥ 根因与修复**:`C1` —— 加工逻辑未覆盖新增枚举值,灰度升级导致受影响范围逐日扩大。
|
|
247
|
+
修复:`where` 改为 `pay_status like 'paid%'` 或走状态码白名单表;补一条「源表枚举值超出任务白名单」的监控。
|
|
248
|
+
|
|
249
|
+
**⑦ 写回**
|
|
250
|
+
|
|
251
|
+
- `H4` 命中 +1;新增 `refutes`(`E1` → `H5`)
|
|
252
|
+
- **新增误导边**:`T3.1` 给出的 `unknown` 缓升与主因**形状一致、量级差 10 倍**。这是「并存的第二个问题被误当主因」—— 图上要记这条,它是权重该看「量级是否匹配」而不只看「方向是否一致」的直接依据
|
|
253
|
+
- 新增检查点 `T4.3`:判据是「源表枚举取值是否超出任务白名单」
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
### CASE-007 · 客单价连续 7 天缓升 10.5%
|
|
258
|
+
|
|
259
|
+
| 项 | 值 |
|
|
260
|
+
| --- | --- |
|
|
261
|
+
| 子类 | `deviation-rise-slow` · 缓升 |
|
|
262
|
+
| 形态 / 时间模式 | `high` · `rise-slow` |
|
|
263
|
+
| 现象 | 客单价 ¥152 → ¥168(+10.5%),连续 7 天,每日约 +1.4% |
|
|
264
|
+
| 真实路径 | `S → T0.1(业务) → H2 → T2.1✗ → H6 → T6.2 → E4 → C1` |
|
|
265
|
+
| 耗时 | 33 分钟 |
|
|
266
|
+
| 根因 | 口径版本 v3 上线时漏了 `- coupon_amount` 扣减项;同期券使用率从 2% 缓升到 11%,两者叠加表现为客单价缓升 |
|
|
267
|
+
|
|
268
|
+
**① 现象**:客单价(AOV = GMV / 订单数)连续 7 天缓升 10.5%。GMV 与订单数各自都在正常区间。
|
|
269
|
+
|
|
270
|
+
**② 现象验证**
|
|
271
|
+
|
|
272
|
+
| 编号 | 维度 | 怎么验 | 成本 | 自动化 | 成立判据 | 不成立判据 | 结论 |
|
|
273
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
274
|
+
| `T0.1` | `业务` | 问运营:有没有调价、改促销规则 | 5 min | 人工 | 无变更 | 有变更 → 关单 | **成立** |
|
|
275
|
+
| `T0.2` | `基期` | 查去年同期 | 2 min | 自动 | 去年平稳 | 去年同升 → 季节性 | **成立** |
|
|
276
|
+
| `T0.3` | `噪声` | 与历史 30 天区间比 | 2 min | 自动 | +10.5% 超出 ±3% | 在区间内 | **成立** |
|
|
277
|
+
| `T0.4` | `观测` | 直连复核 GMV 与订单数 | 2 min | 自动 | 一致 | 不一致 → 展示层 | **成立** |
|
|
278
|
+
|
|
279
|
+
**③ 假设原因**
|
|
280
|
+
|
|
281
|
+
| 编号 | 假设 | 失败原因 | 结论 |
|
|
282
|
+
| --- | --- | --- | --- |
|
|
283
|
+
| `H2` | 高客单品类占比上升 | 数据处理 | 被 `T2.1` 否定(品类结构只解释了 0.4 个点) |
|
|
284
|
+
| `H6` | 口径版本变更漏了扣减项 | 口径变更 | **确认** |
|
|
285
|
+
| `H7` | 促销只作用在部分品类 | 数据处理 | 被 `T6.3` 否定 |
|
|
286
|
+
|
|
287
|
+
**④ 检查点**
|
|
288
|
+
|
|
289
|
+
| 编号 | 检查 | 资产 | 成本 | 自动化 | 真 / 假判据 | 结论 |
|
|
290
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
291
|
+
| `T2.1` | 按品类拆解客单价的加权贡献 | `dim_category_df`、`dwd_ord_di` | 4 min | 自动 | 真:某品类权重变化能解释大部分升幅 | 只解释 0.4 / 10.5 个点 → H2 否定 |
|
|
292
|
+
| `T6.1` | 查 GMV 指标的口径版本与变更记录 | 指标口径注册表 | 2 min | 自动 | 真:近期有版本变更 | **命中**:09-18 上线 v3 |
|
|
293
|
+
| `T6.2` | 对比 v2 / v3 的 SQL 差异 | 口径注册表 | 3 min | 人工 | 真:有未同步到下游的扣减项变化 | **命中**:v3 漏 `- coupon_amount` |
|
|
294
|
+
| `T6.3` | 统计券抵扣金额占订单金额的比例(按天) | `dwd_ord_di` | 2 min | 自动 | 真:占比升幅与外显升幅吻合 | **命中**:2% → 11%,曲线吻合 |
|
|
295
|
+
|
|
296
|
+
**⑤ 证据**
|
|
297
|
+
|
|
298
|
+
| 编号 | 来源 | 看到什么 | 为什么算数 |
|
|
299
|
+
| --- | --- | --- | --- |
|
|
300
|
+
| `E4` | `T6.2` + `T6.3` | 口径漏扣 + 券使用率缓升 → 复算后残差 < 0.3% | 算数:**复算能对上**是这类证据的判据。只说「口径改了」不算数,因为改了不一定影响这个指标 |
|
|
301
|
+
|
|
302
|
+
**⑥ 根因与修复**:`C1` —— 口径版本上线时的遗漏项,被同期缓升的券使用率放大成一条可见趋势。
|
|
303
|
+
修复:补 `- coupon_amount`;口径版本上线加「新旧口径并行对账 7 天」的强制步骤。
|
|
304
|
+
|
|
305
|
+
**⑦ 写回**
|
|
306
|
+
|
|
307
|
+
- `H6` 命中 +1;新增 `refutes`(`E2` → `H2`)
|
|
308
|
+
- **新增一条检查点判据**:`T6.3` 的 `verdict_true` 要求「占比曲线与外显曲线**形状吻合**」,不是「占比在上升」——只写后者的话这条检查永远返回真
|
|
309
|
+
- 记录一条规律:**缓升 / 缓降类现象,根因往往有一个「渐进的自变量」**(券使用率、灰度比例、新客占比)。这条规律进手册
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
### CASE-008 · 数仓 GMV 比源系统多算 2.8 万
|
|
314
|
+
|
|
315
|
+
| 项 | 值 |
|
|
316
|
+
| --- | --- |
|
|
317
|
+
| 子类 | `inconsistency-vs-source` · 与源系统对不上 |
|
|
318
|
+
| 形态 / 时间模式 | `mismatch` · 单日 |
|
|
319
|
+
| 现象 | 数仓 GMV 131.2 万 vs 源系统 128.4 万,多算 2.8 万(+2.2%) |
|
|
320
|
+
| 真实路径 | `S → T0.2(基期) → H4 → T4.1 → E3 → C1` |
|
|
321
|
+
| 耗时 | 29 分钟 |
|
|
322
|
+
| 根因 | 订单取消事件不在 `order_update` 里,同步任务只订阅了 `order_create` / `order_update`;09-08 上线「下单 5 分钟未支付自动取消」后取消量从 0.3% 涨到 2.1% |
|
|
323
|
+
|
|
324
|
+
**① 现象**:财务对账不平,数仓比源系统多 2.8 万。两边各自复核后数稳定。
|
|
325
|
+
|
|
326
|
+
**② 现象验证**
|
|
327
|
+
|
|
328
|
+
| 编号 | 维度 | 怎么验 | 成本 | 自动化 | 成立判据 | 不成立判据 | 结论 |
|
|
329
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
330
|
+
| `T0.1` | `观测` | 两边各自直连复核 | 3 min | 自动 | 差异稳定复现 | 单次抖动 | **成立** |
|
|
331
|
+
| `T0.2` | `基期` | **查前 30 天的每日差值** | 3 min | 自动 | 差值有明确的起始日 | 差值长期恒定 → 是口径定义差异,不是事故 | **成立且高价值**:差值从 09-08 才开始,之前为 0 |
|
|
332
|
+
| `T0.3` | `时点` | 两边是否都已跑完 | 1 min | 自动 | 都已跑完 | 一边没跑完 | **成立** |
|
|
333
|
+
|
|
334
|
+
> `T0.2` 是这条案例里最省时间的一步。**「差值从哪天开始」比「差值是多少」信息量大得多** ——
|
|
335
|
+
> 它直接给出一个可以拿去比对「那天改了什么」的日期。
|
|
336
|
+
|
|
337
|
+
**③ 假设原因**
|
|
338
|
+
|
|
339
|
+
| 编号 | 假设 | 失败原因 | 结论 |
|
|
340
|
+
| --- | --- | --- | --- |
|
|
341
|
+
| `H4` | 上游少同步了一类事件 | 上游未产出 | **确认** |
|
|
342
|
+
| `H5` | 数仓侧重复计数 | 数据处理 | 被 `T5.1` 否定(主键唯一) |
|
|
343
|
+
| `H6` | 两边口径对「取消单」的定义不同 | 口径变更 | 被 `T6.1` 否定(取消单口径一致) |
|
|
344
|
+
|
|
345
|
+
**④ 检查点**
|
|
346
|
+
|
|
347
|
+
| 编号 | 检查 | 资产 | 成本 | 自动化 | 真 / 假判据 | 结论 |
|
|
348
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
349
|
+
| `T4.1` | 按订单状态拆解差异分布 | `dwd_ord_di`、源订单表 | 3 min | 自动 | 真:差异集中在某一类状态 | **命中**:差异 100% 落在「已取消」订单 |
|
|
350
|
+
| `T4.2` | 统计每日取消单量占比趋势 | 源订单表 | 2 min | 自动 | 真:占比升幅与差异率吻合 | **命中**:0.3% → 2.1%,与起始日 09-08 吻合 |
|
|
351
|
+
| `T5.1` | 主键唯一性检查 | `dwd_ord_di` | 1 min | 自动 | 真:有重复 | 无重复 → H5 否定 |
|
|
352
|
+
| `T6.1` | 对比两边的取消单口径定义 | 口径注册表 | 2 min | 人工 | 真:定义不一致 | 定义一致 → H6 否定 |
|
|
353
|
+
|
|
354
|
+
**⑤ 证据**
|
|
355
|
+
|
|
356
|
+
| 编号 | 来源 | 看到什么 | 为什么算数 |
|
|
357
|
+
| --- | --- | --- | --- |
|
|
358
|
+
| `E3` | `T4.1` + `T4.2` | 差异全落在取消单,且取消单占比的起始日与差异起始日同一天 | 算数:**两个独立维度指向同一天** —— 差异的结构(哪类订单)和时间(从哪天起)互相印证 |
|
|
359
|
+
|
|
360
|
+
**⑥ 根因与修复**:`C1` —— 取消事件不在订阅范围内,业务规则变化让隐藏缺口显形。
|
|
361
|
+
修复:订阅补上取消事件;对账任务从「只对总额」改成「按订单状态分别对账」。
|
|
362
|
+
|
|
363
|
+
**⑦ 写回**
|
|
364
|
+
|
|
365
|
+
- `H4` 命中 +1;新增 `refutes`(`E1` → `H5`)、(`E2` → `H6`)
|
|
366
|
+
- **`T0.2` 提升为跨案例通用的现象验证手段**:任何「与源系统对不上」都先跑「差值从哪天开始」
|
|
367
|
+
- 新增误导边:`H5`(重复计数)先验总是最高,但在这个子类里连续被否定。记一条:**子类不同,先验应该不同**
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
### CASE-009 · 明细报表与经营看板的 GMV 差 3.5 万
|
|
372
|
+
|
|
373
|
+
| 项 | 值 |
|
|
374
|
+
| --- | --- |
|
|
375
|
+
| 子类 | `inconsistency-cross-report` · 跨报表勾稽不平 |
|
|
376
|
+
| 形态 / 时间模式 | `mismatch` · 单日 |
|
|
377
|
+
| 现象 | 同一指标,明细报表 128.4 万、经营看板 131.9 万,差 3.5 万(+2.7%) |
|
|
378
|
+
| 真实路径 | `S → T0.2(基期) → H1 → T1.2 → T1.3 → E3 → C1` |
|
|
379
|
+
| 耗时 | 21 分钟 |
|
|
380
|
+
| 根因 | 口径变更只落在 dws 层(`dws_trade_1d` 加了退款冲正),直读 dwd 的明细报表没同步 |
|
|
381
|
+
|
|
382
|
+
**① 现象**:两个报表都自称口径 v3,但数字差 2.7%。
|
|
383
|
+
|
|
384
|
+
**② 现象验证**
|
|
385
|
+
|
|
386
|
+
| 编号 | 维度 | 怎么验 | 成本 | 自动化 | 成立判据 | 不成立判据 | 结论 |
|
|
387
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
388
|
+
| `T0.1` | `观测` | 两边各自直连复核 | 2 min | 自动 | 差异复现 | 抖动 | **成立** |
|
|
389
|
+
| `T0.2` | `基期` | 查差值起始日 | 2 min | 自动 | 有明确起始日 | 长期恒定 | **成立**:09-15 起,之前一致 |
|
|
390
|
+
| `T0.3` | `时点` | 两边刷新状态 | 1 min | 自动 | 都已完成 | 一边没跑完 → 等 | **成立** |
|
|
391
|
+
|
|
392
|
+
**③ 假设原因**
|
|
393
|
+
|
|
394
|
+
| 编号 | 假设 | 失败原因 | 结论 |
|
|
395
|
+
| --- | --- | --- | --- |
|
|
396
|
+
| `H1` | 口径变更只落了一条链路 | 口径变更 | **确认** |
|
|
397
|
+
| `H2` | 刷新时序不同(一边读到了新数) | 消费与展示 | 被 `T0.3` 否定 |
|
|
398
|
+
| `H3` | 数据源不同(一个读 dwd、一个读 dws) | 数据处理 | **支持但只是背景**,不是根因 |
|
|
399
|
+
|
|
400
|
+
**④ 检查点**
|
|
401
|
+
|
|
402
|
+
| 编号 | 检查 | 资产 | 成本 | 自动化 | 真 / 假判据 | 结论 |
|
|
403
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
404
|
+
| `T1.1` | 查两个报表的 SQL 血缘 | 报表配置 | 2 min | 自动 | —— | 明细读 `dwd_ord_di`,看板读 `dws_trade_1d` |
|
|
405
|
+
| `T1.2` | 对比两层的聚合结果 | `dwd_ord_di`、`dws_trade_1d` | 2 min | 自动 | 真:dws 层多出差异额 | **命中**:dws 多 3.5 万 |
|
|
406
|
+
| `T1.3` | 查 `dws_trade_1d` 的最近变更 | `dws_trade_1d` | 3 min | 人工 | 真:有未同步到 dwd 的口径改动 | **命中**:09-15 加了退款冲正 |
|
|
407
|
+
|
|
408
|
+
**⑤ 证据**
|
|
409
|
+
|
|
410
|
+
| 编号 | 来源 | 看到什么 | 为什么算数 |
|
|
411
|
+
| --- | --- | --- | --- |
|
|
412
|
+
| `E3` | `T1.2` + `T1.3` | dws 比 dwd 多 3.5 万,且 09-15 的变更是「加退款冲正」 | 算数:差异额与变更内容能对上。**只说「两条链路读了不同的表」不算数** —— 那是常态,不解释差异 |
|
|
413
|
+
|
|
414
|
+
**⑥ 根因与修复**:`C1` —— 口径变更的实现落在一层,消费方跨层读取。
|
|
415
|
+
修复:把口径计算下沉到共享的指标层,两条链路都读同一处;或给 dwd 层补同一逻辑。
|
|
416
|
+
|
|
417
|
+
**⑦ 写回**
|
|
418
|
+
|
|
419
|
+
- `H1` 命中 +1;新增 `refutes`(`E1` → `H2`)
|
|
420
|
+
- **新增误导边**:`H3`(数据源不同)会被便宜检查(查血缘)证实,但它只是背景条件。这是「便宜检查返回真,但不是答案」的第二类,与 `T1.1` 返回 success 那类要分开记
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
### CASE-010 · 月报 GMV 与日报累加差 51 万
|
|
425
|
+
|
|
426
|
+
| 项 | 值 |
|
|
427
|
+
| --- | --- |
|
|
428
|
+
| 子类 | `inconsistency-spec-change` · 口径变更后不一致 |
|
|
429
|
+
| 形态 / 时间模式 | `mismatch` · `periodic` |
|
|
430
|
+
| 现象 | 月报 3,791 万,日报逐日累加 3,842 万,差 51 万(1.3%) |
|
|
431
|
+
| 真实路径 | `S → T0.2(基期) → H1 → T1.1 → E1 → C1` |
|
|
432
|
+
| 耗时 | **9 分钟**(本批最短) |
|
|
433
|
+
| 根因 | 日报口径已升 v3(含运费),月报仍是 v2(不含运费);月报是另一个团队的独立脚本,没跟着升 |
|
|
434
|
+
|
|
435
|
+
**① 现象**:月报与日报对不上,差 1.3%。上个月两者一致。
|
|
436
|
+
|
|
437
|
+
**② 现象验证**
|
|
438
|
+
|
|
439
|
+
| 编号 | 维度 | 怎么验 | 成本 | 自动化 | 成立判据 | 不成立判据 | 结论 |
|
|
440
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
441
|
+
| `T0.1` | `观测` | 两边复核 | 2 min | 自动 | 复现 | 抖动 | **成立** |
|
|
442
|
+
| `T0.2` | `基期` | 查差值起始 | 1 min | 自动 | 有起始日 | 长期恒定 | **成立**:09-01 起 |
|
|
443
|
+
| `T0.3` | `噪声` | 差的绝对值 ÷ 总量 | 1 min | 自动 | —— | —— | 1.3%,量级上像一个**单项**(不是系统性偏差) |
|
|
444
|
+
|
|
445
|
+
> `T0.3` 的读数直接指向「找那个漏掉的单项」,而不是「找系统性 bug」。这一步 1 分钟,省掉后面半轮。
|
|
446
|
+
|
|
447
|
+
**③ 假设原因**
|
|
448
|
+
|
|
449
|
+
| 编号 | 假设 | 失败原因 | 结论 |
|
|
450
|
+
| --- | --- | --- | --- |
|
|
451
|
+
| `H1` | 两条链路口径版本不一致 | 口径变更 | **确认** |
|
|
452
|
+
| `H2` | 月报有重算 / 补数 | 数据处理 | 未走到 |
|
|
453
|
+
| `H3` | 月末月初时区边界 | 数据处理 | 未走到 |
|
|
454
|
+
|
|
455
|
+
**④ 检查点**
|
|
456
|
+
|
|
457
|
+
| 编号 | 检查 | 资产 | 成本 | 自动化 | 真 / 假判据 | 结论 |
|
|
458
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
459
|
+
| `T1.1` | 查两条链路各自生效的口径版本号 | 口径注册表 | 1 min | 自动 | 真:版本号不同 | **命中**:日报 v3、月报 v2 |
|
|
460
|
+
| `T1.2` | 查 v2 → v3 的差异说明,看差额能否对上 | 口径注册表 | 2 min | 人工 | 真:差异项金额 ≈ 51 万 | **命中**:v3 新增运费,当月运费 50.8 万 |
|
|
461
|
+
| `T1.3` | 用 v3 口径重算月报 | `dwd_ord_di` | 5 min | 自动 | 真:重算结果等于日报累加 | 未走到(`T1.2` 已足够) |
|
|
462
|
+
|
|
463
|
+
**⑤ 证据**
|
|
464
|
+
|
|
465
|
+
| 编号 | 来源 | 看到什么 | 为什么算数 |
|
|
466
|
+
| --- | --- | --- | --- |
|
|
467
|
+
| `E1` | `T1.2` | 差异项金额 50.8 万 vs 实际差 51 万,差 0.2 万(0.4%) | 算数:**能对上量级**。这是本批唯一一条 `T1.1`(1 min)就给足结论的案例 |
|
|
468
|
+
|
|
469
|
+
**⑥ 根因与修复**:`C1` —— 口径升级未覆盖独立维护的月报脚本。
|
|
470
|
+
修复:口径版本登记表增加「依赖该口径的链路清单」,升级时强制遍历。
|
|
471
|
+
|
|
472
|
+
**⑦ 写回**
|
|
473
|
+
|
|
474
|
+
- `H1` 命中 +1
|
|
475
|
+
- **正面对照**:`T1.1` 是 1 分钟、自动、有结论的检查。它和 CASE-001 的 `T7.1`(2 分钟、自动、**没结论**)成本几乎一样,价值完全相反。**两条边一起摆出来,「便宜」不等于「有用」才说得清**
|
|
476
|
+
- 新增检查点 `T1.1` 的判据:读的是**生效版本号**,不是文档写的版本号
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
### CASE-011 · 10-01 DAU 掉 18%,10-02 又正常
|
|
481
|
+
|
|
482
|
+
| 项 | 值 |
|
|
483
|
+
| --- | --- |
|
|
484
|
+
| 子类 | `inconsistency-tz-boundary` · 跨天 / 时区边界 |
|
|
485
|
+
| 形态 / 时间模式 | `mismatch` · `single-day` |
|
|
486
|
+
| 现象 | 10-01 DAU 98 万,09-30 是 120 万(-18%);10-02 回到 122 万 |
|
|
487
|
+
| 真实路径 | `S → T0.4(噪声) → H1 → T1.1✗ → H4 → T4.1 → E3 → C1` |
|
|
488
|
+
| 耗时 | 47 分钟(其中 25 分钟被「上游产出正常」带偏) |
|
|
489
|
+
| 根因 | 上游 09-30 16:00(UTC) 部署「统一用 UTC 存储」,`event_time` 语义从 CST 变 UTC,**字段名和格式都没变**;数仓按 CST 解析,10-01 的前 8 小时事件被算回 09-30 |
|
|
490
|
+
|
|
491
|
+
**① 现象**:10-01 DAU 偏低,前后两天正常。运营侧说 10-01 是假期首日,活跃本该更高。
|
|
492
|
+
|
|
493
|
+
**② 现象验证**
|
|
494
|
+
|
|
495
|
+
| 编号 | 维度 | 怎么验 | 成本 | 自动化 | 成立判据 | 不成立判据 | 结论 |
|
|
496
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
497
|
+
| `T0.1` | `基期` | 查去年 10-01 | 2 min | 自动 | 去年更高 | 去年也低 → 假期效应 | **成立**:去年 128 万,今年反而更低 |
|
|
498
|
+
| `T0.2` | `观测` | 直连复核 | 2 min | 自动 | 一致 | 不一致 | **成立** |
|
|
499
|
+
| `T0.3` | `业务` | 问运营 | 3 min | 人工 | 无变更 | 有变更 | **成立** |
|
|
500
|
+
| `T0.4` | `噪声` | 看波动形态 | 1 min | 自动 | 单日异常、前后正常 | 连续多日 → 换子类 | **成立**:形态是 `single-day` |
|
|
501
|
+
|
|
502
|
+
> `T0.4` 是本案例的**分流阀**:单日异常直接把候选压到「边界类」假设上,先验立刻重排。
|
|
503
|
+
|
|
504
|
+
**③ 假设原因**
|
|
505
|
+
|
|
506
|
+
| 编号 | 假设 | 失败原因 | 结论 |
|
|
507
|
+
| --- | --- | --- | --- |
|
|
508
|
+
| `H1` | 上游未产出,10-01 缺了一段数据 | 上游未产出 | 被 `T1.1` 否定(上游行数正常) |
|
|
509
|
+
| `H4` | 时间窗口 / 时区边界错位 | 数据处理 | **确认** |
|
|
510
|
+
| `H5` | 前后分区串数据 | 数据处理 | 被 `T4.2` 否定(分区边界干净) |
|
|
511
|
+
|
|
512
|
+
**④ 检查点**
|
|
513
|
+
|
|
514
|
+
| 编号 | 检查 | 资产 | 成本 | 自动化 | 真 / 假判据 | 结论 |
|
|
515
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
516
|
+
| `T1.1` | 查上游当日总行数与实例状态 | `ods_user_event_di` | 2 min | 自动 | 真:行数偏低或 failed | 行数正常 → **H1 否定,但这一步给不出正确方向** |
|
|
517
|
+
| `T4.1` | 查 10-01 与 09-30 的**小时级**分布 | `dwd_user_active_1d` | 2 min | 自动 | 真:某几小时异常缺口 / 尖峰 | **命中**:10-01 的 00–08 时几乎是 0,09-30 的 16–24 时异常高 |
|
|
518
|
+
| `T4.2` | 查小时级缺口是否跨分区边界 | `ods_user_event_di` | 3 min | 人工 | 真:缺口止于分区边界 | 缺口止于**小时**而非分区边界 → 否定「串分区」 |
|
|
519
|
+
| `T4.3` | 查上游时间字段的语义变更记录 | `ods_user_event_di` | 3 min | 人工 | 真:时区语义近期变更 | **命中**:09-30 16:00(UTC) 起 `event_time` 改存 UTC |
|
|
520
|
+
|
|
521
|
+
**⑤ 证据**
|
|
522
|
+
|
|
523
|
+
| 编号 | 来源 | 看到什么 | 为什么算数 |
|
|
524
|
+
| --- | --- | --- | --- |
|
|
525
|
+
| `E3` | `T4.1` + `T4.3` | 缺口恒为 8 小时、方向一致(前一日后移),且变更时刻与缺口起始时刻对得上 | 算数:**缺口宽度等于时区偏移量**是时区问题的确定性特征。只看「某小时没数据」不算数,那也可以是上游中断 |
|
|
526
|
+
|
|
527
|
+
**⑥ 根因与修复**:`C1` —— 上游时间戳时区语义静默变更。
|
|
528
|
+
修复:数仓解析改为读上游显式声明的时区字段;推动上游把「时间语义」纳入接口契约,变更要走通知。
|
|
529
|
+
|
|
530
|
+
**⑦ 写回**
|
|
531
|
+
|
|
532
|
+
- `H4` 命中 +1;新增 `refutes`(`E1` → `H1`)
|
|
533
|
+
- **新增误导边**:`T1.1` 返回「上游正常」会让人排除上游方向,但**问题恰恰在上游**(语义变了,数据没少)。这是第三条「便宜检查没有结论」的边,而且这次它把人推向了完全错误的方向
|
|
534
|
+
- 新增一条判据进手册:**时区 / 边界类问题的确定性特征是「缺口宽度 = 偏移量」**
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
### CASE-012 · 「分省份 GMV」里广东整行消失
|
|
539
|
+
|
|
540
|
+
| 项 | 值 |
|
|
541
|
+
| --- | --- |
|
|
542
|
+
| 子类 | `granularity-dim-missing` · 维度值缺失 |
|
|
543
|
+
| 形态 / 时间模式 | `granularity` · 单日 |
|
|
544
|
+
| 现象 | 分省份 GMV 报表里没有「广东」这一行(不是 0,是整行不见),其余 33 个省份都在 |
|
|
545
|
+
| 真实路径 | `S → T0.1(观测) → H1 → T1.2 → E2 → C1` |
|
|
546
|
+
| 耗时 | 14 分钟 |
|
|
547
|
+
| 根因 | 两张维表的省份取值域不一致:`dim_region_df.province_name` 是「广东省」,`dim_user_df.province` 是「广东」;join 不上 → `province` 为 null → 被 `where province is not null` 过滤 → 整行消失 |
|
|
548
|
+
|
|
549
|
+
**① 现象**:广东省整行消失。总量正常(广东的量被算进了「未知」之外的某处或被丢弃 —— 这条要先确认)。
|
|
550
|
+
|
|
551
|
+
**② 现象验证**
|
|
552
|
+
|
|
553
|
+
| 编号 | 维度 | 怎么验 | 成本 | 自动化 | 成立判据 | 不成立判据 | 结论 |
|
|
554
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
555
|
+
| `T0.1` | `观测` | 直连 `group by province` 查一遍 | 2 min | 自动 | 确实没有该行 | 有该行 → 是前端渲染问题 | **成立** |
|
|
556
|
+
| `T0.2` | `时点` | 比对 SLA | 1 min | 自动 | 已过 | 未到 | **成立** |
|
|
557
|
+
| `T0.3` | `噪声` | 看总量 | 1 min | 自动 | 总量正常 → 是**内部丢失**不是外部缺口 | 总量也少 → 换子类 | **成立**:总量正常 |
|
|
558
|
+
|
|
559
|
+
> `T0.3` 一句话把范围劈成两半:总量正常 ⇒ 不可能是「数据没进来」,只可能是「进来后没被切对」。
|
|
560
|
+
|
|
561
|
+
**③ 假设原因**
|
|
562
|
+
|
|
563
|
+
| 编号 | 假设 | 失败原因 | 结论 |
|
|
564
|
+
| --- | --- | --- | --- |
|
|
565
|
+
| `H1` | 维表 join 后该维度为 null,被下游过滤 | 数据处理 | **确认** |
|
|
566
|
+
| `H2` | 源数据里就没有广东的记录 | 上游未产出 | 被 `T1.1` 否定(订单表里有 8.2 万单) |
|
|
567
|
+
| `H3` | 过滤条件显式排除了广东 | 消费与展示 | 被 `T1.3` 否定(过滤条件里没有省份枚举) |
|
|
568
|
+
|
|
569
|
+
**④ 检查点**
|
|
570
|
+
|
|
571
|
+
| 编号 | 检查 | 资产 | 成本 | 自动化 | 真 / 假判据 | 结论 |
|
|
572
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
573
|
+
| `T1.1` | 用订单表的收货地址直接统计广东单量 | `dwd_ord_di` | 2 min | 自动 | 真:单量正常 | **8.2 万单** → H2 否定 |
|
|
574
|
+
| `T1.2` | 查这些订单在宽表里的 `province` 取值 | `dim_user_df`、`dwd_ord_di` | 2 min | 自动 | 真:为 null 或 `unknown` | **命中**:全部为 null |
|
|
575
|
+
| `T1.3` | 查报表的过滤条件定义 | 报表配置 | 2 min | 人工 | 真:有省份枚举白名单 | 只有 `is not null`,无枚举 → H3 否定 |
|
|
576
|
+
| `T1.4` | 对比两张维表的省份取值域 | `dim_region_df`、`dim_user_df` | 2 min | 自动 | 真:同一省份取值不同 | **命中**:「广东省」vs「广东」 |
|
|
577
|
+
|
|
578
|
+
**⑤ 证据**
|
|
579
|
+
|
|
580
|
+
| 编号 | 来源 | 看到什么 | 为什么算数 |
|
|
581
|
+
| --- | --- | --- | --- |
|
|
582
|
+
| `E2` | `T1.2` + `T1.4` | 广东订单的 province 全 null,且两个维表对广东的写法不同 | 算数:`T1.2` 定位「哪一步丢了」,`T1.4` 定位「为什么丢」。两条缺一不可 —— 只知道 null 不知道原因,改不动 |
|
|
583
|
+
|
|
584
|
+
**⑥ 根因与修复**:`C1` —— 主数据取值域不一致导致 join 失败。
|
|
585
|
+
修复:省份统一用行政区划码 join,不用名称;补一条维表取值域一致性校验。
|
|
586
|
+
|
|
587
|
+
**⑦ 写回**
|
|
588
|
+
|
|
589
|
+
- `H1` 命中 +1;新增 `refutes`(`E1` → `H2`)、(`E3` → `H3`)
|
|
590
|
+
- **正面对照**:`T1.1`(查单量)2 分钟、自动、**直接否定了一条看起来很合理的假设**。与 `T7.1` 对照,说明「便宜检查有没有结论」取决于**判据写得对不对**,不取决于成本
|
|
591
|
+
- 新增检查点 `T1.4`:判据是「同一实体在两表中的取值集合是否相等」
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
### CASE-013 · 三方店铺的渠道显示为「未知」
|
|
596
|
+
|
|
597
|
+
| 项 | 值 |
|
|
598
|
+
| --- | --- |
|
|
599
|
+
| 子类 | `granularity-dim-empty` · 部分维度为空 |
|
|
600
|
+
| 形态 / 时间模式 | `granularity` · 单日 |
|
|
601
|
+
| 现象 | 分渠道 GMV 里三方店铺的渠道显示「未知」,`unknown` 占比 3.1%(平时 0.2%);自营正常 |
|
|
602
|
+
| 真实路径 | `S → T0.3(噪声) → H1 → T1.1 → T1.2✗ → T2.2 → E3 → C1` |
|
|
603
|
+
| 耗时 | 41 分钟(其中 18 分钟被「维表任务 success」带偏) |
|
|
604
|
+
| 根因 | 渠道主数据维护系统 09-20 迁移到新平台,旧接口返回**迁移前的静态快照**;维表任务照常 success,但拉的是旧数据,09-22 后的新渠道永远进不来 |
|
|
605
|
+
|
|
606
|
+
**① 现象**:`unknown` 占比从 0.2% 涨到 3.1%,缺口集中在三方店铺。
|
|
607
|
+
|
|
608
|
+
**② 现象验证**
|
|
609
|
+
|
|
610
|
+
| 编号 | 维度 | 怎么验 | 成本 | 自动化 | 成立判据 | 不成立判据 | 结论 |
|
|
611
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
612
|
+
| `T0.1` | `观测` | 直连复核 | 2 min | 自动 | 复现 | 抖动 | **成立** |
|
|
613
|
+
| `T0.2` | `基期` | 查起始日 | 2 min | 自动 | 有起始日 | 长期如此 | **成立**:09-22 起 |
|
|
614
|
+
| `T0.3` | `噪声` | 3.1% 是否值得归因 | 1 min | 自动 | 超出历史区间(历史 ≤0.5%) | 在区间内 | **成立**(历史最高 0.5%) |
|
|
615
|
+
| `T0.4` | `业务` | 问运营:有没有新开渠道 | 3 min | 人工 | 有 | 无 | **成立**:09-22 起新开了一批三方渠道 |
|
|
616
|
+
|
|
617
|
+
> `T0.4` 给了关键输入:**起始日与新渠道上线日同一天**。这几乎锁定「新渠道没进维表」。
|
|
618
|
+
|
|
619
|
+
**③ 假设原因**
|
|
620
|
+
|
|
621
|
+
| 编号 | 假设 | 失败原因 | 结论 |
|
|
622
|
+
| --- | --- | --- | --- |
|
|
623
|
+
| `H1` | 新渠道未补录进维表 | 上游未产出 | **确认**(但机制不是「忘了补」) |
|
|
624
|
+
| `H2` | 维表任务失败,没有更新 | 数据处理 | 被 `T2.1` 否定(实例 success) |
|
|
625
|
+
| `H3` | join 键类型不一致 | 数据处理 | 被 `T1.3` 否定(类型一致) |
|
|
626
|
+
|
|
627
|
+
**④ 检查点**
|
|
628
|
+
|
|
629
|
+
| 编号 | 检查 | 资产 | 成本 | 自动化 | 真 / 假判据 | 结论 |
|
|
630
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
631
|
+
| `T1.1` | 查 unknown 订单的渠道编码 | `dwd_ord_di` | 2 min | 自动 | —— | 得到编码形如 `C_9xxx` |
|
|
632
|
+
| `T1.2` | 查这些编码在维表里是否存在 | `dim_channel_df` | 1 min | 自动 | 真:不存在 | **命中**:不存在 |
|
|
633
|
+
| `T2.1` | 查维表更新任务实例状态 | 调度 | 1 min | 自动 | 真:failed | **success** → H2 被否定,但方向被带偏 |
|
|
634
|
+
| `T2.2` | **查维表数据的最新业务时间戳**(不是任务时间) | `dim_channel_df` | 2 min | 自动 | 真:最新记录时间早于预期 | **命中**:最新记录停在 09-18 |
|
|
635
|
+
| `T2.3` | 查维表上游源的接入方式变更 | 渠道主数据平台 | 3 min | 人工 | 真:接入方式近期有变更 | **命中**:09-20 迁移到新平台,旧接口变静态快照 |
|
|
636
|
+
|
|
637
|
+
**⑤ 证据**
|
|
638
|
+
|
|
639
|
+
| 编号 | 来源 | 看到什么 | 为什么算数 |
|
|
640
|
+
| --- | --- | --- | --- |
|
|
641
|
+
| `E3` | `T2.2` + `T2.3` | 任务每天 success,但表里最新记录停在 09-18;上游接入方式在 09-20 变更 | 算数:**「任务成功」和「数据新鲜」是两件事**,必须分别读 |
|
|
642
|
+
|
|
643
|
+
**⑥ 根因与修复**:`C1` —— 上游系统迁移后旧接口退化为静态快照,任务「成功」地拉旧数据。
|
|
644
|
+
修复:维表任务加**数据新鲜度断言**(最新记录时间必须 > 昨日);接入切到新平台 API。
|
|
645
|
+
|
|
646
|
+
**⑦ 写回**
|
|
647
|
+
|
|
648
|
+
- `H1` 命中 +1;新增 `refutes`(`E1` → `H2`)
|
|
649
|
+
- **新增误导边**:`T2.1`(查任务状态)1 分钟、自动、返回 success —— 与 CASE-004 的 `T1.1` 是同一类陷阱。图上现在有三条同类边,足以支撑一条通用规则进手册:**「任务状态」类检查对「成功但没产出 / 成功但拉旧数据」没有区分力**
|
|
650
|
+
- 新增检查点 `T2.2`:判据是「表内最新业务时间戳 vs 期望日期」,**不是**任务运行时间
|
|
651
|
+
|
|
652
|
+
---
|
|
653
|
+
|
|
654
|
+
### CASE-014 · 订单数突增 45.5%,金额只涨 3%
|
|
655
|
+
|
|
656
|
+
| 项 | 值 |
|
|
657
|
+
| --- | --- |
|
|
658
|
+
| 子类 | `granularity-dup-count` · 重复计数 |
|
|
659
|
+
| 形态 / 时间模式 | `granularity` · `rise-sharp` |
|
|
660
|
+
| 现象 | 订单数 70,110(前一日 48,200,+45.5%),支付金额只涨 3% |
|
|
661
|
+
| 真实路径 | `S → T0.2(观测) → H4 → T4.1✓ → T4.2 → E2 → C1` |
|
|
662
|
+
| 耗时 | 31 分钟 |
|
|
663
|
+
| 根因 | 上游 `ods_order_sync` 重跑用 `insert into` 而非 `insert overwrite`,09-21 02:00–03:00 的数据被追加了一份;数仓的「主键唯一性检查」查的是 `order_id`,而表的主键其实是 `order_id + sku_id` |
|
|
664
|
+
|
|
665
|
+
**① 现象**:订单数 +45.5%,金额只 +3%。**数量和金额背离**。
|
|
666
|
+
|
|
667
|
+
**② 现象验证**
|
|
668
|
+
|
|
669
|
+
| 编号 | 维度 | 怎么验 | 成本 | 自动化 | 成立判据 | 不成立判据 | 结论 |
|
|
670
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
671
|
+
| `T0.1` | `业务` | 问运营:有没有大促 | 3 min | 人工 | 无 | 有 → 可能是真实增长 | **成立** |
|
|
672
|
+
| `T0.2` | `观测` | **交叉验证:订单数 vs 金额** | 2 min | 自动 | 两者背离 → 重复计数特征 | 两者同涨 → 真实增长 | **成立且高价值**:+45.5% vs +3%,背离明显 |
|
|
673
|
+
| `T0.3` | `噪声` | 与历史 30 天区间比 | 1 min | 自动 | 超出区间 | 在区间内 | **成立** |
|
|
674
|
+
|
|
675
|
+
> `T0.2` 是这条案例最省时间的一步。**「计数类涨、金额类不涨」是重复计数的标准指纹**,
|
|
676
|
+
> 2 分钟就能把候选范围从「全部假设」压到「重复 / 回刷」一类。
|
|
677
|
+
|
|
678
|
+
**③ 假设原因**
|
|
679
|
+
|
|
680
|
+
| 编号 | 假设 | 失败原因 | 结论 |
|
|
681
|
+
| --- | --- | --- | --- |
|
|
682
|
+
| `H4` | 重复 / 回刷 | 数据处理 | **确认** |
|
|
683
|
+
| `H5` | 上游确实有更多订单 | 上游未产出 | 被 `T0.2` 的金额背离否定 |
|
|
684
|
+
| `H6` | 时间窗口重叠,跨天订单算了两天 | 数据处理 | 被 `T4.2` 否定(重复行同一天同一小时) |
|
|
685
|
+
|
|
686
|
+
**④ 检查点**
|
|
687
|
+
|
|
688
|
+
| 编号 | 检查 | 资产 | 成本 | 自动化 | 真 / 假判据 | 结论 |
|
|
689
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
690
|
+
| `T4.1` | 主键唯一性:`order_id` | `dwd_ord_di` | 1 min | 自动 | 真:有重复 | **通过**(无重复)→ 看起来否定了 H4 |
|
|
691
|
+
| `T4.2` | 主键唯一性:`order_id + sku_id` | `dwd_ord_di` | 2 min | 自动 | 真:有重复 | **命中**:3.1 万条重复 |
|
|
692
|
+
| `T4.3` | 查重复行的 `update_time` 分布 | `dwd_ord_di` | 2 min | 自动 | 真:集中在某一小时 | **命中**:09-21 02:00–03:00 |
|
|
693
|
+
| `T4.4` | 查上游该时段的写入方式 | `ods_order_sync` | 3 min | 人工 | 真:用了 `insert into` | **命中** |
|
|
694
|
+
|
|
695
|
+
**⑤ 证据**
|
|
696
|
+
|
|
697
|
+
| 编号 | 来源 | 看到什么 | 为什么算数 |
|
|
698
|
+
| --- | --- | --- | --- |
|
|
699
|
+
| `E2` | `T4.2` + `T4.3` + `T4.4` | 组合键有 3.1 万重复,集中在重跑窗口,上游确认用 `insert into` | 算数:**三证齐全**(重复事实 + 时间吻合 + 上游实现确认) |
|
|
700
|
+
|
|
701
|
+
**⑥ 根因与修复**:`C1` —— 上游重跑写入方式造成重复追加。
|
|
702
|
+
修复:重跑改为 `insert overwrite` 或按分区幂等写;**同时修数仓的检查点** —— `T4.1` 的键写错了。
|
|
703
|
+
|
|
704
|
+
**⑦ 写回**(这条案例的写回最重)
|
|
705
|
+
|
|
706
|
+
- `H4` 命中 +1
|
|
707
|
+
- **修正已有检查点 `T4.1`**:这是最重要的产出。CASE-002 和 CASE-003 里 `T4.1` 连续两次正确地否定了 `H4`,
|
|
708
|
+
在本案里它**又一次返回「通过」**,而 `H4` 恰恰是真的。原因不是它没结论,是**它的键写错了**。
|
|
709
|
+
图上要给 `T4.1` 补一条 `refutes` 的 `because` 注释:「键限于 `order_id`;组合键为 `order_id + sku_id` 时不适用」
|
|
710
|
+
- 新增检查点 `T4.2`(组合键唯一性),并把 `T4.1` 的 `verdict_false` 从「无重复 → H4 不成立」
|
|
711
|
+
改成「无重复 → **在本粒度下** H4 不成立」,防止跨粒度误用
|
|
712
|
+
- **对指标的意义**:0021 §11 已经诚实记过「同一个检查连续两次否定同一个假设,但公式几乎不敏感」。
|
|
713
|
+
本案给出了那条缺口的**真实样本**:一个 `verdict` 写错的检查点,会在多个案例里持续产出错误的否定边
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
717
|
+
### CASE-015 · 家电 GMV 涨 1789%,数码跌 94%
|
|
718
|
+
|
|
719
|
+
| 项 | 值 |
|
|
720
|
+
| --- | --- |
|
|
721
|
+
| 子类 | `granularity-mapping-shift` · 映射错位 |
|
|
722
|
+
| 形态 / 时间模式 | `granularity` · 单日 |
|
|
723
|
+
| 现象 | 家电 18 万 → 340 万(+1789%),数码 352 万 → 21 万(-94%),**总 GMV 正常** |
|
|
724
|
+
| 真实路径 | `S → T0.1(观测) → H4 → T4.1 → T4.3 → E3 → C1` |
|
|
725
|
+
| 耗时 | 24 分钟 |
|
|
726
|
+
| 根因 | 品类维表重建编码区间时留下重叠:家电和数码**都有 `2000-2999` 区间**;区间 join 产生多对多,取值取决于物理顺序,数码的 SKU 被映射成了家电 |
|
|
727
|
+
|
|
728
|
+
**① 现象**:两个品类的量级几乎互换,总 GMV 不变。
|
|
729
|
+
|
|
730
|
+
**② 现象验证**
|
|
731
|
+
|
|
732
|
+
| 编号 | 维度 | 怎么验 | 成本 | 自动化 | 成立判据 | 不成立判据 | 结论 |
|
|
733
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
734
|
+
| `T0.1` | `观测` | 直连复核 + **看总量** | 2 min | 自动 | 总量正常 → 是内部搬移 | 总量也变 → 换子类 | **成立**:总量正常 |
|
|
735
|
+
| `T0.2` | `业务` | 问运营:有没有调品类归属 | 3 min | 人工 | 无 | 有 → 可能是有意调整 | **成立** |
|
|
736
|
+
| `T0.3` | `噪声` | 看是否为「此消彼长」 | 1 min | 自动 | 一涨一跌、幅度对应 | 同涨同跌 | **成立**:+322 万 / -331 万,幅度同量级 |
|
|
737
|
+
|
|
738
|
+
> `T0.3` 的读数比 `T0.1` 更进一步:**总量正常 + 两个类目此消彼长** ⇒ 几乎确定是映射类问题。
|
|
739
|
+
> 这一步把「上游改了数据」这类假设整体剪掉。
|
|
740
|
+
|
|
741
|
+
**③ 假设原因**
|
|
742
|
+
|
|
743
|
+
| 编号 | 假设 | 失败原因 | 结论 |
|
|
744
|
+
| --- | --- | --- | --- |
|
|
745
|
+
| `H4` | 品类映射错位 | 数据处理 | **确认** |
|
|
746
|
+
| `H5` | 上游改了品类编码 | 数据处理 | **证实但不是根因** —— 编码调整是背景,重叠才是原因 |
|
|
747
|
+
| `H6` | join 产生多对多 | 数据处理 | **确认**(是 `H4` 的实现机制) |
|
|
748
|
+
|
|
749
|
+
**④ 检查点**
|
|
750
|
+
|
|
751
|
+
| 编号 | 检查 | 资产 | 成本 | 自动化 | 真 / 假判据 | 结论 |
|
|
752
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
753
|
+
| `T4.1` | 抽样查两个品类里的 SKU 是否对得上 | `dim_category_df`、`dwd_ord_di` | 3 min | 自动 | 真:品类里出现别的品类的 SKU | **命中**:家电里有手机、相机 |
|
|
754
|
+
| `T4.2` | 查品类维表最近变更 | `dim_category_df` | 2 min | 自动 | 真:编码区间近期调整 | **命中**:09-23 调整过区间 |
|
|
755
|
+
| `T4.3` | 查维表里编码区间是否存在重叠 | `dim_category_df` | 2 min | 自动 | 真:同一编码命中多行 | **命中**:`2000-2999` 命中两行 |
|
|
756
|
+
| `T4.4` | 统计 join 后一个 SKU 对应的品类数 | `dwd_ord_di` | 2 min | 自动 | 真:> 1 | **命中**:34% 的 SKU 对应 2 个品类 |
|
|
757
|
+
|
|
758
|
+
**⑤ 证据**
|
|
759
|
+
|
|
760
|
+
| 编号 | 来源 | 看到什么 | 为什么算数 |
|
|
761
|
+
| --- | --- | --- | --- |
|
|
762
|
+
| `E3` | `T4.3` + `T4.4` | 区间重叠,且实测 34% 的 SKU 被映射到 2 个品类 | 算数:**重叠是必要条件,实测多对多是充分证据**。只有 `T4.2`(编码变过)不算数 |
|
|
763
|
+
|
|
764
|
+
**⑥ 根因与修复**:`C1` —— 区间 join 的区间重叠导致多对多。
|
|
765
|
+
修复:编码区间改为不重叠的闭开区间并加唯一性约束;join 前加「一个 key 只命中一行」的断言。
|
|
766
|
+
|
|
767
|
+
**⑦ 写回**
|
|
768
|
+
|
|
769
|
+
- `H4` 命中 +1
|
|
770
|
+
- **新增误导边**:`T4.2`(查编码是否变更)2 分钟、自动、**返回真** —— 而且它是真的。
|
|
771
|
+
停下来就会得出「编码变更导致映射错位」的结论,方向对、机制错,改不动问题。
|
|
772
|
+
这是「便宜检查返回真但不是答案」的典型,与 CASE-009 的 `H3` 同类
|
|
773
|
+
- 新增检查点 `T4.3`:判据是「同一编码值命中维表行数是否 > 1」,进手册的「区间 join 三查」清单
|
|
774
|
+
|
|
775
|
+
---
|
|
776
|
+
|
|
777
|
+
## 附录 A:现象验证通用清单
|
|
778
|
+
|
|
779
|
+
落成卡片时,`T0.x` 的 `assets[]` 与判据按下表填。**不是每条都要跑**,按子类挑。
|
|
780
|
+
|
|
781
|
+
| 代号 | 检查点 | 资产 | 成本 | 自动化 | 真判据 | 假判据 |
|
|
782
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
783
|
+
| `观测` | 换入口 / 直连明细重查 | 报表配置、明细表 | 1–3 min | 自动 | 数字不一致 | 数字一致 → 现象成立 |
|
|
784
|
+
| `基期` | 查差值起始日 + 口径版本 + 同类日 | 口径注册表、明细表 | 1–3 min | 自动 | 对比不公平(口径版本不同 / 基期是大促 / 天数不同) | 对比公平 → 现象成立 |
|
|
785
|
+
| `时点` | 观测时点 vs 任务 SLA | 调度 | 1 min | 自动 | 未到 SLA | 已过 SLA → 现象成立 |
|
|
786
|
+
| `噪声` | 与历史 30 / 90 天波动区间比 | 明细表 | 1–2 min | 自动 | 在区间内 | 超出区间 → 现象成立 |
|
|
787
|
+
| `业务` | 问活动 / 投放 / 规则变更 | —— | 3–5 min | 人工 | 业务侧有解释 | 无解释 → 现象成立 |
|
|
788
|
+
|
|
789
|
+
**通用手段:`基期` 里的「查差值起始日」。** CASE-008 和 CASE-010 都靠它把范围压到一天之内。
|
|
790
|
+
它比「差值是多少」信息量大 —— 它直接给出一个可以拿去比对变更记录的日期。
|
|
791
|
+
|
|
792
|
+
---
|
|
793
|
+
|
|
794
|
+
## 附录 B:覆盖率矩阵
|
|
795
|
+
|
|
796
|
+
**根因切面的标签与编码。** 写卡片时 `failure_reason` 字段填**编码**(取 `types.ts:43` 的 `FailureReason`),
|
|
797
|
+
本文正文里写的是标签,两者对照如下:
|
|
798
|
+
|
|
799
|
+
| 标签 | 编码 | 本批条数 |
|
|
800
|
+
| --- | --- | --- |
|
|
801
|
+
| 上游未产出 | `upstream-missing` | 2 |
|
|
802
|
+
| 口径变更 | `spec-change` | 3 |
|
|
803
|
+
| 数据处理 | `data-processing` | 7 |
|
|
804
|
+
| 消费与展示 | `consumption` | 0 |
|
|
805
|
+
| 权限与过滤 | `permission` | 0 |
|
|
806
|
+
|
|
807
|
+
> 标签以 `seed.ts:78-82` 的节点标题为准。PRD 散文里写的「口径与版本变更」是**叙述**,
|
|
808
|
+
> 图上 `F2` 节点的正式标题是 **`口径变更`**(假设节点 `H2` 的标题才是「口径 / 版本变更」)。
|
|
809
|
+
|
|
810
|
+
矩阵:
|
|
811
|
+
|
|
812
|
+
| 大类 | 子类 | 案例 | 根因切面 |
|
|
813
|
+
| --- | --- | --- | --- |
|
|
814
|
+
| 缺失 | `missing-zero` | CASE-001(已有) | 上游未产出 |
|
|
815
|
+
| 缺失 | `missing-no-partition` | **CASE-004** | 数据处理 |
|
|
816
|
+
| 缺失 | `missing-job-failed` | **CASE-005** | 数据处理 |
|
|
817
|
+
| 偏差 | `deviation-drop-sharp` | CASE-002(已有) | 数据处理 |
|
|
818
|
+
| 偏差 | `deviation-drop-slow` | **CASE-006** | 数据处理 |
|
|
819
|
+
| 偏差 | `deviation-rise-sharp` | CASE-003(已有) | 数据处理 |
|
|
820
|
+
| 偏差 | `deviation-rise-slow` | **CASE-007** | 口径变更 |
|
|
821
|
+
| 不一致 | `inconsistency-vs-source` | **CASE-008** | 上游未产出 |
|
|
822
|
+
| 不一致 | `inconsistency-cross-report` | **CASE-009** | 口径变更 |
|
|
823
|
+
| 不一致 | `inconsistency-spec-change` | **CASE-010** | 口径变更 |
|
|
824
|
+
| 不一致 | `inconsistency-tz-boundary` | **CASE-011** | 数据处理 |
|
|
825
|
+
| 粒度 | `granularity-dim-missing` | **CASE-012** | 数据处理 |
|
|
826
|
+
| 粒度 | `granularity-dim-empty` | **CASE-013** | 上游未产出 |
|
|
827
|
+
| 粒度 | `granularity-dup-count` | **CASE-014** | 数据处理 |
|
|
828
|
+
| 粒度 | `granularity-mapping-shift` | **CASE-015** | 数据处理 |
|
|
829
|
+
|
|
830
|
+
> **后两类的缺口要说清。** 本批没造 `消费与展示` 和 `权限与过滤` 的案例,理由是这两类在本批的
|
|
831
|
+
> 六个子类里都不是**根因**,只以「被否定的假设」出现(CASE-004 的 `H3`、CASE-009 的 `H2`)。
|
|
832
|
+
> 它们需要自己的症状族来承载(典型是「同一个人换个账号看数不一样」),下一批补。
|
|
833
|
+
|
|
834
|
+
**误导边汇总**(这批案例最贵的产出,共 **10 条**,分四类):
|
|
835
|
+
|
|
836
|
+
| 类别 | 表现 | 条目 |
|
|
837
|
+
| --- | --- | --- |
|
|
838
|
+
| ① 便宜检查**没结论** | 分钟级、自动、返回「正常」,但否定不了任何假设 | CASE-001 `T7.1`、CASE-004 `T1.1`、CASE-011 `T1.1`、CASE-013 `T2.1` |
|
|
839
|
+
| ② 便宜检查返回**真但不是主因** | 检查本身没错,结论也成立,但它只是背景条件 | CASE-006 `T3.1`(方向对、量级差 10 倍)、CASE-009 `H3`、CASE-015 `T4.2` |
|
|
840
|
+
| ③ **一个事实本身**就能误导方向 | 不是检查,是一个看起来能排除方向的观察 | CASE-005(分区存在 ⇒ 误以为不是「没产出」)、CASE-008(`H5` 先验最高,却连续被否定) |
|
|
841
|
+
| ④ **检查本身写错了** | 判据的键 / 阈值写错,会持续产出错误的否定边 | CASE-014 `T4.1`(键用了 `order_id`,真主键是 `order_id + sku_id`) |
|
|
842
|
+
|
|
843
|
+
第 ④ 类是本批**新发现**的类型,seed 里原本没有样本;它也是 0021 §11 记的那个公式缺口的第一个真实案例。
|
|
844
|
+
|
|
845
|
+
---
|
|
846
|
+
|
|
847
|
+
## 附录 C:公开评测集现状复核(2026-10)
|
|
848
|
+
|
|
849
|
+
评测方案 §6 的结论**没有变**:**不存在面向数仓 / 指标口径的、带「故障 → 已知根因」标注的公开评测集。**
|
|
850
|
+
数仓这条线只能自建,这批案例就是自建集的一部分。
|
|
851
|
+
|
|
852
|
+
复核要点(相对 §6 的增量):
|
|
853
|
+
|
|
854
|
+
| 名称 | 变化 | 对排查侧的用处 |
|
|
855
|
+
| --- | --- | --- |
|
|
856
|
+
| [RCAEval](https://github.com/phamquiluan/RCAEval) | 仓库 2026-09-29 仍在更新(233 star) | 仍是最方便的一份。但故障类型是 CPU / MEM / DISK / SOCKET / DELAY / LOSS,**没有口径、血缘、分区语义** |
|
|
857
|
+
| [OpenRCA](https://github.com/microsoft/OpenRCA) | 仓库 2026-07-25 有更新(429 star) | 根因三要素(时间 / 组件 / 原因)形态最接近,`原因` 是预设候选类别,可映射五分类看 top-1 |
|
|
858
|
+
| [TraceBench](https://arxiv.org/abs/2608.27182) | **新增(2026-08)** | 用受控仿真生成根因归因任务,评的是「物理动力系统的参数是否被改过」。**领域不匹配**,但「受控生成 + 记录 agent 轨迹 + 公开 leaderboard」的做法值得抄 —— 这正是我们自建集缺的形态 |
|
|
859
|
+
|
|
860
|
+
**TraceBench 值得抄的一点**:它公开了 **agent 轨迹**,不只公开答案。
|
|
861
|
+
我们的标定集要能算「检查步数 / 成本 / 走没走冤枉路」,就必须存轨迹。
|
|
862
|
+
本批 12 条案例里每条都记了「真实路径 + 耗时 + 哪一步浪费了多少」,
|
|
863
|
+
落成 `agent_diagnosis_case` 的 SourceRaw 时正好是这个形态。
|
|
864
|
+
|
|
865
|
+
---
|
|
866
|
+
|
|
867
|
+
## 附录 D:这批案例要求 schema 改什么
|
|
868
|
+
|
|
869
|
+
**改动很小,只有三处。** 目标是让「现象验证」不需要新节点类型就能表达。
|
|
870
|
+
|
|
871
|
+
### 1. `symptom` 卡片新增 `verified_by[]`
|
|
872
|
+
|
|
873
|
+
和 `hypothesis.verified_by[]` 同一形状(指向 `check_point`)。这样 `T0.x` 有地方挂。
|
|
874
|
+
|
|
875
|
+
### 2. `supports` / `refutes` 边的目标允许是 `symptom`
|
|
876
|
+
|
|
877
|
+
现在这两条边只连「证据 → 假设」。要表达「现象不成立」,需要允许连「证据 → 现象」。
|
|
878
|
+
|
|
879
|
+
**语义要分清**:
|
|
880
|
+
- `refutes` → `hypothesis`:**这条原因被排除了**,继续找下一条
|
|
881
|
+
- `refutes` → `symptom`:**这个现象不成立**,关单,不进归因
|
|
882
|
+
|
|
883
|
+
两者都是 `refutes`,但出口完全不同。界面和统计必须分开算,否则「关单率」会被混进「假设否定率」。
|
|
884
|
+
|
|
885
|
+
### 3. `symptom` 卡片新增 `closure_reason`
|
|
886
|
+
|
|
887
|
+
关单原因,枚举取附录 A 的五个代号:`观测` / `基期` / `时点` / `噪声` / `业务`。
|
|
888
|
+
用途是回答「我们的误报都误在哪一类」—— 没有这个字段,误报治理没有抓手。
|
|
889
|
+
|
|
890
|
+
### 为什么不用新增节点类型
|
|
891
|
+
|
|
892
|
+
`check_point` 和 `evidence` 的形状对「验证现象」和「验证假设」完全一样:
|
|
893
|
+
都是「一次可执行的动作 + 判真判假的阈值」,都是「一次查询的产出 + 算不算数」。
|
|
894
|
+
**加一个 `verification` 节点类型会让同一件事有两个 kind,图上要多一批只差连线的节点。**
|
|
895
|
+
改边比加节点便宜,也不破坏现有 9 类节点 / 10 种边的计数。
|
|
896
|
+
|
|
897
|
+
**代价要说清**:`check_point` 这个 kind 现在同时服务两类判断,
|
|
898
|
+
所以「一个检查点必须能回答谁 / 用什么 / 多久 / 真 / 假」这条硬约束变得**更**重要 ——
|
|
899
|
+
它是区分「验证现象的检查」和「验证假设的检查」的唯一依据。
|