with one click
delivery-assurance
Meta-model-agent 完成编译、版式、匿名、页数、引用与提交前合规验收。适用于提交质量验收。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Meta-model-agent 完成编译、版式、匿名、页数、引用与提交前合规验收。适用于提交质量验收。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Meta-model-agent 致力于辅助研究者与参赛团队完成高质量数学建模研究和论文产出,提供从问题理解、模型构建、计算实验、证据可视化到论文写作、冠军级多轮审稿与提交验收的完整工程支持。适用于 CUMCM、51MCM、MCM/ICM 及同类数模研究任务,可用于启动或恢复项目、按证据门禁推进、修复薄弱环节并形成可复现、可验证、可提交的高质量数模论文。
Meta-model-agent 将计算成果转换为可发表的数据图形、表格和排版引用。适用于证据图谱构建。
Meta-model-agent 将数学机制落地为可运行程序、数值实验、结果合同与可复核证据。适用于计算实验实现。
Meta-model-agent 整合模型、程序、结果、图形与引用为完整中文竞赛文稿。适用于竞赛文稿集成。
Meta-model-agent 将竞赛题面转换为子问题、变量、约束、证据和后续工作契约。适用于问题情境解构与建模前置分析。
Meta-model-agent 构建技术路线、方法关系、系统架构与流程示意资产。适用于系统逻辑制图。
| name | delivery-assurance |
| description | Meta-model-agent 完成编译、版式、匿名、页数、引用与提交前合规验收。适用于提交质量验收。 |
参考资料/paper-layout/core.md 与 body-density.md。latex-figures.md。docx-figures.md。DOCX 路线使用 python 工具/docx_export.py --workspace . 生成 论文/数模论文.docx 和 论文/docx_report.json。不得对 DOCX 路线执行 XeLaTeX/BibTeX;验收以 Markdown 正文、DOCX 包、尺寸报告以及可选的 LibreOffice PDF 预览为准。
编译前必须读取 状态/工作流状态.json 中的竞赛 Profile 和 参考资料/竞赛规则.md:
51mcmthesis、withoutpreface、报名号/题号/组别字段,以及正文不存在学校、成员、邮箱和电话信息。编译成功不能覆盖竞赛 Profile 门禁失败。
Compile and validate: $ARGUMENTS
ENGINE = xelatex
MAX_COMPILE_ATTEMPTS = 3
PAPER_DIR = 论文/
MAX_PAGES / COMPETITION — From Additional Parameters.
if ! which xelatex 2>/dev/null; then
echo "xelatex not found, attempting install..."
if which miktex 2>/dev/null; then
miktex packages install xetex ctex xecjk gbt7714 fontspec
miktex fndb refresh
elif which initexmf 2>/dev/null; then
initexmf --set-config-value=[MPM]AutoInstall=1
fi
fi
which xelatex && which bibtex && echo "ready" || echo "xelatex/bibtex not found"
fc-list :lang=zh | head -5
kpsewhich gbt7714.sty 2>/dev/null || echo "gbt7714.sty not found (will auto-install on first compile)"
if [ -f "工具/compile_utils.sh" ]; then
bash 工具/compile_utils.sh 论文/
elif [ -f "skills/shared-scripts/compile_utils.sh" ]; then
bash skills/shared-scripts/compile_utils.sh 论文/
else
echo "compile_utils.sh not found, manual cleanup needed"
fi
This utility auto-handles: special chars cleanup, table format fixes, includegraphics path correction (图表/ → ../图表/), hidelinks, 图表/图表/ nesting, math_commands conflicts, wide table resizebox wrapping, narrow table resizebox removal, light-color text fixes, TikZ library injection.
If script not found, perform these steps manually.
⛔ 表格行结束符修复(Misplaced \noalign 的根因):
# 检测并修复 tabular/longtable 中的单 \ 行结束符(应该是 \\)
# 这是 heredoc 不加引号导致 \\ 被转义为 \ 的常见问题
for f in 论文/章节/*.tex; do
[ -f "$f" ] || continue
# 检测:tabular 环境内,行末只有单个 \ 后跟换行(应该是 \\)
if grep -P '(?<!\\)\\(?!\\)(?=\s*$)' "$f" | grep -v '\\begin\|\\end\|\\hline\|\\toprule\|\\midrule\|\\bottomrule\|\\caption\|\\label\|\\centering\|\\input\|\\include\|\\usepackage\|\\section\|\\subsection' > /dev/null 2>&1; then
echo "⚠ $(basename $f): 可能有表格行结束符问题(单 \\ 应为 \\\\)"
# 在 tabular/longtable 环境内,把行末的单 \ 替换为 \\
python3 -c "
import re
with open('$f', 'r', encoding='utf-8') as fh:
content = fh.read()
# 只在 tabular/longtable 环境内修复
def fix_table_endings(match):
table = match.group(0)
# 把数据行末尾的单 \ (后跟换行) 替换为 \\\\
fixed = re.sub(r'(?<=&[^&\n]*)\\\s*\n', r'\\\\\\\\\n', table)
return fixed
for env in ['tabular', 'longtable']:
pattern = r'(\\\\begin\{' + env + r'[*]?\}.*?\\\\end\{' + env + r'[*]?\})'
content = re.sub(pattern, fix_table_endings, content, flags=re.DOTALL)
with open('$f', 'w', encoding='utf-8') as fh:
fh.write(content)
" 2>/dev/null
fi
done
Additionally validate ref/label matching and embed missing visuals:
mkdir -p 临时文件
grep -oh '\\ref{[^}]*}' 论文/章节/*.tex 论文/论文正文.tex 2>/dev/null | sort -u > 临时文件/_refs.txt
grep -oh '\\label{[^}]*}' 论文/章节/*.tex 论文/论文正文.tex 2>/dev/null | sort -u > 临时文件/_labels.txt
comm -23 <(sed 's/\\ref/\\label/g' 临时文件/_refs.txt) 临时文件/_labels.txt > 临时文件/_missing_labels.txt
cat 临时文件/_missing_labels.txt
⛔ 中文引号统一为全角引号(避免 PDF 出现 ''乱码或两个堆叠反引号):
中文论文用 xeCJK,全角引号 "..." 会自动化渲染为漂亮的对称弯引号。
LaTeX 风格 ...'' `` 在中文字体下会呈现成两个堆叠的反引号,很丑。
ASCII 直引号 "..." 在 LaTeX 中渲染为右右引号 ''...''。
统一替换为全角引号。
# 把所有错误引号统一为全角引号
for f in 论文/章节/*.tex; do
[ -f "$f" ] || continue
python3 -c "
import re
content = open('$f', 'r', encoding='utf-8').read()
# 保护数学环境
placeholders = []
def stash(m):
placeholders.append(m.group(0)); return f'\\x00M{len(placeholders)-1}\\x00'
content = re.sub(r'\\\$[^\\\$]*\\\$', stash, content)
content = re.sub(r'\\\\\\[.*?\\\\\\]', stash, content, flags=re.DOTALL)
# 保护 \begin{verbatim}/lstlisting 等代码环境
content = re.sub(r'\\\\begin\{(verbatim|lstlisting|minted)\}.*?\\\\end\{\\1\}', stash, content, flags=re.DOTALL)
# 1. LaTeX 风格 ``...'' → 全角双引号
content = re.sub(r\"\`\`([^\`'\\\\n]+?)''\", '\u201c\\\\g<1>\u201d', content)
# 2. ASCII 直引号 \"...\" → 全角双引号(成对处理)
parts = content.split('\"')
if len(parts) > 2:
result = parts[0]
for i, p in enumerate(parts[1:], 1):
result += ('\u201c' if i % 2 == 1 else '\u201d') + p
content = result
# 还原
for i, ph in enumerate(placeholders):
content = content.replace(f'\\x00M{i}\\x00', ph)
open('$f', 'w', encoding='utf-8').write(content)
" 2>/dev/null
done
If labels are missing, find corresponding figure/table code in 图表/*.tex and embed into the correct section file.
Also verify compile_utils.sh output for "UNEMBEDDED" warnings — each one means a figure or table from 图表/ is not in any section.
MANDATORY FIX LOOP — do NOT proceed to compilation until all figures AND tables are embedded:
UNEMBED=0
# Validate PDF visuals
for pdf in 图表/*.pdf; do
[ -f "$pdf" ] || continue
bn=$(basename "$pdf")
grep -rq "$bn" 论文/章节/*.tex 论文/论文正文.tex 2>/dev/null || { echo "UNEMBEDDED PDF: $bn"; UNEMBED=$((UNEMBED+1)); }
done
# Validate TABLE_*.tex files
for tbl in 图表/TABLE_*.tex; do
[ -f "$tbl" ] || continue
bn=$(basename "$tbl")
# Validate if any label from this table file appears in sections
for lbl in $(grep -oh '\\label{[^}]*}' "$tbl" 2>/dev/null); do
grep -rq "$lbl" 论文/章节/*.tex 论文/论文正文.tex 2>/dev/null || { echo "UNEMBEDDED TABLE: $lbl (from $bn)"; UNEMBED=$((UNEMBED+1)); }
done
done
# Validate 图表引用.tex labels
if [ -f 图表/图表引用.tex ]; then
for lbl in $(grep -oh '\\label{[^}]*}' 图表/图表引用.tex 2>/dev/null); do
grep -rq "$lbl" 论文/章节/*.tex 论文/论文正文.tex 2>/dev/null || { echo "UNEMBEDDED: $lbl (from 图表引用.tex)"; UNEMBED=$((UNEMBED+1)); }
done
fi
echo "Total unembedded: $UNEMBED"
If UNEMBED > 0, you MUST fix ALL of them before compiling. For each unembedded item:
PDF figure: copy the \begin{figure}...\end{figure} block from 图表/图表引用.tex into the target section
TABLE_*.tex: copy the \begin{table}...\end{table} block from 图表/TABLE_*.tex into the target section (use \input{../图表/TABLE_xxx.tex} or paste the tabular code directly)
Add 1-2 sentences of lead-in text before and 3-5 sentences of analysis after each embedded item
Re-run the count verify above — repeat until UNEMBED = 0
Do NOT compile with unembedded figures or tables — the PDF will have missing content.
# Validate all 图表/*.pdf are referenced in body
for pdf in 图表/*.pdf; do
[ -f "$pdf" ] || continue
bn=$(basename "$pdf")
grep -rq "$bn" 论文/章节/*.tex 论文/论文正文.tex 2>/dev/null || echo "⚠ $bn not referenced"
done
cd 论文/
xelatex -interaction=nonstopmode 论文正文.tex
bibtex 论文正文
xelatex -interaction=nonstopmode 论文正文.tex
xelatex -interaction=nonstopmode 论文正文.tex
After each compilation, verify 编译日志.log for CRITICAL errors. You MUST fix ALL errors before declaring compilation complete.
# Count critical errors
MATH_ERR=$(grep -c 'Bad math environment delimiter\|Missing \$ inserted\|begin{document} ended by' 论文/编译日志.log 2>/dev/null || echo 0)
LR_ERR=$(grep -c 'Not allowed in LR mode' 论文/编译日志.log 2>/dev/null || echo 0)
UNDEF_CS=$(grep -c 'Undefined control sequence' 论文/编译日志.log 2>/dev/null || echo 0)
TOTAL_ERR=$((MATH_ERR + LR_ERR))
echo "Math errors: $MATH_ERR, LR mode errors: $LR_ERR, Undefined CS: $UNDEF_CS"
if [ "$TOTAL_ERR" -gt 0 ]; then
echo "CRITICAL: $TOTAL_ERR errors — MUST FIX prior to proceeding"
# Show error locations
grep -B2 'Bad math\|Missing \$ inserted\|begin{document} ended\|Not allowed in LR mode' 论文/编译日志.log | grep -E '^\./|^l\.' | head -20
fi
Error fix rules (iterate up to 5 times, not 3):
Math environment errors (Bad math environment delimiter, Missing $ inserted, \begin{document} ended by \end{equation}):
Read the error location from 编译日志.log (e.g., ./章节/3_model_theory.tex:42)
Open the file and find the broken math: usually \X(t)$ should be $X(t)$, or \mu$ should be $\mu$
Common cause: a sed/cleanup script stripped the opening $ but left the closing $
Fix: ensure every math expression has matching $...$ or \[...\] delimiters
Do NOT use broad sed patterns to fix math — read each error location and fix individually
LR mode errors (Not allowed in LR mode):
Usually caused by \begin{figure} or \begin{table} inside a paragraph without proper separation
Fix: add \par or blank line before the float environment
Undefined control sequence:
Missing package → add \usepackage{xxx} to 论文正文.tex preamble
Typo in command → fix the command name
BibTeX failures:
If BibTeX fails because of earlier LaTeX errors, fix the LaTeX errors first, then recompile
Verify that \bibliography{references} and \bibliographystyle{plainnat} exist in 论文正文.tex
Verify that references.bib has no syntax errors (unmatched braces, missing commas)
After each fix, recompile and reverify:
cd 论文/
xelatex -interaction=nonstopmode 论文正文.tex
bibtex 论文正文 2>&1 | tail -5
xelatex -interaction=nonstopmode 论文正文.tex
xelatex -interaction=nonstopmode 论文正文.tex
cd ..
# Reverify
MATH_ERR=$(grep -c 'Bad math environment delimiter\|Missing \$ inserted' 论文/编译日志.log 2>/dev/null || echo 0)
echo "Remaining math errors: $MATH_ERR"
⛔ Do NOT proceed to Step 5 until MATH_ERR = 0 and LR_ERR = 0. BibTeX will also fail if there are LaTeX errors upstream — fix LaTeX first.
When fixing errors in 论文正文.tex, only fix the specific error (e.g., add a missing package, fix a typo). Avoid rewrite or restructure 论文正文.tex — the template's preamble, cover page, page margins, section numbering format, and header/footer settings must remain unchanged.
bash 工具/compile_check.sh 论文/ 2>/dev/null || bash skills/shared-scripts/compile_check.sh 论文/
The script checks: PDF existence/size, undefined references, overfull hbox, TOC, abstracts, bibliography entries, citation count, citation format (上标/顺序/合并), unused figures, figure stacking, TikZ diagram presence.
⛔ MANDATORY: 引用格式问题必须修复(不可忽略):
compile_check.sh 会检查 3 类引用格式问题,任何一类 FAIL/WARN 都必须修复:
上标格式 FAIL → 如果 bibliographystyle 是 plain/plainnat/unsrt 但 \cite{} 没有上标
修复方法A:改 bibliographystyle 为 gbt7714-numerical 或 plainnat + \usepackage[numbers,square,super]{natbib}
修复方法B:把正文里所有 \cite{x} 改为 \upcite{x} 或 \textsuperscript{\cite{x}}
多引用顺序 WARN → \cite{c,a,b} 但全文 a 先出现
修复方法:改成 \cite{a,b,c}(按全文首次出现顺序)
用以下 bash 找出所有需修复的位置:
grep -rnP '\\(up)?cite\{[^}]+\}' 论文/章节/*.tex 论文/论文正文.tex
连续引用未合并 WARN → \cite{a}\cite{b} 或 \cite{a} \cite{b}
修复方法:合并为 \cite{a,b}
批量修复:
# 找出全部需合并的位置
grep -rnoP '\\(up)?cite\{[^}]+\}\s*\\(up)?cite\{[^}]+\}' 论文/章节/*.tex 论文/论文正文.tex
⛔ 修复后必须重新编译验证: xelatex → bibtex → xelatex → xelatex,然后重新运行 compile_check.sh 确认无 FAIL。
Additionally verify:
# List of visuals / list of tables (stats competition requirement)
[ -s 论文/论文正文.lof ] && echo "✅ 插图清单已产出" || echo "⚠ 插图清单为空"
[ -s 论文/论文正文.lot ] && echo "✅ 表格清单已产出" || echo "⚠ 表格清单为空"
Template format verification (stats competition):
echo "=== 模板格式校验 ==="
if grep -q 'stats\|统计建模' 论文/论文正文.tex 2>/dev/null || [ "$COMPETITION" = "stats" ]; then
# Validate page margins (is expected to be 2.54cm top/bottom, 3.17cm left/right)
grep -q '2.54cm' 论文/论文正文.tex && echo "✅ 页边距无误" || echo "⚠ 页边距可能不对(应为上下2.54cm,左右3.17cm)"
# Validate Chinese section numbering
grep -q 'chinese{section}' 论文/论文正文.tex && echo "✅ 中文章节编号" || echo "⚠ 缺少中文章节编号(一、二、三...)"
# Validate cover page
grep -q '参赛学校\|参赛作品\|作品编号' 论文/论文正文.tex && echo "✅ 封面出现" || echo "⚠ 缺少封面"
# Verify abstract format (should be \section*{摘要}, not \begin{abstract})
grep -q 'section\*.*摘要' 论文/论文正文.tex && echo "✅ 摘要格式无误" || echo "⚠ 摘要格式可能不对"
# Validate natbib (stats uses natbib, not gbt7714)
grep -q 'natbib' 论文/论文正文.tex && echo "✅ natbib 引用格式" || echo "⚠ 缺少 natbib(统计建模应用 natbib)"
# Validate no header line
grep -q 'headrulewidth.*0pt' 论文/论文正文.tex && echo "✅ 无页眉线" || echo "⚠ 可能有页眉线"
# Validate listoffigures / listoftables
grep -q 'listoffigures' 论文/论文正文.tex && echo "✅ 插图清单命令" || echo "⚠ 缺少 \\listoffigures"
grep -q 'listoftables' 论文/论文正文.tex && echo "✅ 表格清单命令" || echo "⚠ 缺少 \\listoftables"
fi
If any format checks fail, Meta-model-agent should fix 论文正文.tex to match the template format before recompiling.
Verify items:
Page count: determine which parts count under the active competition Profile and require the count to be ≤ MAX_PAGES. Separately reject substantively incomplete chapters; never require the paper to fill the page ceiling.
Anonymous: no team info (队号, 队员, 指导老师)
Abstract exists (数模竞赛: at least Chinese; 统计建模: both Chinese and English)
TOC exists (required by MathorCup etc.)
Code appendix exists
No undefined references/citations
“Code appendix exists”不得只检查标题或“代码/程序”关键词。必须读取 程序/code_manifest.json,逐项核验源码存在、SHA-256 未陈旧、required_in_appendix=true 的文件均有 CODE_FILE 标记和真实 \lstinputlisting/代码块。CUMCM 要求全部完整可运行源程序;其他赛制按 Profile 核验核心实现。
CUMCM 页数必须读取编译后的 AbstractStart/AbstractEnd 与 BodyStart/BodyEnd 标签:摘要不超过 1 页,正文不超过 30 页,附录页数单独报告且不计入正文。模板含目录、标签缺失或仅用字符数估算时直接失败。
<page_diagnosis>
不要再把“正文达到 MAX_PAGES 的 80%”作为硬目标。MAX_PAGES 只表示上限。即使页数较少,也只有在论证链缺失时才扩充正文。
echo "=== 页数不足诊断 ==="
echo "页数上限: MAX_PAGES;另行检查正文论证充分性"
echo ""
echo "=== 各章节字符数(找出最薄的章节)==="
for f in 论文/章节/*.tex; do
chars=$(wc -c < "$f")
echo " $(basename $f): $chars 字符 (~$(echo "scale=1; $chars/900" | bc) 页)"
done
echo ""
echo "=== 推荐扩充的章节(字符数最少的 3 个)==="
for f in $(ls -S 论文/章节/*.tex | tail -3); do
chars=$(wc -c < "$f")
echo " ⚠ $(basename $f): 仅 $chars 字符"
done
只有出现以下问题时才标记为 CRITICAL 并扩充:
某个子问题缺少模型机制或必要公式推导
结果只有数字或图表,没有验证和解释
摘要/结论中的关键主张无法在正文定位
扩充时只添加有证据来源的内容:
Read 建模报告.md and 计算结果.md for detailed content
Add unexpanded derivations, result analysis, validation, parameter discussions, and limitations
Recompile after expansion
</page_diagnosis>
Run all checks and verify every item passes. Do NOT output the report until all CRITICAL items are resolved.
echo "=========================================="
echo " FINAL QUALITY GATE"
echo "=========================================="
GATE_FAIL=0
# 1. PDF exists and non-trivial
if [ -f 论文/数模论文.pdf ] && [ $(wc -c < 论文/数模论文.pdf) -gt 100000 ]; then
echo "✅ PDF exists ($(wc -c < 论文/数模论文.pdf) bytes)"
else
echo "❌ PDF missing or too small"; GATE_FAIL=$((GATE_FAIL+1))
fi
# 2. No LaTeX errors
MATH_ERR=$(grep -c 'Bad math environment delimiter\|Missing \$ inserted' 论文/编译日志.log 2>/dev/null || echo 0)
LR_ERR=$(grep -c 'Not allowed in LR mode' 论文/编译日志.log 2>/dev/null || echo 0)
[ "$((MATH_ERR+LR_ERR))" -eq 0 ] && echo "✅ No LaTeX errors" || { echo "❌ $MATH_ERR math + $LR_ERR LR errors"; GATE_FAIL=$((GATE_FAIL+1)); }
# 3. Bibliography not empty
BBL_ENTRIES=$(grep -c '\\bibitem' 论文/论文正文.bbl 2>/dev/null || echo 0)
[ "$BBL_ENTRIES" -gt 0 ] && echo "✅ Bibliography: $BBL_ENTRIES entries" || { echo "❌ Bibliography empty (BibTeX failed)"; GATE_FAIL=$((GATE_FAIL+1)); }
# 4. No unembedded visuals
UNEMBED=0
for pdf in 图表/*.pdf; do
[ -f "$pdf" ] || continue
bn=$(basename "$pdf")
grep -rq "$bn" 论文/章节/*.tex 论文/论文正文.tex 2>/dev/null || UNEMBED=$((UNEMBED+1))
done
[ "$UNEMBED" -eq 0 ] && echo "✅ All visuals embedded" || { echo "❌ $UNEMBED visuals not embedded in manuscript"; GATE_FAIL=$((GATE_FAIL+1)); }
# 5. Page count
PAGE_EST=0
for f in 论文/章节/*.tex; do [ -f "$f" ] || continue; c=$(wc -c < "$f"); PAGE_EST=$((PAGE_EST + c)); done
PAGE_EST=$((PAGE_EST / 900))
echo " Body estimate: ~$PAGE_EST pages; MAX_PAGES is the submission ceiling, not a fill target"
# 6. Overfull vbox (table/visual overflow)
VBOX_ERR=$(grep -c 'Overfull.*vbox' 论文/编译日志.log 2>/dev/null || echo 0)
[ "$VBOX_ERR" -eq 0 ] && echo "✅ No table/visual overflow" || { echo "❌ $VBOX_ERR overfull vbox — tables may be cut off"; GATE_FAIL=$((GATE_FAIL+1)); }
# 7. AI writing patterns (itemize in body)
AI_LISTS=0
for f in 论文/章节/*.tex; do
[ -f "$f" ] || continue
echo "$(basename $f)" | grep -qi 'appendix\|附录' && continue
c=$(grep -c '\\begin{itemize}' "$f" 2>/dev/null || echo 0)
AI_LISTS=$((AI_LISTS + c))
done
[ "$AI_LISTS" -eq 0 ] && echo "✅ No bullet lists in body" || { echo "❌ $AI_LISTS itemize — convert to prose"; GATE_FAIL=$((GATE_FAIL+1)); }
# 8. Template integrity — compare preamble against established template
echo "--- Template integrity ---"
TMPL=""
for t in 模板/stats_论文正文.tex 模板/cumcm_论文正文.tex 模板/mcm_论文正文.tex 模板/bachelor_论文正文.tex 模板/master_论文正文.tex 模板/journal_论文正文.tex; do
[ -f "$t" ] && TMPL="$t" && break
done
if [ -n "$TMPL" ] && [ -f 论文/论文正文.tex ]; then
# Extract preamble (before \begin{document}) from both files
TMPL_PRE=$(sed -n '1,/\\begin{document}/p' "$TMPL" | grep '\\usepackage\|\\documentclass\|\\ctexset\|\\pagestyle\|\\renewcommand.*headrulewidth\|\\listoftables\|\\listoffigures\|\\cline\|\\bibliography' | sort)
MAIN_PRE=$(sed -n '1,/\\begin{document}/p' 论文/论文正文.tex | grep '\\usepackage\|\\documentclass\|\\ctexset\|\\pagestyle\|\\renewcommand.*headrulewidth\|\\listoftables\|\\listoffigures\|\\cline\|\\bibliography' | sort)
MISSING=$(comm -23 <(echo "$TMPL_PRE") <(echo "$MAIN_PRE") 2>/dev/null | head -5)
if [ -z "$MISSING" ]; then
echo "✅ Template preamble intact"
else
echo "❌ Template preamble was modified — these lines from template are missing in 论文正文.tex:"
echo "$MISSING" | sed 's/^/ /'
GATE_FAIL=$((GATE_FAIL+1))
fi
# Validate cover page structure (if template has one)
if grep -q '参赛学校\|参赛作品' "$TMPL" 2>/dev/null; then
grep -q '参赛学校\|参赛作品' 论文/论文正文.tex 2>/dev/null && echo "✅ Cover page present" || { echo "❌ Cover page missing/rewritten"; GATE_FAIL=$((GATE_FAIL+1)); }
grep -q 'cline{2-2}' 论文/论文正文.tex 2>/dev/null && echo "✅ Cover underlines (cline)" || { echo "❌ Cover cline missing"; GATE_FAIL=$((GATE_FAIL+1)); }
fi
# Validate bracket placeholders not remaining
if grep -q '\[论文标题\]\|\[学校名称\]\|\[队员1\]\|\[指导老师\]\|\[竞赛年份\]\|\[届数\]\|\[中文摘要内容\]' 论文/论文正文.tex 2>/dev/null; then
echo "❌ Unreplaced bracket placeholders in 论文正文.tex"; GATE_FAIL=$((GATE_FAIL+1))
else
echo "✅ All placeholders replaced"
fi
# Validate hand-written visual/table list (anti-pattern)
if grep -P '^(表|图)\d+\.' 论文/论文正文.tex 2>/dev/null | head -1 | grep -q '.'; then
echo "❌ Hand-written figure/table list (use \\listoftables/\\listoffigures)"; GATE_FAIL=$((GATE_FAIL+1))
fi
else
echo " (no template found for comparison, skipping)"
fi
# 9. Visual plan reconciliation (validate planning docs)
echo "--- Visual plan validate ---"
PLAN_FIGS=0; ACTUAL_FIGS=$(ls 图表/*.pdf 2>/dev/null | wc -l)
for plan in 选题规划.md 论文规划.md 问题分析.md; do
[ -f "$plan" ] || continue
pf=$(grep -ci 'fig_\|图.*:\|visual.*:' "$plan" 2>/dev/null || echo 0)
[ "$pf" -gt "$PLAN_FIGS" ] && PLAN_FIGS=$pf
done
if [ "$PLAN_FIGS" -gt 0 ]; then
echo " Planned: ~$PLAN_FIGS visuals, Actual: $ACTUAL_FIGS PDFs"
[ "$ACTUAL_FIGS" -ge "$PLAN_FIGS" ] && echo "✅ Visual count meets plan" || { echo "❌ Fewer visuals than planned ($ACTUAL_FIGS < $PLAN_FIGS)"; GATE_FAIL=$((GATE_FAIL+1)); }
else
echo " No visual plan found, actual: $ACTUAL_FIGS PDFs"
fi
# 10. TikZ 几何/算法/架构图
# TikZ 由 systems-diagramming 编译成 图表/结构示意图.pdf, 通过 \includegraphics 嵌入
# (不是 sections 里的裸 tikzpicture 代码)。两种形态都算已嵌入。
TIKZ_IN_PAPER=$(grep -rl 'tikzpicture\|结构示意图\|tikz_' 论文/章节/*.tex 论文/论文正文.tex 2>/dev/null | wc -l)
# ⛔ 只在"真实产出了 tikz_*.pdf 产物"时才硬核对(避免规划提了但用 DrawIO 替代时误报失败)
TIKZ_PDF_TOTAL=0; TIKZ_PDF_MISSING=0
for tpdf in 图表/结构示意图.pdf 图表/结构示意图_*.pdf 图表/tikz_*.pdf; do
[ -f "$tpdf" ] || continue
TIKZ_PDF_TOTAL=$((TIKZ_PDF_TOTAL+1))
grep -rq "$(basename "$tpdf")" 论文/章节/*.tex 论文/论文正文.tex 2>/dev/null || TIKZ_PDF_MISSING=$((TIKZ_PDF_MISSING+1))
done
if [ "$TIKZ_PDF_TOTAL" -gt 0 ]; then
# 有真实 TikZ 产物 → 务必全部嵌入
if [ "$TIKZ_PDF_MISSING" -gt 0 ]; then
echo "❌ $TIKZ_PDF_MISSING 张 TikZ PDF 未嵌入任何章节"; GATE_FAIL=$((GATE_FAIL+1))
else
echo "✅ TikZ diagrams embedded ($TIKZ_PDF_TOTAL)"
fi
elif grep -qi 'tikz\|架构\|路线图\|几何示意\|算法流程' 论文规划.md 问题分析.md 2>/dev/null; then
# 规划提到 TikZ 但没产出 tikz_*.pdf(可能已用 DrawIO 替代) → 仅提醒, 不判失败
[ "$TIKZ_IN_PAPER" -gt 0 ] && echo "✅ TikZ embedded" || echo " ⚠ 规划提到 TikZ 但未发现 tikz_*.pdf(可能已用 DrawIO 替代, 不阻塞)"
else
[ "$TIKZ_IN_PAPER" -gt 0 ] && echo "✅ TikZ diagrams embedded ($TIKZ_IN_PAPER)" || echo " (no TikZ planned)"
fi
# 11. Citations in body
CITE_COUNT=$(grep -roh '\\cite{' 论文/章节/*.tex 论文/论文正文.tex 2>/dev/null | wc -l)
[ "$CITE_COUNT" -gt 0 ] && echo "✅ Citations: $CITE_COUNT" || { echo "❌ No citations in body text"; GATE_FAIL=$((GATE_FAIL+1)); }
# 12. No placeholders remaining
PLACEHOLDERS=$(grep -rl 'PLACEHOLDER\|待补充\|TODO\|\[论文标题\]\|\[中文摘要内容\]' 论文/章节/*.tex 论文/论文正文.tex 2>/dev/null | wc -l)
[ "$PLACEHOLDERS" -eq 0 ] && echo "✅ No placeholders" || { echo "❌ $PLACEHOLDERS files have placeholders"; GATE_FAIL=$((GATE_FAIL+1)); }
# 13. Undefined references
UNDEF_REFS=$(grep -c 'LaTeX Warning.*Reference.*undefined' 论文/编译日志.log 2>/dev/null || echo 0)
[ "$UNDEF_REFS" -eq 0 ] && echo "✅ No undefined refs" || { echo "❌ $UNDEF_REFS undefined references"; GATE_FAIL=$((GATE_FAIL+1)); }
# 14. Overfull hbox (>5 = too many)
HBOX_ERR=$(grep -c 'Overfull.*hbox' 论文/编译日志.log 2>/dev/null || echo 0)
[ "$HBOX_ERR" -lt 5 ] && echo "✅ Overfull hbox: $HBOX_ERR" || { echo "❌ $HBOX_ERR overfull hbox — fix wide tables/formulas"; GATE_FAIL=$((GATE_FAIL+1)); }
# 15. Visual stacking
STACKING=0
for f in 论文/章节/*.tex; do [ -f "$f" ] || continue; s=$(awk '/\\end\{(figure|table)\}/{a=1;t=0;next} a&&/\\begin\{(figure|table)\}/{if(t<3)c++;a=0;next} a&&/[a-zA-Z\x80-\xff]{3,}/{t++} a&&t>=3{a=0} END{print c+0}' "$f" 2>/dev/null); STACKING=$((STACKING+s)); done
[ "$STACKING" -eq 0 ] && echo "✅ No visual stacking" || { echo "❌ $STACKING visual stacking — add analysis text between visuals"; GATE_FAIL=$((GATE_FAIL+1)); }
# 16. TOC
if grep -q 'tableofcontents' 论文/论文正文.tex 2>/dev/null; then
[ -s 论文/论文正文.toc ] && echo "✅ TOC generated" || {
echo "❌ TOC empty — running extra compile pass..."
cd 论文/
xelatex -interaction=nonstopmode 论文正文.tex > /dev/null 2>&1
xelatex -interaction=nonstopmode 论文正文.tex > /dev/null 2>&1
cd ..
[ -s 论文/论文正文.toc ] && echo "✅ TOC generated following extra compile" || { echo "❌ TOC still empty"; GATE_FAIL=$((GATE_FAIL+1)); }
}
fi
# 17. Abstracts (Chinese papers)
if grep -q 'ctex' 论文/论文正文.tex 2>/dev/null; then
grep -rq '摘.*要' 论文/章节/*.tex 论文/论文正文.tex 2>/dev/null && echo "✅ Chinese abstract" || { echo "❌ No Chinese abstract"; GATE_FAIL=$((GATE_FAIL+1)); }
grep -rq 'Abstract' 论文/章节/*.tex 论文/论文正文.tex 2>/dev/null && echo "✅ English abstract" || { echo "❌ No English abstract"; GATE_FAIL=$((GATE_FAIL+1)); }
fi
# 18. Run compile_check.sh + writing_check.sh for full details
echo ""
echo "--- Full validate scripts ---"
bash 工具/compile_check.sh 论文/ 2>/dev/null || bash skills/shared-scripts/compile_check.sh 论文/ 2>/dev/null
bash 工具/writing_check.sh 论文/ 2>/dev/null || bash skills/shared-scripts/writing_check.sh 论文/ 2>/dev/null
WC_EXIT=$?
[ "$WC_EXIT" -eq 0 ] && echo "✅ Writing checks passed" || { echo "❌ Writing checks failed (exit=$WC_EXIT)"; GATE_FAIL=$((GATE_FAIL+1)); }
# 19. 符号阐明 longtable 核验
echo "--- Symbol table format ---"
for f in 论文/章节/*.tex; do
[ -f "$f" ] || continue
if grep -q '\\section{符号说明}\|\\section.*符号' "$f" 2>/dev/null; then
if grep -q '\\begin{longtable}' "$f" 2>/dev/null; then
echo "✅ 符号阐明采用 longtable"
elif grep -q '\\begin{table}' "$f" 2>/dev/null; then
echo "❌ 符号阐明仍用 table(应转 longtable 防分页)"; GATE_FAIL=$((GATE_FAIL+1))
fi
fi
done
# 20. 正文长表格核验(>15行应用 longtable)
echo "--- Long table validate ---"
for f in 论文/章节/*.tex; do
[ -f "$f" ] || continue
echo "$(basename $f)" | grep -qi 'symbol\|appendix\|A_code' && continue
if grep -q '\\begin{tabular}' "$f" 2>/dev/null; then
ROW_COUNT=$(awk '/\\begin\{tabular\}/,/\\end\{tabular\}/' "$f" 2>/dev/null | grep -c '&' || echo 0)
[ "$ROW_COUNT" -gt 15 ] && { echo "❌ $(basename $f): $ROW_COUNT 行表格应转 longtable"; GATE_FAIL=$((GATE_FAIL+1)); }
fi
done
# 21. babel[english] 冲突
echo "--- babel validate ---"
if grep -q 'ctex\|cumcmthesis\|gmcmthesis' 论文/论文正文.tex 2>/dev/null; then
grep -q 'babel.*english' 论文/论文正文.tex 2>/dev/null && { echo "❌ 中文论文有 babel[english]"; GATE_FAIL=$((GATE_FAIL+1)); } || echo "✅ 无 babel 冲突"
fi
# 22. 数值一致性(JSON vs 论文)
echo "--- Numerical consistency ---"
if [ -f 图表/全部结果.json ]; then
python3 -c "
import json, re, os
with open('图表/全部结果.json','r',encoding='utf-8') as f: outcomes=json.load(f)
def extract(obj,p=''):
n={}
if isinstance(obj,dict):
for k,v in obj.items(): n.update(extract(v,f'{p}.{k}'))
elif isinstance(obj,(int,float)) and not isinstance(obj,bool):
if 0.001<abs(obj)<1e10: n[p]=obj
return n
jn=extract(outcomes); pn=set()
for tf in sorted(os.listdir('论文/章节')):
if not tf.endswith('.tex'): continue
with open(f'论文/章节/{tf}','r',encoding='utf-8',errors='ignore') as f: t=f.read()
for m in re.finditer(r'(?<![a-zA-Z])(\d+\.?\d+)(?![a-zA-Z_{}])',t):
try: pn.add(float(m.group(1)))
except: pass
miss=sum(1 for k,v in jn.items() if not any(abs(p-v)<abs(v)*0.01+0.001 for p in pn) and any(w in k.lower() for w in ['rmse','r2','accuracy','f1','objective','optimal','best']))
print(f'❌ {miss} key values missing in manuscript' if miss else '✅ Key values consistent')
import sys; sys.exit(1 if miss>3 else 0)
" 2>/dev/null
[ $? -ne 0 ] && GATE_FAIL=$((GATE_FAIL+1))
fi
# 22.5 "太完美"结果检测(AI 编造或过拟合特征)
echo "--- Unrealistic values validate ---"
if [ -f 图表/全部结果.json ]; then
python3 -c "
import json
with open('图表/全部结果.json','r',encoding='utf-8') as f: data=json.load(f)
suspicious = []
def validate(name, val):
if not isinstance(val,(int,float)) or isinstance(val,bool): return
key = name.lower()
if any(w in key for w in ['r2','r_squared','accuracy','acc','precision','recall','f1','auc']) and val > 0.999:
suspicious.append(f'{name}={val:.4f} 过于完美(>0.999)')
if any(w in key for w in ['rmse','mae','mse','loss']) and val == 0:
suspicious.append(f'{name}=0 完美误差')
if ('p_value' in key or 'pvalue' in key) and val == 0:
suspicious.append(f'{name}=0 完美显著')
if any(w in key for w in ['improvement','speedup','gain','提升']) and val > 10:
suspicious.append(f'{name}={val} 提升过大({val*100:.0f}%)')
def walk(obj, path=''):
if isinstance(obj,dict):
for k,v in obj.items(): walk(v, f'{path}.{k}')
elif isinstance(obj,list):
for i,v in enumerate(obj): walk(v, f'{path}[{i}]')
else: validate(path, obj)
walk(data)
if suspicious:
print(f'🚩 {len(suspicious)} 处可疑的完美结果(可能过拟合或数值编造):')
for s in suspicious[:5]: print(f' {s}')
print(' 需在论文中阐明合理性,或回到 computational-realization 核验数据泄漏')
else:
print('✅ 数值合理性通过')
" 2>/dev/null
fi
# 22.6 合理性复核章节是否出现(务必)
echo "--- 合理性复核章节核验 ---"
if [ -f 计算结果.md ]; then
if grep -q '合理性审查\|数值合理\|背景对照\|sanity.*verify' 计算结果.md 2>/dev/null; then
echo "✅ 计算结果.md 涵盖合理性复核章节"
else
echo "❌ 计算结果.md 缺少合理性复核章节 — 回到 computational-realization Phase 1.7 补充"
GATE_FAIL=$((GATE_FAIL+1))
fi
fi
# 22.7 数据源时间戳一致性(代码 vs 图形与表格 vs 论文)
echo "--- 数据源时间戳一致性 ---"
if [ -f 图表/全部结果.json ]; then
JSON_TIME=$(stat -c %Y 图表/全部结果.json 2>/dev/null || stat -f %m 图表/全部结果.json 2>/dev/null || echo 0)
# 核验是否有 PDF 图形与表格比 JSON 旧(阐明代码重跑了但图没更新)
STALE_FIGS=0
for pdf in 图表/*.pdf; do
[ -f "$pdf" ] || continue
PDF_TIME=$(stat -c %Y "$pdf" 2>/dev/null || stat -f %m "$pdf" 2>/dev/null || echo 0)
if [ "$JSON_TIME" -gt "$PDF_TIME" ] && [ "$((JSON_TIME - PDF_TIME))" -gt 60 ]; then
echo " ⚠ $(basename $pdf) 比 全部结果.json 旧 — 图形与表格数据可能过期"
STALE_FIGS=$((STALE_FIGS+1))
fi
done
if [ "$STALE_FIGS" -gt 0 ]; then
echo " ❌ $STALE_FIGS 张图形与表格可能采用了旧数据(JSON 更新后图形与表格未重新产出)"
echo " → 推荐重跑 evidence-visualization 环节更新图形与表格"
GATE_FAIL=$((GATE_FAIL+1))
else
echo "✅ 数据源时间戳保持一致"
fi
fi
# 22.8 正文长表格检测(>12 行的表格不应在正文中完整展开)
echo "--- 正文长表格检测 ---"
LONG_TABLES=0
for f in 论文/章节/*.tex; do
[ -f "$f" ] || continue
# 跳过附录文件
echo "$(basename $f)" | grep -qi 'appendix\|附录\|A_code' && continue
# 统计各个 tabular/longtable 环境内的数据行数(\\ 的数量)
python3 -c "
import re
with open('$f', 'r', encoding='utf-8', errors='ignore') as fh:
content = fh.read()
# 找全部 tabular/longtable 环境
for env in ['tabular', 'longtable', 'tabular*']:
pattern = r'\\\\begin\{' + env + r'[*]?\}.*?\\\\end\{' + env + r'[*]?\}'
for match in re.finditer(pattern, content, re.DOTALL):
table_text = match.group()
row_count = table_text.count('\\\\\\\\') - table_text.count('\\\\hline') // 2
if row_count > 12:
print(f'$(basename $f): {env} 有 {row_count} 行(>12)')
" 2>/dev/null | while read line; do
echo " ❌ $line — 正文表格超过 12 行,应截断(前3+后3+省略),完整版放附录"
LONG_TABLES=$((LONG_TABLES+1))
done
done
[ "$LONG_TABLES" -eq 0 ] && echo "✅ 正文无超长表格" || GATE_FAIL=$((GATE_FAIL+1))
# 23. AI 写作痕迹(列表环境)
echo "--- AI writing patterns ---"
AI_LISTS=0
for f in 论文/章节/*.tex; do
[ -f "$f" ] || continue
echo "$(basename $f)" | grep -qi 'appendix\|A_code' && continue
c=$(grep -c '\\begin{itemize}\|\\begin{enumerate}' "$f" 2>/dev/null || echo 0)
AI_LISTS=$((AI_LISTS+c))
done
[ "$AI_LISTS" -le 3 ] && echo "✅ AI patterns: $AI_LISTS lists" || { echo "❌ $AI_LISTS lists in body — convert to prose"; GATE_FAIL=$((GATE_FAIL+1)); }
# 24. 元叙述泄露
echo "--- Meta content leak ---"
META=0
for f in 论文/章节/*.tex; do
[ -f "$f" ] || continue
l=$(grep -ci 'RESULTS\.md\|META_MODEL_AGENT\.md\|MODELING_REPORT\|PROBLEM_ANALYSIS\|latex_includes' "$f" 2>/dev/null || echo 0)
META=$((META+l))
done
[ "$META" -eq 0 ] && echo "✅ No meta leaks" || { echo "❌ $META meta content leaks"; GATE_FAIL=$((GATE_FAIL+1)); }
# 25. 过度声称
echo "--- Overclaiming ---"
OC=0
for f in 论文/章节/*.tex; do
[ -f "$f" ] || continue
for w in "首次提出" "首次发现" "完美" "最优的" "无可比拟" "前所未有" "开创性" "革命性"; do
c=$(grep -c "$w" "$f" 2>/dev/null || echo 0); OC=$((OC+c))
done
done
[ "$OC" -eq 0 ] && echo "✅ No overclaiming" || echo "⚠ $OC overclaiming instances"
echo ""
echo "=========================================="
if [ "$GATE_FAIL" -eq 0 ]; then
echo " ✅ ALL CRITICAL CHECKS PASSED — ready to submit"
else
echo " ❌ $GATE_FAIL CRITICAL FAILURES — MUST FIX prior to finishing"
echo " Go back and fix each ❌ item, recompile, then re-run this gate."
fi
echo "=========================================="
⛔ If GATE_FAIL > 0, you MUST go back and fix every ❌ item, recompile, and re-run this gate. Do NOT output the final report with any ❌ remaining. Repeat until GATE_FAIL = 0.
Competition name, status, PDF path, total pages, body pages, compliance pass/fail.
No latexmk — manual step-by-step compilation
Avoid delete .bbl file after compilation (bibliography data)
Figure paths auto-corrected by compile_utils.sh: 图表/ → ../图表/
Total/countable pages ≤ MAX_PAGES. Page count is a ceiling;正文充分性按逐问论证链独立检查。
Every embedded LaTeX figure must stay within \linewidth and 0.70\textheight with keepaspectratio; every DOCX image must stay within the computed page body width. Oversized or unreadably shrunken figures are gate failures.
Anonymous: no team info in body
Primary output: 论文/数模论文.pdf, temp files: 临时文件/