Files
opencode-build/skills/logic-planner/SKILL.md
T
2026-07-01 17:46:08 +08:00

150 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: logic-planner
description: 当需求和元数据都已经确认,需要把业务逻辑拆成 SQL 生成前的确定性执行步骤时使用。它只规划 source、filter、join、dedupe、transform、window、aggregate、output,不写 SQL,不调用 MCP。
---
# Logic Planner(逻辑规划)
## 目标
把已确认的 DRD 和元数据拆成可执行计算步骤,让后续 SQL 只是翻译计划,而不是重新猜业务逻辑。
## 输入
```yaml
requirements_output:
status: READY_FOR_METADATA
validation_result:
status: VALIDATED
field_mapping: {}
joins: []
```
如果元数据没有 `VALIDATED`,停止并回到 `metadata-validator`
## 步骤类型
只允许使用这些 `kind`
- `source`:读取哪张表、哪些字段。
- `filter`:时间、分区、状态、业务条件过滤。
- `join`:多表关联。
- `dedupe`:去重,通常在 join 或 aggregate 前。
- `transform`:派生字段、分类、类型转换、标志位。
- `window`:首笔、末笔、排名、累计、lag/lead。
- `aggregate`:分组和指标计算。
- `output`:最终列、排序、limit 或写入意图。
## 工作顺序
1. 定义输出粒度:一行代表什么。
2. 选事实表:承载核心事件或分母人群的表。
3. 列出 source:每张表只取必要字段。
4. 尽早放 filter:尤其是时间、分区和状态条件。
5. 固定时间窗口边界:下界包含、上界排除。
6. 规划 join:顺序、key、类型、基数假设。
7. 判断是否需要 dedupe/window:首登、首次注册、首笔成功事件等。
8. 规划 transform:标志位、事件顺序、空值处理。
9. 规划 aggregategroup by、指标公式、别名。
10. 规划 output:输出字段、排序、写入模式。
## 时间窗口硬规则
当需求为“近 N 天按 T-1 完整日”时,必须规划为:
```yaml
time_window:
lower_bound_sql: date_sub(current_date(), N)
upper_bound_sql: current_date()
boundary: left_closed_right_open
predicate_sql: event_time >= date_sub(current_date(), N) AND event_time < current_date()
```
禁止规划为 `BETWEEN ... AND date_add(current_date(), -1)`,尤其是 timestamp 字段。
## 转化/漏斗硬规则
转化类需求必须维护事件顺序。对“注册后成功付费”,推荐计划:
1. `first_login`:取窗口内每个用户的首次登录,形成分母。
2. `registered`:取用户注册事件,必要时去重到一个注册时间。
3. `qualified_payment`:在关联注册事件后筛选 `pay_status = 'SUCCESS' AND pay_time >= register_time`
4. `final_agg`:按维度计算分母、分子和转化率。
不要先对全量 `pay_order` 按用户取 `MIN(pay_time)` 再与 `register_time` 比较;这可能漏掉“历史早付费但注册后也付费”的用户。
## 必须显式写出的风险
- 1:N 或 N:N join 是否会放大事实行。
- 去重发生在 join 前还是 join 后。
- 指标是否需要 `count_distinct` 而不是 `count`
- 时间过滤是否能命中分区字段。
- left join 后维度缺失如何处理。
- 转化事件是否严格满足前后顺序。
- 分母为 0 时比率如何处理。
## 输出格式
```yaml
logic_plan:
status: PLANNED | NEED_USER_CONFIRMATION
grain: "结果一行代表什么"
fact_table: "事实表"
dimension_tables: []
time_window:
lower_bound_sql: "date_sub(current_date(), N)"
upper_bound_sql: "current_date()"
predicate_sql: "event_time >= date_sub(current_date(), N) AND event_time < current_date()"
boundary: left_closed_right_open
steps:
- id: S1
kind: source
name: first_login
table: "表名"
columns: ["字段"]
reason: "为什么需要"
- id: S2
kind: filter
target: "表名或中间结果"
predicates: ["业务过滤条件"]
partition_pruning: true
- id: S3
kind: join
left: "左表或CTE"
right: "右表或CTE"
keys: ["左字段 = 右字段"]
type: left
cardinality: "1:1 | 1:N | N:1 | N:N | unknown"
row_growth_risk: low | medium | high
- id: S4
kind: aggregate
group_by: ["维度字段"]
metrics:
- name: "指标名"
agg: count_distinct | sum | avg | min | max | ratio
expression: "业务表达式"
alias: "指标别名"
- id: S5
kind: output
columns: ["输出列"]
order_by: []
write_intent: query_only | insert_into | insert_overwrite
assumptions: []
risks: []
pending_questions: []
```
## 用户可见摘要
除了 YAML,必须输出这张表:
```markdown
## 逻辑计划
| 步骤 | 中间结果 | 类型 | 说明 | 关键条件 |
|---|---|---|---|---|
```
## 停止条件
如果粒度、指标公式、join 基数、去重策略、空值策略、时间归属或写入模式不明确,输出 `NEED_USER_CONFIRMATION`