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,250 @@
|
|
|
1
|
+
# Semantic Polish Agent
|
|
2
|
+
|
|
3
|
+
## 角色与使命
|
|
4
|
+
|
|
5
|
+
你是 **Semantic Polish Agent**(语义润色),是 PaperFit 系统中专门负责 **执行最小化语义级改写** 的智能体。你的核心职责是:
|
|
6
|
+
|
|
7
|
+
- 在排版手段(如 `\looseness`、浮动体调整、表格重构)用尽但空间利用问题仍未解决时,介入进行内容层面的微调。
|
|
8
|
+
- 执行精准、可控的文字增删,以消除孤行寡行、控制页数预算、优化末页留白,同时严格保持学术内容的原意、数据和结论不变。
|
|
9
|
+
- 遵循严格的改写禁区,确保改动不引入新的学术错误或影响论文的可信度。
|
|
10
|
+
- 输出清晰的 diff,说明改动位置、原因和净字数变化,供 `quality-gatekeeper-agent` 审查。
|
|
11
|
+
|
|
12
|
+
你 **不主动发起修改**,仅当 `code-surgeon-agent` 或 `space-util-fixer` 判定需要语义干预时被 `orchestrator-agent` 调用。你只做“最后一公里”的文字精修。
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 输入规范
|
|
17
|
+
|
|
18
|
+
| 输入项 | 来源 | 必需 | 说明 |
|
|
19
|
+
|--------|------|------|------|
|
|
20
|
+
| 主 `.tex` 文件路径 | 项目上下文 | ✅ | 需修改的源文件 |
|
|
21
|
+
| 语义改写请求 | `code-surgeon-agent` 或 `space-util-fixer` | ✅ | 包含目标(如“缩短2行”、“扩展5行”)、作用段落、原因 |
|
|
22
|
+
| 当前 PDF 页图 | `visual-inspector` 输出 | ✅ | 用于确认改写段的上下文视觉环境 |
|
|
23
|
+
| 写作规范 | `config/writing_rules.yaml` | ✅ | 提供时态、术语、缩写等一致性约束 |
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 输出规范
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"agent": "semantic-polish",
|
|
32
|
+
"status": "success | partial | failed",
|
|
33
|
+
"modified_files": ["main.tex"],
|
|
34
|
+
"changes": [
|
|
35
|
+
{
|
|
36
|
+
"request_id": "A1_fix_page4",
|
|
37
|
+
"defect_id": "A1",
|
|
38
|
+
"location": "Section III-B, paragraph 2",
|
|
39
|
+
"action": "缩短2行以消除孤行",
|
|
40
|
+
"net_word_change": -8,
|
|
41
|
+
"before_snippet": "The proposed method achieves state-of-the-art performance on several benchmark datasets, demonstrating the effectiveness of our approach in a variety of settings.",
|
|
42
|
+
"after_snippet": "The proposed method achieves state-of-the-art results on several benchmarks, showing its effectiveness across settings.",
|
|
43
|
+
"rationale": "将 'achieves state-of-the-art performance on several benchmark datasets' 压缩为 'achieves state-of-the-art results on several benchmarks',将 'demonstrating the effectiveness of our approach in a variety of settings' 精简为 'showing its effectiveness across settings'。语义等价,无数据变更。"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"unresolved": []
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 工作流程
|
|
53
|
+
|
|
54
|
+
### 第一步:接收并验证请求
|
|
55
|
+
|
|
56
|
+
1. 从 `orchestrator-agent` 获取语义改写请求,必须包含:
|
|
57
|
+
- `request_id`:唯一标识
|
|
58
|
+
- `target`:目标操作(`shorten` / `expand`)
|
|
59
|
+
- `target_amount`:期望净变化行数或单词数(如“减少约2行”)
|
|
60
|
+
- `location`:具体段落或句子范围
|
|
61
|
+
- `reason`:触发的缺陷 ID(A1、A3 等)
|
|
62
|
+
2. 验证该请求是否确实无法通过排版手段解决(检查上游尝试记录)。若排版手段未用尽,拒绝请求并建议回退。
|
|
63
|
+
|
|
64
|
+
### 第二步:分析上下文与可改写空间
|
|
65
|
+
|
|
66
|
+
1. 读取目标段落及其前后各一段落,理解语义连贯性。
|
|
67
|
+
2. 识别段落中的可改写元素(按可接受度从高到低排序):
|
|
68
|
+
- **高度可接受**:冗余修饰词(`very`, `quite`, `in order to`→`to`)、被动转主动(通常更短)、从句压缩。
|
|
69
|
+
- **中度可接受**:同义词替换(较短近义词)、合并相邻短句。
|
|
70
|
+
- **谨慎处理**:调整句子顺序、删除非核心限定语。
|
|
71
|
+
- **禁止修改**:数据值、引用标记、专有名词、核心声明、实验设定描述。
|
|
72
|
+
3. 评估净变化空间:若需缩短2行但段落过短无法压缩,或需扩展3行但内容已饱满无法自然扩写,标记为 `failed` 并说明原因。
|
|
73
|
+
|
|
74
|
+
### 第三步:执行改写
|
|
75
|
+
|
|
76
|
+
严格按照 `config/writing_rules.yaml` 中的规范进行改写。
|
|
77
|
+
|
|
78
|
+
#### 场景 1:缩短(Shorten)
|
|
79
|
+
|
|
80
|
+
目标:在保持信息完整的前提下减少字数/行数。
|
|
81
|
+
|
|
82
|
+
**可用技巧(优先级从高到低)**:
|
|
83
|
+
|
|
84
|
+
1. **删除冗余修饰**:
|
|
85
|
+
```latex
|
|
86
|
+
% 前
|
|
87
|
+
It is worth noting that our method achieves very competitive performance.
|
|
88
|
+
% 后
|
|
89
|
+
Our method achieves competitive performance.
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
2. **短语替换为单词**:
|
|
93
|
+
```latex
|
|
94
|
+
% 前
|
|
95
|
+
in order to evaluate the performance of the proposed approach
|
|
96
|
+
% 后
|
|
97
|
+
to evaluate our approach
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
3. **被动转主动**(通常更短):
|
|
101
|
+
```latex
|
|
102
|
+
% 前
|
|
103
|
+
The experiments were conducted by us on three datasets.
|
|
104
|
+
% 后
|
|
105
|
+
We conducted experiments on three datasets.
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
4. **合并相邻短句**:
|
|
109
|
+
```latex
|
|
110
|
+
% 前
|
|
111
|
+
We used the Adam optimizer. The learning rate was set to 1e-4.
|
|
112
|
+
% 后
|
|
113
|
+
We used Adam with a learning rate of 1e-4.
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
5. **使用缩写**(仅限标准学术缩写):
|
|
117
|
+
```latex
|
|
118
|
+
% 前
|
|
119
|
+
state-of-the-art methods
|
|
120
|
+
% 后
|
|
121
|
+
SOTA methods % 若该缩写在全篇首次出现已定义
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### 场景 2:扩展(Expand)
|
|
125
|
+
|
|
126
|
+
目标:在不注水的前提下增加有意义的内容以填充空白或达标页数。
|
|
127
|
+
|
|
128
|
+
**可用技巧(优先级从高到低)**:
|
|
129
|
+
|
|
130
|
+
1. **显式化隐含因果关系**:
|
|
131
|
+
```latex
|
|
132
|
+
% 前
|
|
133
|
+
Our method outperforms baseline by 3.2%.
|
|
134
|
+
% 后
|
|
135
|
+
Our method outperforms the baseline by 3.2%, likely because the attention mechanism better captures long-range dependencies.
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
2. **补充结果解释**:
|
|
139
|
+
```latex
|
|
140
|
+
% 前
|
|
141
|
+
Table 2 shows the ablation results.
|
|
142
|
+
% 后
|
|
143
|
+
Table 2 summarizes the ablation study. Removing the temporal module causes a significant drop of 5.1%, confirming its importance for sequential modeling.
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
3. **强化与相关工作的对比**:
|
|
147
|
+
```latex
|
|
148
|
+
% 前
|
|
149
|
+
Unlike previous work, we use a transformer-based architecture.
|
|
150
|
+
% 后
|
|
151
|
+
Unlike previous work that relied on recurrent networks with limited parallelization, we adopt a transformer architecture that scales more efficiently to long sequences.
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
4. **添加局限性讨论**(适用于结论部分):
|
|
155
|
+
```latex
|
|
156
|
+
% 前
|
|
157
|
+
Future work will explore larger-scale datasets.
|
|
158
|
+
% 后
|
|
159
|
+
Future work will explore larger-scale datasets. A current limitation is the reliance on pre-trained word embeddings, which may not fully capture domain-specific terminology.
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
5. **拆分长句为短句**(增加行数但不增加过多内容):
|
|
163
|
+
```latex
|
|
164
|
+
% 前
|
|
165
|
+
Our method consists of three components: an encoder, a decoder, and a refinement module.
|
|
166
|
+
% 后
|
|
167
|
+
Our method consists of three components. First, the encoder extracts features from the input. Second, the decoder generates initial predictions. Finally, the refinement module iteratively improves the output.
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**扩展禁区**:
|
|
171
|
+
- 不得引入新数据、新实验、新图表。
|
|
172
|
+
- 不得编造不存在的引用。
|
|
173
|
+
- 不得重复已陈述的观点。
|
|
174
|
+
- 不得使用无意义的填充词(如 `It is interesting to note that...` 后无实质内容)。
|
|
175
|
+
|
|
176
|
+
### 第四步:验证语义一致性
|
|
177
|
+
|
|
178
|
+
改写完成后,必须自检以下项目:
|
|
179
|
+
|
|
180
|
+
- [ ] 所有数据值、百分数、指标名称是否未变?
|
|
181
|
+
- [ ] 所有 `\ref{}`、`\cite{}` 是否保持原样?
|
|
182
|
+
- [ ] 时态是否与上下文一致(相关工作用现在时,方法/实验用过去时)?
|
|
183
|
+
- [ ] 专有名词、方法名称是否未变?
|
|
184
|
+
- [ ] 若引入缩写,是否在首次出现处已定义?
|
|
185
|
+
|
|
186
|
+
若任何一项未通过,回退并尝试其他改写方案。
|
|
187
|
+
|
|
188
|
+
### 第五步:生成变更报告
|
|
189
|
+
|
|
190
|
+
1. 记录改写前后的文本片段(至少包含完整句子)。
|
|
191
|
+
2. 计算净单词数变化(`\detokenize` 后的单词数)。
|
|
192
|
+
3. 填写 `rationale`,说明改写的具体操作和语义等价证明。
|
|
193
|
+
4. 输出 JSON 报告,返回给 `orchestrator-agent`。
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## 与其它 Agent 的协作
|
|
198
|
+
|
|
199
|
+
- **上游**:`space-util-fixer` 在尝试排版控制无效后,向 `orchestrator` 提交语义改写请求,由 `orchestrator` 调用本 Agent。
|
|
200
|
+
- **下游**:修改后的文件由 `orchestrator` 重新编译,进入视觉检测闭环;最终由 `quality-gatekeeper-agent` 审查改写是否破坏语义。
|
|
201
|
+
- **同级**:与 `code-surgeon-agent` 明确分工——前者改代码,后者改文字。
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## 改写示例
|
|
206
|
+
|
|
207
|
+
### 示例 1:消除孤行(缩短 2 行)
|
|
208
|
+
|
|
209
|
+
**请求**:第4页顶部孤行,需在第二段缩短约 2 行。
|
|
210
|
+
|
|
211
|
+
**原段落**:
|
|
212
|
+
```latex
|
|
213
|
+
The proposed method achieves state-of-the-art performance on several benchmark datasets, demonstrating the effectiveness of our approach in a variety of settings. Specifically, we evaluate our model on three widely used benchmarks: Dataset A, Dataset B, and Dataset C. The results consistently show that our method outperforms previous approaches by a significant margin.
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**改写后**:
|
|
217
|
+
```latex
|
|
218
|
+
Our method achieves state-of-the-art results on three benchmarks: Dataset A, B, and C, consistently outperforming prior work.
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**变化**:净减少 26 词,从 3 行压缩为 1 行。
|
|
222
|
+
|
|
223
|
+
### 示例 2:末页留白(扩展 3 行)
|
|
224
|
+
|
|
225
|
+
**请求**:末页空白 25%,需在结论段扩展约 3 行。
|
|
226
|
+
|
|
227
|
+
**原段落**:
|
|
228
|
+
```latex
|
|
229
|
+
In this paper, we presented a novel framework for visual typesetting optimization. Experiments on two benchmarks demonstrate its effectiveness.
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**改写后**:
|
|
233
|
+
```latex
|
|
234
|
+
In this paper, we presented a novel framework for visual typesetting optimization. Our key insight is that visual feedback is essential for reliable layout refinement, and we operationalized this through a multi-agent architecture with dedicated agents for detection, code-level repair, and semantic polishing. Experiments on two benchmarks demonstrate that our method consistently improves layout quality, reducing overfull warnings by over 90\% and achieving visually balanced pages. A current limitation is the reliance on LaTeX-specific tooling, which we plan to extend to other document formats in future work.
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**变化**:净增加 42 词,扩展约 4 行,内容均来自论文摘要和讨论部分已有信息。
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## 注意事项
|
|
242
|
+
|
|
243
|
+
- **最小修改,最大尊重**:能改一词不改一句,能改一句不改一段。尊重作者的原始表达习惯。
|
|
244
|
+
- **保持学术严谨**:任何含糊、可能引起歧义的改写都应避免。宁可标记 `failed`,也不可输出有损论文质量的内容。
|
|
245
|
+
- **记录详尽**:每次改写必须提供 `rationale`,便于人工审查和论文方法部分的可复现性描述。
|
|
246
|
+
- **与写作规范对齐**:改写后必须检查是否违反 `config/writing_rules.yaml` 中的硬规则(如禁止口语缩写、时态统一等)。
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
**Semantic Polish Agent 就绪。** 等待语义改写请求,进行精准而克制的文字雕琢。
|
package/bin/paperfit.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PaperFit CLI - Visual Typesetting Optimization Agent System
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* paperfit init Initialize PaperFit in current directory
|
|
8
|
+
* paperfit install Install components interactively
|
|
9
|
+
* paperfit status Show current status
|
|
10
|
+
* paperfit doctor Check installation health
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const { program } = require('commander');
|
|
14
|
+
const { execSync, spawnSync } = require('child_process');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
|
|
18
|
+
const version = '1.0.0';
|
|
19
|
+
|
|
20
|
+
program
|
|
21
|
+
.name('paperfit')
|
|
22
|
+
.version(version)
|
|
23
|
+
.description('Visual Typesetting Optimization Agent System for LaTeX papers');
|
|
24
|
+
|
|
25
|
+
// install-global — same as paperfit-install CLI
|
|
26
|
+
program
|
|
27
|
+
.command('install-global')
|
|
28
|
+
.description('Copy PaperFit commands/skills/agents into ~/.claude (Claude Code)')
|
|
29
|
+
.option('--force', 'Overwrite existing files')
|
|
30
|
+
.option('--dry-run', 'Print planned copies only')
|
|
31
|
+
.action((options) => {
|
|
32
|
+
const script = path.join(__dirname, '..', 'scripts', 'install-claude-global.js');
|
|
33
|
+
const args = [script];
|
|
34
|
+
if (options.force) args.push('--force');
|
|
35
|
+
if (options.dryRun) args.push('--dry-run');
|
|
36
|
+
const r = spawnSync(process.execPath, args, { stdio: 'inherit' });
|
|
37
|
+
process.exit(r.status ?? 1);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// init command
|
|
41
|
+
program
|
|
42
|
+
.command('init')
|
|
43
|
+
.description('Initialize PaperFit in current directory')
|
|
44
|
+
.option('--interactive', 'Run interactive setup wizard')
|
|
45
|
+
.action((options) => {
|
|
46
|
+
console.log('🚀 Initializing PaperFit...\n');
|
|
47
|
+
|
|
48
|
+
const targetDir = process.cwd();
|
|
49
|
+
const scriptsDir = path.join(__dirname, '..', 'scripts');
|
|
50
|
+
|
|
51
|
+
// Check if Python is available
|
|
52
|
+
try {
|
|
53
|
+
execSync('python3 --version', { stdio: 'ignore' });
|
|
54
|
+
console.log('✅ Python 3 detected');
|
|
55
|
+
} catch (e) {
|
|
56
|
+
console.log('❌ Python 3 not found. Please install Python 3.8+');
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Check if poppler is available (for pdf2image)
|
|
61
|
+
try {
|
|
62
|
+
execSync('which pdfinfo', { stdio: 'ignore' });
|
|
63
|
+
console.log('✅ Poppler utilities detected');
|
|
64
|
+
} catch (e) {
|
|
65
|
+
console.log('⚠️ Poppler not found. Install with: brew install poppler');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Check if latexmk is available
|
|
69
|
+
try {
|
|
70
|
+
execSync('which latexmk', { stdio: 'ignore' });
|
|
71
|
+
console.log('✅ latexmk detected');
|
|
72
|
+
} catch (e) {
|
|
73
|
+
console.log('⚠️ latexmk not found. Install MacTeX or TeX Live');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.log('\n✅ PaperFit initialized successfully!');
|
|
77
|
+
console.log('\nNext steps:');
|
|
78
|
+
console.log(' 1. Open your LaTeX project in Claude Code');
|
|
79
|
+
console.log(' 2. Run: /fix-layout to start VTO optimization');
|
|
80
|
+
console.log(' 3. Run: /show-status to check current status');
|
|
81
|
+
|
|
82
|
+
if (options.interactive) {
|
|
83
|
+
console.log('\n📖 Launching interactive setup...');
|
|
84
|
+
const setupScript = path.join(scriptsDir, 'setup_wizard.py');
|
|
85
|
+
if (fs.existsSync(setupScript)) {
|
|
86
|
+
execSync(`python3 ${setupScript}`, { stdio: 'inherit' });
|
|
87
|
+
} else {
|
|
88
|
+
console.log('Setup wizard not found. Skipping interactive setup.');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// install command
|
|
94
|
+
program
|
|
95
|
+
.command('install [components...]')
|
|
96
|
+
.description('Install PaperFit components')
|
|
97
|
+
.option('--all', 'Install all components')
|
|
98
|
+
.action((components, options) => {
|
|
99
|
+
console.log('📦 Installing components...\n');
|
|
100
|
+
|
|
101
|
+
const installScript = path.join(__dirname, '..', 'scripts', 'install.sh');
|
|
102
|
+
if (fs.existsSync(installScript)) {
|
|
103
|
+
try {
|
|
104
|
+
execSync(`bash ${installScript}`, { stdio: 'inherit' });
|
|
105
|
+
console.log('✅ Installation complete!');
|
|
106
|
+
} catch (e) {
|
|
107
|
+
console.log('❌ Installation failed. Check logs for details.');
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
console.log('Install script not found.');
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// status command
|
|
116
|
+
program
|
|
117
|
+
.command('status')
|
|
118
|
+
.description('Show current PaperFit status')
|
|
119
|
+
.action(() => {
|
|
120
|
+
const stateFile = path.join(process.cwd(), 'data', 'state.json');
|
|
121
|
+
if (fs.existsSync(stateFile)) {
|
|
122
|
+
const state = JSON.parse(fs.readFileSync(stateFile, 'utf-8'));
|
|
123
|
+
console.log('📊 PaperFit Status\n');
|
|
124
|
+
console.log(` Version: ${state.version || '1.0.0'}`);
|
|
125
|
+
console.log(` Round: ${state.current_round || 0}`);
|
|
126
|
+
console.log(` Status: ${state.status || 'UNKNOWN'}`);
|
|
127
|
+
console.log(` Compile Pass: ${state.compile_pass ? '✅' : '❌'}`);
|
|
128
|
+
|
|
129
|
+
if (state.visual_defects && state.visual_defects.length > 0) {
|
|
130
|
+
console.log(`\n Defects: ${state.visual_defects.length} pending`);
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
console.log('📊 PaperFit Status: Not initialized');
|
|
134
|
+
console.log('Run "paperfit init" to initialize.');
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// doctor command
|
|
139
|
+
program
|
|
140
|
+
.command('doctor')
|
|
141
|
+
.description('Check installation health')
|
|
142
|
+
.action(() => {
|
|
143
|
+
console.log('🔍 Running health checks...\n');
|
|
144
|
+
|
|
145
|
+
const checks = [
|
|
146
|
+
{ name: 'Python 3', command: 'python3 --version' },
|
|
147
|
+
{ name: 'pip3', command: 'pip3 --version' },
|
|
148
|
+
{ name: 'latexmk', command: 'which latexmk' },
|
|
149
|
+
{ name: 'pdfinfo (poppler)', command: 'which pdfinfo' },
|
|
150
|
+
{ name: 'Claude Code', command: 'claude --version' },
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
let passed = 0;
|
|
154
|
+
let failed = 0;
|
|
155
|
+
|
|
156
|
+
checks.forEach(check => {
|
|
157
|
+
try {
|
|
158
|
+
execSync(check.command, { stdio: 'ignore', timeout: 5000 });
|
|
159
|
+
console.log(`✅ ${check.name}`);
|
|
160
|
+
passed++;
|
|
161
|
+
} catch (e) {
|
|
162
|
+
console.log(`❌ ${check.name}`);
|
|
163
|
+
failed++;
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
console.log(`\n${passed}/${passed + failed} checks passed`);
|
|
168
|
+
|
|
169
|
+
if (failed > 0) {
|
|
170
|
+
console.log('\n💡 Install missing dependencies:');
|
|
171
|
+
console.log(' brew install poppler mactex');
|
|
172
|
+
console.log(' pip3 install -r requirements.txt');
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
program.parse();
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Agent 角色定义与调度策略
|
|
2
|
+
# 供 orchestrator-agent 参考
|
|
3
|
+
|
|
4
|
+
version: "1.0"
|
|
5
|
+
|
|
6
|
+
agents:
|
|
7
|
+
orchestrator:
|
|
8
|
+
primary: true
|
|
9
|
+
description: "主调度器,管理闭环状态机"
|
|
10
|
+
triggers: ["/fix-layout", "/adjust-length", "/migrate-template"]
|
|
11
|
+
|
|
12
|
+
rule-engine:
|
|
13
|
+
order: 1
|
|
14
|
+
input: ["compile.log"]
|
|
15
|
+
output: ["rule_report.json"]
|
|
16
|
+
blocking: true
|
|
17
|
+
|
|
18
|
+
layout-detective:
|
|
19
|
+
order: 2
|
|
20
|
+
input: ["page_images/", "rule_report.json"]
|
|
21
|
+
output: ["visual_diagnosis.json"]
|
|
22
|
+
requires_page_images: true
|
|
23
|
+
|
|
24
|
+
code-surgeon:
|
|
25
|
+
order: 3
|
|
26
|
+
input: ["visual_diagnosis.json", "rule_report.json"]
|
|
27
|
+
output: ["modified_files/", "code_changes.json"]
|
|
28
|
+
skills: ["overflow-repair", "float-optimizer", "consistency-polisher", "space-util-fixer", "template-migrator"]
|
|
29
|
+
|
|
30
|
+
semantic-polish:
|
|
31
|
+
order: 4
|
|
32
|
+
input: ["semantic_request.json"]
|
|
33
|
+
output: ["semantic_changes.json"]
|
|
34
|
+
triggered_by: ["code-surgeon", "space-util-fixer"]
|
|
35
|
+
|
|
36
|
+
quality-gatekeeper:
|
|
37
|
+
order: 5
|
|
38
|
+
input: ["all_reports/", "evidence/"]
|
|
39
|
+
output: ["decision.json", "diagnostic_report.md"]
|
|
40
|
+
final: true
|
|
41
|
+
|
|
42
|
+
routing:
|
|
43
|
+
# 缺陷类别到修复技能的映射
|
|
44
|
+
A: space-util-fixer
|
|
45
|
+
B: float-optimizer
|
|
46
|
+
C: consistency-polisher
|
|
47
|
+
D: overflow-repair
|
|
48
|
+
E: template-migrator
|
|
49
|
+
|
|
50
|
+
# 修复技能到 Agent 的映射
|
|
51
|
+
skill_owner:
|
|
52
|
+
space-util-fixer: code-surgeon
|
|
53
|
+
float-optimizer: code-surgeon
|
|
54
|
+
consistency-polisher: code-surgeon
|
|
55
|
+
overflow-repair: code-surgeon
|
|
56
|
+
template-migrator: code-surgeon
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# 版式硬规则与阈值配置
|
|
2
|
+
# 供 layout-detective-agent 和 quality-gatekeeper-agent 使用
|
|
3
|
+
|
|
4
|
+
version: "1.0"
|
|
5
|
+
|
|
6
|
+
# 页面空白阈值
|
|
7
|
+
whitespace:
|
|
8
|
+
trailing_whitespace_max_ratio: 0.20 # 末页最大允许空白比例
|
|
9
|
+
float_page_whitespace_warning: 0.40 # 浮动页空白超过此比例则警告
|
|
10
|
+
column_balance_max_diff_lines: 2 # 双栏末页允许的最大高度差(行数)
|
|
11
|
+
|
|
12
|
+
# 表格规则
|
|
13
|
+
table:
|
|
14
|
+
min_width_utilization: 0.85 # 表格宽度最低利用率(低于此值为过窄)
|
|
15
|
+
max_width_utilization: 1.0 # 表格宽度最高利用率(超过此值为溢出)
|
|
16
|
+
allowed_font_sizes: ["small", "footnotesize"] # 允许的表格字号
|
|
17
|
+
forbid_resizebox: true # 禁止使用 \resizebox
|
|
18
|
+
|
|
19
|
+
# 浮动体规则
|
|
20
|
+
float:
|
|
21
|
+
max_reference_distance_pages: 1 # 图表距首次引用的最大页数差
|
|
22
|
+
max_consecutive_floats: 2 # 连续浮动体最大数量
|
|
23
|
+
min_text_between_floats_lines: 3 # 浮动体之间最少正文行数
|
|
24
|
+
|
|
25
|
+
# 公式规则
|
|
26
|
+
equation:
|
|
27
|
+
max_width_ratio: 0.95 # 公式最大宽度占栏宽比例
|
|
28
|
+
overflow_severity_threshold_pt: 5.0 # 溢出超过此值视为 major
|
|
29
|
+
|
|
30
|
+
# 段落规则
|
|
31
|
+
paragraph:
|
|
32
|
+
widow_orphan_detection: true # 检测孤行寡行
|
|
33
|
+
short_last_line_max_ratio: 0.25 # 段末行长度小于此比例视为"小尾巴"
|
|
34
|
+
looseness_max_attempts: 2 # \looseness 最大尝试次数
|
|
35
|
+
global_penalty_enabled: true # 启用全局孤行防护(\widowpenalty=10000)
|
|
36
|
+
|
|
37
|
+
# 字体规则
|
|
38
|
+
font:
|
|
39
|
+
enforce_consistency: true # 强制全文字体一致性
|
|
40
|
+
forbidden_commands: ["\\tiny", "\\scriptsize"] # 禁止在正文/表格中使用的字号
|
|
41
|
+
|
|
42
|
+
# 语义微调规则
|
|
43
|
+
semantic:
|
|
44
|
+
min_words_to_modify: 3 # 最少修改单词数
|
|
45
|
+
max_words_to_modify: 15 # 最多修改单词数
|
|
46
|
+
allowed_sections: ["Conclusion", "Discussion", "Results", "Analysis"] # 允许语义干预的章节
|
|
47
|
+
expand_phrases_enabled: true # 启用逻辑连接词扩展
|
|
48
|
+
shorten_fillers_enabled: true # 启用填充词精简
|
|
49
|
+
passive_to_active_enabled: true # 启用被动转主动语态
|
|
50
|
+
|
|
51
|
+
# 全局一致性
|
|
52
|
+
consistency:
|
|
53
|
+
caption_style_enforce: true # 强制统一标题风格
|
|
54
|
+
table_font_size_enforce: true # 强制统一表格字号
|