- name
- evidence-visualization
- description
- Meta-model-agent 将计算成果转换为可发表的数据图形、表格和排版引用。适用于证据图谱构建。
# 证据图谱构建
## 稳定执行契约
- **执行目标**:把已冻结的计算结果转换为可核验、可复用、可直接入文的图形与表格证据。
- **调用参数**:[visual-plan-or-data-path]。
- **权威输入**:计算结果.md、图表/全部结果.json、逐问结果文件与用户图表要求。
- **允许交付**:图表/中的数据图、表格和图表引用.tex;不得改写上游数值。
- **禁止写入**:不得越权修改已冻结的上游事实、用户原始文件或本协议未授权的目录。
- **可用工具边界**:Bash(*), Read, Write, Edit, Grep, Glob, Agent。
- **最小交付**:每项核心结论至少有匹配的图或表、可追溯数据源、中文标注与论文引用入口。
- **恢复入口**:优先读取当前工作、状态记录和已有产物,从最近一次通过门禁的位置继续。
- **失败回退**:缺少结果或口径冲突时停止绘图并回退计算实现;不得臆造数据补齐视觉效果。
- **收口顺序**:先核对输入,再完成产物,再运行本环节门禁,最后登记状态;门禁未通过不得宣告完成。
Produce visuals and tables from data: **$ARGUMENTS**
## 运行参数
- **FIG_DIR = `图表/`**
- **FORMAT = `pdf`** (vector, suitable for LaTeX)
- **DPI = 300**
- **CUSTOM_REQUIREMENTS** — User-specified requirements, highest priority.
<tools_and_style>
## 工具与表达规范
`shared-scripts/plot_utils.py` 提供学术绘图的基础样式。Meta-model-agent 可按任务需要选用其中的辅助函数、仅调用 `setup_style()` 后直接使用 matplotlib,或完全采用自定义实现。
**Quality floor**: 300 DPI PDF, no in-visual title (`plt.title`), font ≥9pt, grayscale-distinguishable.
**Color palette and recipes**: read `工具/figure_style_guide.md` (color schemes) and `工具/figure_recipes_*.md` (implementation examples).
plot_utils functions: `setup_style`, `save_fig`, `heatmap`, `forest_plot`, `trend_plot`, `bar_compare`, `distribution_plot`, `scatter_plot`, `residual_diagnostic`, `multi_line_plot`, `box_plot`, `radar_plot`, `subplot_grid`
Stats tables: `stats_utils.py` supplies `regression_table`, `descriptive_table`, `correlation_table`.
</tools_and_style>
## ⛔⛔⛔ 交付契约(最高优先级)
除 `图表/图表引用.tex` 外,必须生成 `图表/figure_manifest.json`。`figures` 与 `tables` 均登记 `path`、`question`、`visual_role`、`claim`、`source`、`result_keys`、`reader_task`、`publish` 和 `placement`,表格可另登记 `label`。`visual_role` 取 `mechanism/result/validation/decision/diagnostic`;只有 `publish=true` 的图表必须嵌入正文,诊断、调试、完整长表和被替代资产登记为 `publish=false`。
```json
{
"version": 1,
"figures": [
{
"path": "图表/fig_q1_sensitivity.pdf",
"question": "Q1",
"visual_role": "validation",
"claim": "参数扰动不改变最优方案排序",
"source": "图表/全部结果.json",
"result_keys": ["Q1.validation.sensitivity"],
"reader_task": "比较趋势与稳定区间",
"publish": true,
"placement": "body"
}
],
"tables": [
{
"path": "图表/TABLE_q1_solution.tex",
"label": "tab:q1-solution",
"question": "Q1",
"visual_role": "result",
"claim": "最优方案满足全部约束并优于基线",
"source": "图表/全部结果.json",
"result_keys": ["Q1.solution", "Q1.validation.residual"],
"reader_task": "核对关键决策值与约束余量",
"publish": true,
"placement": "body"
}
]
}
```
正文图表按论证需要组织为“机制 -> 结果 -> 验证/决策”,不是每问机械凑齐三张。所有生成的 `TABLE_*.tex/md` 必须进入 `tables` 分类,但只有 `publish=true` 的摘要表进入正文;相同数据和相同结论的重复资产不得通过更换形式伪装成新证据。
**Must produce all planned visuals (per 论文规划.md or skill-specific plan)** as `图表/fig_*.png/pdf` plus `图表/图表引用.tex` (or, in docx mode, the same PNGs without 图表引用.tex requirement).
⛔ **特殊豁免**:若 论文规划.md 清晰标明写"无图形与表格"或图形与表格清单为空(纯文字综述/思辨论文),准许 图表/ 为空,但**务必**写一个空的 `图表/图表引用.tex` (`touch 图表/图表引用.tex; mkdir -p 图表`) 让下游知道这步跑过了。
⛔ **MUST run output verification prior to ending**:
```bash
PASS=true
mkdir -p 图表
FIG_PNG=$(ls 图表/fig_*.png 2>/dev/null | wc -l)
FIG_PDF=$(ls 图表/fig_*.pdf 2>/dev/null | wc -l)
TOTAL=$((FIG_PNG + FIG_PDF))
# 检查规划是否要求图表
PLAN_HAS_FIG=$(grep -E '^\s*-?\s*fig_|图表清单|图表/fig_' 论文规划.md 2>/dev/null | wc -l)
if [ "$TOTAL" -ge 1 ]; then
echo "✅ 图表/fig_*.png/pdf ($TOTAL)"
elif [ "$PLAN_HAS_FIG" -eq 0 ]; then
echo "✓ 规划无图表, 创建占位 图表引用.tex"
touch 图表/图表引用.tex
else
echo "❌ 规划要求图表但未生成"
PASS=false
fi
MODE=$(grep -q "Word(.docx)\|docx mode" META_MODEL_AGENT.md 2>/dev/null && echo docx || echo pdf)
if [ "$MODE" = "pdf" ] && [ ! -f 图表/图表引用.tex ]; then
touch 图表/图表引用.tex
fi
[ "$PASS" != true ] && echo "⛔ Output verification FAILED — must complete before ending"
```
## 执行流程
### 工作节点 0:恢复核验(断线重跑必读)
⛔ **当前环节可能由于断线/人工重跑被多次启动**。每一次启动前**务必**先扫描已有产物:
```bash
echo "=== 工作区扫描 ==="
HAS_PNG=$(ls 图表/fig_*.png 2>/dev/null | wc -l)
HAS_PDF=$(ls 图表/fig_*.pdf 2>/dev/null | wc -l)
HAS_TIKZ=$(ls 图表/tikz_*.pdf 2>/dev/null | wc -l)
HAS_INCLUDES=$([ -f 图表/图表引用.tex ] && wc -c < 图表/图表引用.tex || echo 0)
echo " fig_*.png: $HAS_PNG, fig_*.pdf: $HAS_PDF, tikz_*.pdf: $HAS_TIKZ"
echo " 图表引用.tex: $HAS_INCLUDES bytes"
```
**依据扫描结果决定行动**:
| 运行状态 | 行动 |
|---|---|
| 满足 论文规划.md 中规划的图形与表格数(不少于规划) + 图表引用.tex 出现 | **跳到 Phase 9 (count verification) 校验**,校验通过即完成 |
| 已有部分图但少于规划数 | **只产出缺失的图**(已出现的图**避免重画**) |
| 图表引用.tex 缺失但图都在 | **只产出 Phase 6 的 图表引用.tex** |
| 啥都没有 | 从 Phase 1 启动 |
⛔ **铁律**:
- **已有 `图表/fig_*.png/pdf` 避免重画**(覆盖会让审稿人看到的图变了)
- **已有的 `图表/TABLE_*.md/tex` 避免重写**(数据已固化)
- 只补缺失的图 / 表
### 工作节点 1:Read manuscript structure + data discovery
1. Consult the full style guide (color schemes + visual selection decision table + anti-patterns + DrawIO/TikZ color schemes — all in one file):
```bash
cat 工具/figure_style_guide.md 2>/dev/null || cat skills/shared-scripts/figure_style_guide.md
```
2. Scan recipe file headings to know what templates are available:
```bash
echo "=== Advanced ==="
(cat 工具/figure_recipes_advanced.md 2>/dev/null || cat skills/shared-scripts/figure_recipes_advanced.md 2>/dev/null) | grep '^## '
echo "=== Basic ==="
(cat 工具/figure_recipes_basic.md 2>/dev/null || cat skills/shared-scripts/figure_recipes_basic.md 2>/dev/null) | grep '^## '
echo "=== Academic ==="
(cat 工具/figure_recipes_academic.md 2>/dev/null || cat skills/shared-scripts/figure_recipes_academic.md 2>/dev/null) | grep '^## '
echo "=== Competition ==="
(cat 工具/figure_recipes_competition.md 2>/dev/null || cat skills/shared-scripts/figure_recipes_competition.md 2>/dev/null) | grep '^## '
echo "=== Empirical ==="
(cat 工具/figure_recipes_empirical.md 2>/dev/null || cat skills/shared-scripts/figure_recipes_empirical.md 2>/dev/null) | grep '^## '
echo "=== Basic (fallback only) ==="
(cat 工具/figure_recipes_basic.md 2>/dev/null || cat skills/shared-scripts/figure_recipes_basic.md 2>/dev/null) | grep '^## '
```
3. **⛔ MANDATORY: Extract the COMPLETE visual plan from planning docs.** Read ALL planning docs and extract every planned visual/table into a numbered checklist:
```bash
echo "=== Extracting figure plan ==="
for plan in 论文规划.md 问题分析.md 选题规划.md 建模报告.md; do
[ -f "$plan" ] || continue
echo "--- $plan ---"
cat "$plan"
done
```
Following reading, output a **FIGURE PLAN CHECKLIST** like this (you MUST produce this prior to proceeding):
```
FIGURE PLAN CHECKLIST (from planning docs):
[ ] 1. fig_xxx — Descriptive stats distribution (Rain Cloud) — data: results.json
[ ] 2. fig_yyy — Model comparison radar (Radar) — data: results.json
[ ] 3. fig_zzz — Regression coefficient forest plot (Forest Plot) — data: results.json
[ ] 4. TABLE_desc — Descriptive statistics table — data: results.json
[ ] 5. TABLE_reg — Regression results table — data: results.json
[ ] 6. drawio_roadmap — Technical roadmap (DrawIO)
Total planned: 6 figures + 2 tables + 1 DrawIO
```
**Every item in the plan MUST appear in this checklist. If the plan says "12 visuals", the checklist is expected to include 12 entries.**
3.5. **⛔ JSON 数据完整性核验(保证数据能支撑全部图形与表格):**
```bash
echo "=== JSON 数据完整性检查 ==="
if [ -f 图表/全部结果.json ]; then
python3 -c "
import json
with open('图表/全部结果.json', 'r') as f:
data = json.load(f)
# 列出所有顶层 key
keys = list(data.keys()) if isinstance(data, dict) else [f'[{i}]' for i in range(min(len(data), 10))]
print(f'JSON 顶层 key ({len(keys)} 个): {keys}')
# 检查是否有空值
def verify_empty(obj, path=''):
issues = []
if isinstance(obj, dict):
for k, v in obj.items():
if v is None or v == '' or v == []:
issues.append(f'{path}.{k} 为空')
else:
issues.extend(verify_empty(v, f'{path}.{k}'))
elif isinstance(obj, list) and len(obj) == 0:
issues.append(f'{path} 为空列表')
return issues
issues = verify_empty(data)
if issues:
print(f'⚠ 发现 {len(issues)} 个空值:')
for i in issues[:5]:
print(f' - {i}')
else:
print('✅ JSON 数据无空值')
" 2>/dev/null
else
echo "⚠ 图表/全部结果.json 不存在,图表将缺少数据支撑"
fi
# 检查各子问题的结果文件
for f in 图表/problem_*_结果.json; do
[ -f "$f" ] && echo "✅ $(basename $f) 存在" || true
done
```
4. Scan data files (`用户数据/` > `图表/` > root). **⛔ 避免 `cat` 或 `print()` 全部 JSON 文件——大 JSON 会撑爆上下文。** 只用以下方式扫描:
```bash
ls -la 图表/*.json 2>/dev/null
python3 -c "
import json, os
def summarize(v, depth=0):
if isinstance(v, list):
n = len(v)
nulls = sum(1 for x in v if x is None)
nums = [x for x in v if isinstance(x, (int,float)) and x is not None]
if nums:
return f'list[{n}] nulls={nulls} range=[{min(nums):.4g}, {max(nums):.4g}] sample={v[:3]}'
elif v and isinstance(v[0], dict):
return f'list[{n}] of dict, keys={list(v[0].keys())[:8]}'
return f'list[{n}] sample={str(v[:3])[:100]}'
elif isinstance(v, dict) and depth < 2:
items = []
Ver no GitHub