with one click
executor-workflow
// 对应 /experiment-bridge。用于在用户确认 baseline design 后,完成主回归执行、解释检查与鲁棒性检验,并沉淀可直接用于表图与写作的结果材料。
// 对应 /experiment-bridge。用于在用户确认 baseline design 后,完成主回归执行、解释检查与鲁棒性检验,并沉淀可直接用于表图与写作的结果材料。
| name | executor_workflow |
| description | 对应 /experiment-bridge。用于在用户确认 baseline design 后,完成主回归执行、解释检查与鲁棒性检验,并沉淀可直接用于表图与写作的结果材料。 |
references/role-rules.md。references/role-rules.md 的硬约束优先。planner/stage_7_baseline_design.md 和相邻规划文件读取已确认的 baseline design。stage_*.md 中的中文叙述必须使用中文术语,不得在中文句子里直接夹塞英文单词冒充术语。常见对照:
| 英文 | 中文(正文使用) |
|---|---|
| censoring | 删失(生存分析)/ 截断(panel 边界) |
| confounding / confounder | 混杂 / 混杂因素 |
| heterogeneity / heterogeneous treatment effect | 异质性 / 异质性处理效应 |
| endogeneity | 内生性 |
| selection bias | 选择性偏差 |
| reverse causality | 反向因果 |
| robustness check | 稳健性检验 |
| placebo test | 安慰剂检验 |
| pre-trend | 平行趋势(事前趋势) |
| spillover | 溢出效应 |
| treatment / control group | 处理组 / 对照组 |
| baseline / outcome / covariate | 基准 / 结果变量 / 协变量 |
| cluster / clustering | 聚类(标准误) |
| fixed effect (FE) | 固定效应 |
| identification strategy | 识别策略 |
保留的英文缩写(行业惯例,不译):DID、IV、RDD、PSM、OLS、Logit、Probit、AIC、BIC、p-value、N、R²、F-stat、SE、CI、ATT、ATE、LATE、MVP。
R 代码、函数 / 包名(fixest::feols、lmtest)、表格表头、文件路径保留英文。仅适用于 stage_*.md 的中文叙述段落。
启动时必须从上下文(全局 system prompt 或 planner/stage_7_baseline_design.md 首部的 Research purpose 字段)读取 research_purpose。它决定回归执行口径与结论表述的硬约束,Planner 的方法学选择已按此字段分化,Executor 只执行、不重定性。
| 目的 | 执行要求 | 结论表述 | 不可做 |
|---|---|---|---|
| causal | 严格按 Planner 锁定的识别策略执行(DID / Event Study / IV / RDD / PSM);placebo / pre-trend / falsification 等防线必须跑出来 | 用因果语言:"X 对 Y 的因果效应为…"、"识别得到…"、"处理效应…" | 用"关联/相关/在控制…后仍显著"削弱 Planner 已确立的因果结论 |
| associative | 按 Planner 指定的回归族(OLS / Logit / Probit / Poisson 等)+ FE / 聚类 SE 执行;补共线性(VIF)与反向因果讨论作为边界 | 首次呈现主结果时必须声明"本研究为关联性研究,结果不支持因果解读";措辞统一"相关/关联/在控制…后仍显著" | 用"因果效应/影响/导致/使得…"冒充因果结论 |
禁止私自降级:若 causal 项目的识别策略在数据上失效(平行趋势不成立、IV 弱工具、RDD 带宽无变异、PSM 共同支撑过窄),必须在 executor/specification_log.md 中明确标注失效原因 + 诊断证据,并在 stage_5_assessment.md 中建议用户回到 Planner 调整研究问题或识别策略——不得擅自把研究重新定性为 associative 后继续推进。用户选 causal 就是期望因果结论,偷偷降级等于违约。
每个 Phase 写 stage_*.md 前自检:通读一遍即将落盘的文本,确保所有结论性措辞与 research_purpose 一致;Phase 5 最终摘要是用户唯一看到的结论,"研究类型"一行必须与 research_purpose 完全对齐。
以下是推荐的执行流程,供参考。你可以根据实际情况调整顺序、回溯不适用的步骤。
下游 Reviewer(Mode B)和 Writer 按固定文件名读取你的输出。每个 Phase 结束前必须调用写工具写入对应的 stage_*.md,否则等同于没做。
⚠️ 路径警示(极易写错,违反下游契约)
stage_*.md必须落在executor/根目录,绝对不能写到executor/scripts/或其他子目录。executor/scripts/只允许存放.R脚本。
| Phase | 文件 | 关键内容 |
|---|---|---|
| 1 | executor/stage_1_data_preparation.md | 数据准备说明 + 样本量 + 变量清单 |
| 2 | executor/stage_2_run_baseline.md | 主回归结果文字 + 系数/SE 汇报 + 2-4 句解读 |
| 3 | executor/stage_3_explanation_robustness.md | Priority Check Map + 机制/异质性/稳健性 |
| 4 | executor/stage_4_table_figure_output.md | Table Package + Figure Package 清单 + 文件路径 |
| 5 | executor/stage_5_assessment.md | Appendix & Next-Step Suggestions |
| 持续 | executor/specification_log.md | 所有跑过的规格(即使失败的) |
硬性规则:
executor/outputs/tables/ 和 executor/outputs/figures/,stage_*.md 里只引用路径summary(model) 全文粘到 stage_*.md 里,挑关键行就行以下是 Executor 跨项目共享的"标准配方"——表格 / 图 / 回归的口径在这里统一锁死。脚本里直接套用,规格调整改参数即可,不要替换库或重写 helper。要换写法必须先在 specification_log.md 说明理由。
suppressPackageStartupMessages({
library(data.table) # 数据处理(fread/fwrite)
library(arrow) # parquet I/O
library(fixest) # 回归(高维 FE + C++ 后端)
library(modelsummary) # 表格 / 系数图
library(ggfixest) # event study (ggiplot)
library(ggplot2) # 图
library(scales) # 坐标格式化
})
# 双向 FE + cluster SE — 短面板最常见配方
m <- feols(y ~ x + z1 + z2 | firm + year, data = dt, cluster = ~firm)
# 主表多列对比必须用 named list(modelsummary 直接读列名)
mods <- list(
"(1) Pooled" = feols(y ~ x, data = dt, cluster = ~firm),
"(2) + Controls" = feols(y ~ x + z1 + z2, data = dt, cluster = ~firm),
"(3) + FE" = feols(y ~ x + z1 + z2 | firm+year, data = dt, cluster = ~firm)
)
关键:modelsummary
output = "data.frame"是长格式(含part / term / statistic三列元信息 + 每模型一列)。直接fwrite会让下游 .md 把这三列原样泄漏给读者,且 std.error 行的statistic字段会出现({std.error})字面量;当变量名是中文 /get("...")时还会让 R 表达式裸奔到表里。必须做下面 (a) (b) (c) 三步。
library(data.table)
# (a) 必填 coef_map:把中文 / get("...") 变量名翻译成可读字符串
raw <- modelsummary(
mods,
output = "data.frame",
fmt = 4, # 系数/SE 4 位
estimate = "{estimate}{stars}",
statistic = "({std.error})",
stars = c('*' = .1, '**' = .05, '***' = .01),
coef_map = c(
'get("SA指数_abs")' = "SA指数 (绝对值)", # 公式里写 get("xx") 时 key 也要带 get(...)
"Size" = "Size", "Lev" = "Lev", "ROA" = "ROA"
),
gof_omit = "AIC|BIC|Log.|RMSE|R2 Adj|R2 Within"
) |> as.data.table()
# (b) 长 → 宽美化:std.error 行的 term 置空(避免变量名重复显示)
idx_est <- which(raw$part == "estimates")
if (length(idx_est) > 0) {
raw[idx_est[seq(2L, length(idx_est), by = 2L)], term := ""]
}
# (c) 删除 part / statistic 元信息列后再落盘
raw[, c("part", "statistic") := NULL]
fwrite(raw, "executor/outputs/tables/table_baseline.csv")
# 学术风 minimal:无次网格 / 黑色边框 / 灰度调色 / 顶部图例
theme_coase <- function(base_size = 11) {
theme_minimal(base_size = base_size, base_family = "sans") +
theme(
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank(),
panel.grid.major.y = element_line(linewidth = .25, color = "grey85"),
panel.border = element_rect(color = "black", fill = NA, linewidth = .5),
axis.ticks = element_line(color = "black", linewidth = .35),
axis.text = element_text(color = "black"),
legend.position = "top",
legend.title = element_blank(),
# 左 16pt 给长 y label 留空间(异质性图 / 横向条形图常见多行 label,左 8pt 会被裁断)
plot.margin = margin(8, 12, 8, 16)
)
}
theme_set(theme_coase())
# 调色板:≤4 类用 grayscale;>4 类用 viridis(scale_*_viridis_d(option = "D"))
pal_gray <- c("#000000", "#7F7F7F", "#BFBFBF", "#404040")
# 双格式落盘(PNG 300 DPI + PDF 矢量;含中文必须 cairo_pdf)
# w 默认 8 而不是 7:异质性 / coefplot / 横向条形图的 y label 容易超出 7 inch
save_fig <- function(p, name, w = 8, h = 5) {
ggsave(sprintf("executor/outputs/figures/%s.png", name),
p, dpi = 300, width = w, height = h)
ggsave(sprintf("executor/outputs/figures/%s.pdf", name),
p, device = cairo_pdf, width = w, height = h)
}
# (a) 系数图:多模型主回归对比 — modelplot 已自带 ggplot 接口
p <- modelplot(mods, coef_omit = "Intercept|z1|z2") +
geom_vline(xintercept = 0, linetype = "dashed", color = "grey50") +
scale_color_manual(values = pal_gray) +
labs(x = NULL, y = NULL)
save_fig(p, "fig_coef_baseline")
# (b) Event Study:DID 平行趋势 + 动态效应
es <- feols(y ~ i(rel_year, treated, ref = -1) | firm + year,
data = dt, cluster = ~firm)
p <- ggiplot(es, ref.line = 0,
xlab = "Years relative to event",
ylab = "Coefficient") + theme_coase()
save_fig(p, "fig_event_study")
# (c) 散点 + 拟合线:双变量描述性
p <- ggplot(dt, aes(x = x, y = y)) +
geom_point(alpha = .25, size = .8, color = pal_gray[2]) +
geom_smooth(method = "lm", color = pal_gray[1], se = TRUE, linewidth = .5) +
scale_x_continuous(labels = label_comma()) +
labs(x = "X label", y = "Y label")
save_fig(p, "fig_scatter_xy")
# (d) 异质性柱状图(横向 / 推荐):子样本系数 + 95% CI
# 数据:het_df 含 group (chr/factor) / est / lo / hi 四列;多维度异质性时建议加 dimension 列做 facet
#
# 三个**必须**遵守的渲染规范,否则成图反复出问题:
# 1. geom_vline(xintercept = 0) **必须放在 geom_col + geom_errorbar 之后**,
# 否则零参考线会被柱条遮住,看不出系数符号 / 是否跨零。
# 2. 多维度异质性(SOE / Polluting / Region / Size...)不要混在一张图按 magnitude 全局排序,
# 会让"同一维度的两端"被打散。要么 facet_wrap(~ dimension, scales = "free_y"),
# 要么显式 forcats::fct_inorder 把同维度两端排在一起。
# 3. y label 用 \n 换行写多行(如 "SOE=1\n(State-owned)")时,必须确认 plot.margin 左侧 ≥ 16pt
# 且 save_fig(w = 8.5+),否则会被画布裁断(症状:相邻两行的 label 看起来都一样)。
p <- ggplot(het_df, aes(x = est, y = forcats::fct_reorder(group, est))) +
geom_col(width = 0.6, fill = pal_gray[3], color = "black", linewidth = 0.3) +
geom_errorbar(aes(xmin = lo, xmax = hi), width = 0.2, linewidth = 0.4) +
geom_vline(xintercept = 0, linetype = "dashed", color = "grey40") + # 必须最后画
labs(x = "Coefficient (with 95% CI)", y = NULL)
save_fig(p, "fig_heterog_bar", w = 8.5, h = 5)
# (d') 多维度异质性(SOE / Polluting / Region / Size 各一个 panel) — 维度区分清晰,强烈建议
# het_df 此时还需要 dimension 列(如 "SOE" / "Region" / "Industry" / "Size")
# p <- ggplot(het_df, aes(x = est, y = group)) +
# geom_col(width = 0.6, fill = pal_gray[3], color = "black", linewidth = 0.3) +
# geom_errorbar(aes(xmin = lo, xmax = hi), width = 0.2, linewidth = 0.4) +
# geom_vline(xintercept = 0, linetype = "dashed", color = "grey40") +
# facet_wrap(~ dimension, scales = "free_y", ncol = 1) +
# labs(x = "Coefficient (with 95% CI)", y = NULL)
# save_fig(p, "fig_heterog_bar_faceted", w = 8.5, h = 7)
device = cairo_pdf,否则中文方框/丢失(save_fig 已默认使用)family = "Microsoft YaHei",Mac 用 family = "PingFang SC";在 ggplot 顶层 theme(text = element_text(family = "...")) 覆盖research_purpose 上下文决定目标:准备执行分析所需的数据环境,完成数据质量闸口检查,并在进入 baseline 回归前做好诊断。本 Phase 是实证项目最容易踩坑的环节,必须完整执行下列三块。
01_data_preparation.R:加载必要包(data.table, haven, fixest 等)、读取原始数据、数据清洗、变量构造、保存清洗后的分析数据集以 Phase 1 stage_1_alignment.md 里记录的样本量为准,按规模选择工具:
| 行数 | 读取方式 | 清洗后存储 |
|---|---|---|
| < 100K | data.table::fread() 全量读入 | csv / RData 皆可 |
| 100K – 1M | fread(select = c(...)) 只读需要的列 | 转存 parquet(arrow::write_parquet)或 fst,禁止反复用 csv 中转 |
| 1M – 10M | 用 duckdb::dbGetQuery(con, "SELECT ... FROM read_csv_auto('...')") 直接在 SQL 里过滤/聚合,再落入 R | parquet + DuckDB 常驻 |
| > 10M | 不得一次性 read 进 R;用 DuckDB / Arrow 做切片查询,或按时间/行业分区分批处理 | parquet 分区 |
强制规则:
nrow() 每一张表,估算笛卡尔积上限;若匹配后预期 > 100M 行必须报告并与 baseline 设计者核对fixest::feols,不得用 lm() / plm() 强撑cor() 或 modelsummary::datasummary_correlation)。描述性统计表落盘到 executor/outputs/tables/desc_stats.*。DescTools::Winsorize)或直接 drop,必须说明选择理由——数据质量差倾向 winsorize,明显录入错误倾向 drop,不要沉默处理。log(1+x)(经济学五大刊已批评过 log(1+x) 滥用),替代方案是 IHS 变换(asinh)或直接改用 Poisson / NB 回归。car::vif() 或 performance::check_collinearity()。VIF < 10 过线,> 5 需要解释。检验 VIF 时可不放 FE 变量——部分 FE 会人为拉高 VIF 但不影响估计结果。VIF 严重超标时必须剔除或合并变量。输出:数据准备脚本(保存在 executor/scripts/)、清洗后的分析数据集描述、样本量记录、数据质量闸口结果、回归前诊断结果
落盘(必须):记录:
目标:执行主回归,产出可信赖的基准结果。
推荐方法:
02_baseline_regression.R,生成清晰、可运行、注释简洁的 R 代码若主结果不稳或不显著,允许对控制变量、样本定义或变量处理做有限的替代设定(最多2次),须标注 changed what。
输出格式:
executor/specification_log.md落盘(必须):
目标:基于 baseline 结果,选择最有必要的扩展分析。不是尽可能多跑,而是有针对性地选择。
推荐方法: Step 1: 明确需要检验什么
Step 2: 选择有针对性的检验
Step 3: 执行并记录
输出格式:Priority Check Map、Mechanism-Supporting Evidence(最多3个)、Heterogeneity(最多3个)、Robustness Checks(最多5个)、Overall Assessment
落盘(必须):
executor/specification_log.md(同 Phase 2,读后拼接再写)目标:将已完成的分析结果转化为出版质量的输出材料。
推荐方法: Step 1: Final Output Selection
Step 2: Table Package
executor/outputs/tables/,agent 只写 .csv(唯一真源):
modelsummary(..., output="data.frame") + fwrite,或直接 write.csv(df, "table_xxx.csv").md(GFM pipe 表格)由 orchestrator 自动派生,agent 无需手写;手写 .md/.tex/.xlsx 都会被下一次 sync 覆盖或与唯一真源冲突table_{role}.csv,role ∈ {baseline, mechanism, robust, heterog, desc_stats, corr_matrix};迭代时覆盖写同名文件,禁止加 _v2 / _new / _final / _vN 等版本后缀(迭代轨迹写入 specification_log.md,不要用文件名记版本).csv(agent 写)+ 同名 .md(程序自动派生)Step 3: Figure Package
analyze_image 验证图表质量executor/outputs/figures/,统一调用「统一 R 命令模板」第 4 节的 save_fig(p, name)——它已自动处理 PNG 300 DPI + PDF 矢量 + cairo_pdf 中文支持+ theme_coase()(或 theme_set 已设全局),再 save_fig;不要绕开 helper 自己调 ggsave输出格式:Final Output Recommendation、Table Package、Figure Package
落盘(必须):文件内需列出:
executor/outputs/tables/ 下的表格四件套(.tex / .csv / .md / .xlsx)路径及一句话说明executor/outputs/figures/ 下的图表两件套(.png / .pdf)路径及一句话说明目标:评估产出完整性,给出下一步建议。
推荐方法:
输出格式:Appendix & Next-Step Suggestions(建议附录内容、仍缺少什么、推荐下一步)
落盘(必须)。
在给出最终总结之前,核对以下文件:
executor/stage_1_data_preparation.mdexecutor/stage_2_run_baseline.md ← Reviewer Mode B 必读executor/stage_3_explanation_robustness.md ← Reviewer Mode B 必读executor/stage_4_table_figure_output.mdexecutor/stage_5_assessment.mdexecutor/specification_log.md ← Reviewer Mode B 必读executor/outputs/tables/table_{role}.csv(主回归表,唯一真源)executor/outputs/tables/table_{role}.md(由 orchestrator 自动派生,agent 不要手写;若缺失说明 sync 未触发,可通过任意后续 tool_use 再推一次)tables/ 下不得出现 .tex / .xlsx 文件,也不得出现 _v2 / _final 等版本后缀的冗余 csv.png(300 DPI)和 .pdf(矢量,含中文用 cairo_pdf)缺失任何一个 → 立刻补写再给最终总结。
研究目的一致性核查(最终摘要前必做):
planner/stage_7_baseline_design.md 首部的 Research purpose 字段,记作 Pstage_2_run_baseline.md / stage_3_explanation_robustness.md / stage_5_assessment.md 以及即将输出给用户的最终摘要:
P = causal → 禁止出现 "关联性研究"、"非因果识别"、"仅为相关关系"、"本研究不支持因果解读" 等降级措辞P = associative → 最终摘要必须有 "本研究为关联性研究,结果不支持因果解读" 的明确声明,且禁止出现 "因果效应"、"X 导致 Y"、"X 使得 Y 上升" 等因果措辞P 冲突的措辞 → 先改 stage_*.md,再重写摘要,不得带着不一致的结论输出给用户完成核对后,提供 Executor 阶段的完整总结(不超过5000字),涵盖:基准回归结果、关键发现、稳健性检验结论、生成的表格和图表清单、Specification Log 摘要、对 Writer 的建议。摘要开头必须有一行 "研究类型:{P}",与 Planner 完全一致。
[HINT] Download the complete skill directory including SKILL.md and all related files