paperfit-cli 1.0.0
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/.claude/commands/adjust-length.md +21 -0
- package/.claude/commands/check-visual.md +27 -0
- package/.claude/commands/fix-layout.md +31 -0
- package/.claude/commands/migrate-template.md +23 -0
- package/.claude/commands/repair-table.md +21 -0
- package/.claude/commands/show-status.md +32 -0
- package/.claude-plugin/README.md +77 -0
- package/.claude-plugin/marketplace.json +41 -0
- package/.claude-plugin/plugin.json +39 -0
- package/CLAUDE.md +266 -0
- package/CONTRIBUTING.md +131 -0
- package/LICENSE +21 -0
- package/README.md +164 -0
- package/agents/code-surgeon-agent.md +214 -0
- package/agents/layout-detective-agent.md +229 -0
- package/agents/orchestrator-agent.md +254 -0
- package/agents/quality-gatekeeper-agent.md +270 -0
- package/agents/rule-engine-agent.md +224 -0
- package/agents/semantic-polish-agent.md +250 -0
- package/bin/paperfit.js +176 -0
- package/config/agent_roles.yaml +56 -0
- package/config/layout_rules.yaml +54 -0
- package/config/templates.yaml +241 -0
- package/config/vto_taxonomy.yaml +489 -0
- package/config/writing_rules.yaml +64 -0
- package/install.sh +30 -0
- package/package.json +52 -0
- package/requirements.txt +5 -0
- package/scripts/benchmark_runner.py +629 -0
- package/scripts/compile.sh +244 -0
- package/scripts/config_validator.py +339 -0
- package/scripts/cv_detector.py +600 -0
- package/scripts/evidence_collector.py +167 -0
- package/scripts/float_fixers.py +861 -0
- package/scripts/inject_defects.py +549 -0
- package/scripts/install-claude-global.js +148 -0
- package/scripts/install.js +66 -0
- package/scripts/install.sh +106 -0
- package/scripts/overflow_fixers.py +656 -0
- package/scripts/package-for-opensource.sh +138 -0
- package/scripts/parse_log.py +260 -0
- package/scripts/postinstall.js +38 -0
- package/scripts/pre_tool_use.py +265 -0
- package/scripts/render_pages.py +244 -0
- package/scripts/session_logger.py +329 -0
- package/scripts/space_util_fixers.py +773 -0
- package/scripts/state_manager.py +352 -0
- package/scripts/test_commands.py +187 -0
- package/scripts/test_cv_detector.py +214 -0
- package/scripts/test_integration.py +290 -0
- package/skills/consistency-polisher/SKILL.md +337 -0
- package/skills/float-optimizer/SKILL.md +284 -0
- package/skills/latex_fixers/__init__.py +82 -0
- package/skills/latex_fixers/float_fixers.py +392 -0
- package/skills/latex_fixers/fullwidth_fixers.py +375 -0
- package/skills/latex_fixers/overflow_fixers.py +250 -0
- package/skills/latex_fixers/semantic_micro_tuning.py +362 -0
- package/skills/latex_fixers/space_util_fixers.py +389 -0
- package/skills/latex_fixers/utils.py +55 -0
- package/skills/overflow-repair/SKILL.md +304 -0
- package/skills/space-util-fixer/SKILL.md +307 -0
- package/skills/taxonomy-vto/SKILL.md +486 -0
- package/skills/template-migrator/SKILL.md +251 -0
- package/skills/visual-inspector/SKILL.md +217 -0
- package/skills/writing-polish/SKILL.md +289 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
证据收集器
|
|
4
|
+
|
|
5
|
+
汇总多模态证据链,供 quality-gatekeeper-agent 验收使用。
|
|
6
|
+
收集内容包括:编译日志摘要、页图清单、代码变更 diff、诊断报告路径等。
|
|
7
|
+
|
|
8
|
+
用法:
|
|
9
|
+
python evidence_collector.py --round <N> --output <dir>
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import shutil
|
|
14
|
+
import argparse
|
|
15
|
+
import subprocess
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from datetime import datetime
|
|
18
|
+
from typing import Dict, List, Any, Optional
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class EvidenceCollector:
|
|
22
|
+
"""证据收集器"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, project_root: Path = None):
|
|
25
|
+
self.project_root = project_root or Path.cwd()
|
|
26
|
+
self.data_dir = self.project_root / "data"
|
|
27
|
+
self.evidence_dir = self.data_dir / "evidence"
|
|
28
|
+
|
|
29
|
+
def collect(
|
|
30
|
+
self,
|
|
31
|
+
round_num: int,
|
|
32
|
+
log_file: Optional[Path] = None,
|
|
33
|
+
pages_dir: Optional[Path] = None,
|
|
34
|
+
diagnostic_report: Optional[Path] = None,
|
|
35
|
+
modified_files: Optional[List[Path]] = None,
|
|
36
|
+
state_file: Optional[Path] = None
|
|
37
|
+
) -> Dict[str, Any]:
|
|
38
|
+
"""收集指定轮次的所有证据并打包"""
|
|
39
|
+
self.evidence_dir.mkdir(parents=True, exist_ok=True)
|
|
40
|
+
round_evidence_dir = self.evidence_dir / f"round_{round_num:02d}"
|
|
41
|
+
round_evidence_dir.mkdir(exist_ok=True)
|
|
42
|
+
|
|
43
|
+
evidence = {
|
|
44
|
+
"round": round_num,
|
|
45
|
+
"timestamp": datetime.now().isoformat(),
|
|
46
|
+
"files": {}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# 1. 复制编译日志
|
|
50
|
+
if log_file and log_file.exists():
|
|
51
|
+
dest = round_evidence_dir / "compile.log"
|
|
52
|
+
shutil.copy2(log_file, dest)
|
|
53
|
+
evidence["files"]["log"] = str(dest)
|
|
54
|
+
evidence["log_summary"] = self._summarize_log(log_file)
|
|
55
|
+
|
|
56
|
+
# 2. 复制页图目录
|
|
57
|
+
if pages_dir and pages_dir.exists():
|
|
58
|
+
dest_pages = round_evidence_dir / "pages"
|
|
59
|
+
if dest_pages.exists():
|
|
60
|
+
shutil.rmtree(dest_pages)
|
|
61
|
+
shutil.copytree(pages_dir, dest_pages)
|
|
62
|
+
evidence["files"]["pages_dir"] = str(dest_pages)
|
|
63
|
+
evidence["page_count"] = len(list(dest_pages.glob("page_*.png")))
|
|
64
|
+
|
|
65
|
+
# 3. 复制诊断报告
|
|
66
|
+
if diagnostic_report and diagnostic_report.exists():
|
|
67
|
+
dest = round_evidence_dir / diagnostic_report.name
|
|
68
|
+
shutil.copy2(diagnostic_report, dest)
|
|
69
|
+
evidence["files"]["diagnostic_report"] = str(dest)
|
|
70
|
+
|
|
71
|
+
# 4. 记录修改的文件及 diff
|
|
72
|
+
if modified_files:
|
|
73
|
+
evidence["modified_files"] = [str(f) for f in modified_files]
|
|
74
|
+
evidence["diffs"] = self._collect_diffs(modified_files, round_evidence_dir)
|
|
75
|
+
|
|
76
|
+
# 5. 复制状态文件快照
|
|
77
|
+
if state_file and state_file.exists():
|
|
78
|
+
dest = round_evidence_dir / "state_snapshot.json"
|
|
79
|
+
shutil.copy2(state_file, dest)
|
|
80
|
+
evidence["files"]["state_snapshot"] = str(dest)
|
|
81
|
+
|
|
82
|
+
# 6. 生成证据清单
|
|
83
|
+
manifest_path = round_evidence_dir / "manifest.json"
|
|
84
|
+
with open(manifest_path, "w", encoding="utf-8") as f:
|
|
85
|
+
json.dump(evidence, f, indent=2, ensure_ascii=False)
|
|
86
|
+
|
|
87
|
+
return evidence
|
|
88
|
+
|
|
89
|
+
def _summarize_log(self, log_path: Path) -> Dict[str, int]:
|
|
90
|
+
"""快速提取日志摘要"""
|
|
91
|
+
summary = {
|
|
92
|
+
"errors": 0,
|
|
93
|
+
"warnings": 0,
|
|
94
|
+
"overfull_hbox": 0,
|
|
95
|
+
"underfull_hbox": 0
|
|
96
|
+
}
|
|
97
|
+
try:
|
|
98
|
+
content = log_path.read_text(encoding="utf-8", errors="ignore")
|
|
99
|
+
summary["errors"] = content.count("!")
|
|
100
|
+
summary["warnings"] = content.count("Warning:")
|
|
101
|
+
summary["overfull_hbox"] = content.count("Overfull \\hbox")
|
|
102
|
+
summary["underfull_hbox"] = content.count("Underfull \\hbox")
|
|
103
|
+
except Exception:
|
|
104
|
+
pass
|
|
105
|
+
return summary
|
|
106
|
+
|
|
107
|
+
def _collect_diffs(self, modified_files: List[Path], dest_dir: Path) -> Dict[str, str]:
|
|
108
|
+
"""收集文件的 git diff 或简单前后对比(需要备份支持)"""
|
|
109
|
+
diffs = {}
|
|
110
|
+
backups_dir = self.data_dir / "backups"
|
|
111
|
+
|
|
112
|
+
for file_path in modified_files:
|
|
113
|
+
# 尝试找到最近的备份
|
|
114
|
+
backup_pattern = f"{file_path.name}_*"
|
|
115
|
+
backups = sorted(backups_dir.glob(backup_pattern), reverse=True)
|
|
116
|
+
if backups:
|
|
117
|
+
# 生成 diff
|
|
118
|
+
try:
|
|
119
|
+
result = subprocess.run(
|
|
120
|
+
["diff", "-u", str(backups[0]), str(file_path)],
|
|
121
|
+
capture_output=True,
|
|
122
|
+
text=True
|
|
123
|
+
)
|
|
124
|
+
diffs[str(file_path)] = result.stdout
|
|
125
|
+
except Exception:
|
|
126
|
+
diffs[str(file_path)] = f"# Unable to generate diff for {file_path}"
|
|
127
|
+
else:
|
|
128
|
+
diffs[str(file_path)] = f"# No backup found for {file_path}"
|
|
129
|
+
|
|
130
|
+
# 保存 diff 文件
|
|
131
|
+
diff_file = dest_dir / "changes.diff"
|
|
132
|
+
with open(diff_file, "w", encoding="utf-8") as f:
|
|
133
|
+
for path, diff_content in diffs.items():
|
|
134
|
+
f.write(f"--- {path}\n")
|
|
135
|
+
f.write(diff_content)
|
|
136
|
+
f.write("\n\n")
|
|
137
|
+
|
|
138
|
+
return diffs
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def main():
|
|
142
|
+
parser = argparse.ArgumentParser(description="收集 PaperFit 迭代证据")
|
|
143
|
+
parser.add_argument("--round", "-r", type=int, required=True, help="迭代轮次")
|
|
144
|
+
parser.add_argument("--log", help="编译日志路径")
|
|
145
|
+
parser.add_argument("--pages", help="页图目录")
|
|
146
|
+
parser.add_argument("--report", help="诊断报告路径")
|
|
147
|
+
parser.add_argument("--modified", nargs="+", help="修改的文件列表")
|
|
148
|
+
parser.add_argument("--state", help="状态文件路径")
|
|
149
|
+
parser.add_argument("--output", "-o", help="输出目录", default="data/evidence")
|
|
150
|
+
|
|
151
|
+
args = parser.parse_args()
|
|
152
|
+
|
|
153
|
+
collector = EvidenceCollector()
|
|
154
|
+
evidence = collector.collect(
|
|
155
|
+
round_num=args.round,
|
|
156
|
+
log_file=Path(args.log) if args.log else None,
|
|
157
|
+
pages_dir=Path(args.pages) if args.pages else None,
|
|
158
|
+
diagnostic_report=Path(args.report) if args.report else None,
|
|
159
|
+
modified_files=[Path(f) for f in args.modified] if args.modified else None,
|
|
160
|
+
state_file=Path(args.state) if args.state else None
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
print(json.dumps(evidence, indent=2, ensure_ascii=False))
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
if __name__ == "__main__":
|
|
167
|
+
main()
|