psyclaw 0.28.0 → 0.28.2

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.
Files changed (167) hide show
  1. package/README.md +5 -5
  2. package/agents/recommended/catalog.json +99 -0
  3. package/dist/apps/panel/index.html +5 -5
  4. package/dist/src/adapters/pi/extension.js +164 -18
  5. package/dist/src/adapters/pi/extension.js.map +1 -1
  6. package/dist/src/adapters/pi/rpc.d.ts +2 -0
  7. package/dist/src/adapters/pi/rpc.js +9 -2
  8. package/dist/src/adapters/pi/rpc.js.map +1 -1
  9. package/dist/src/agents/recommended-personas.d.ts +42 -0
  10. package/dist/src/agents/recommended-personas.js +135 -0
  11. package/dist/src/agents/recommended-personas.js.map +1 -0
  12. package/dist/src/ars/mode-editor.d.ts +20 -0
  13. package/dist/src/ars/mode-editor.js +57 -0
  14. package/dist/src/ars/mode-editor.js.map +1 -0
  15. package/dist/src/ars/profile.d.ts +4 -1
  16. package/dist/src/ars/profile.js +23 -6
  17. package/dist/src/ars/profile.js.map +1 -1
  18. package/dist/src/cli.js +6 -3
  19. package/dist/src/cli.js.map +1 -1
  20. package/dist/src/creation/contracts.d.ts +3 -0
  21. package/dist/src/creation/service.js +17 -5
  22. package/dist/src/creation/service.js.map +1 -1
  23. package/dist/src/index.d.ts +1 -0
  24. package/dist/src/index.js +1 -0
  25. package/dist/src/index.js.map +1 -1
  26. package/dist/src/orchestration/bundled-personas.d.ts +16 -0
  27. package/dist/src/orchestration/bundled-personas.js +101 -0
  28. package/dist/src/orchestration/bundled-personas.js.map +1 -0
  29. package/dist/src/orchestration/effects.d.ts +8 -0
  30. package/dist/src/orchestration/effects.js +39 -0
  31. package/dist/src/orchestration/effects.js.map +1 -0
  32. package/dist/src/orchestration/personas.d.ts +2 -1
  33. package/dist/src/orchestration/personas.js +20 -7
  34. package/dist/src/orchestration/personas.js.map +1 -1
  35. package/dist/src/orchestration/pi-executor.d.ts +9 -5
  36. package/dist/src/orchestration/pi-executor.js +55 -22
  37. package/dist/src/orchestration/pi-executor.js.map +1 -1
  38. package/dist/src/orchestration/research-agents.d.ts +3 -7
  39. package/dist/src/orchestration/research-agents.js +5 -69
  40. package/dist/src/orchestration/research-agents.js.map +1 -1
  41. package/dist/src/panel/server.js +6 -0
  42. package/dist/src/panel/server.js.map +1 -1
  43. package/dist/src/style/cli-ui.d.ts +14 -0
  44. package/dist/src/style/cli-ui.js +45 -0
  45. package/dist/src/style/cli-ui.js.map +1 -1
  46. package/dist/src/tui/skill-manager.js +1 -1
  47. package/dist/src/tui/skill-manager.js.map +1 -1
  48. package/dist/src/updates/update.js +9 -3
  49. package/dist/src/updates/update.js.map +1 -1
  50. package/package.json +11 -3
  51. package/vendor/academic-paper-skills/LICENSE +21 -0
  52. package/vendor/academic-paper-skills/NOTICE.md +7 -0
  53. package/vendor/academic-paper-skills/PSYCLAW_SOURCE.json +14 -0
  54. package/vendor/academic-paper-skills/academic-paper-composer/SKILL.md +840 -0
  55. package/vendor/academic-paper-skills/academic-paper-composer/references/section_guides.md +675 -0
  56. package/vendor/academic-paper-skills/academic-paper-composer/references/writing_standards.md +629 -0
  57. package/vendor/academic-paper-skills/academic-paper-composer/scripts/chapter_quality_check.py +470 -0
  58. package/vendor/academic-paper-skills/academic-paper-composer/scripts/final_evaluation.py +550 -0
  59. package/vendor/academic-paper-skills/academic-paper-strategist/SKILL.md +670 -0
  60. package/vendor/academic-paper-skills/academic-paper-strategist/references/quality_standards.md +336 -0
  61. package/vendor/academic-paper-skills/academic-paper-strategist/references/search_strategy.md +459 -0
  62. package/vendor/academic-paper-skills/academic-paper-strategist/scripts/evaluate_samples.py +300 -0
  63. package/vendor/academic-paper-skills/academic-paper-strategist/scripts/gap_analysis.py +399 -0
  64. package/vendor/ars/pi/wrapper.js +9 -0
  65. package/vendor/nature-skills/LICENSE +201 -0
  66. package/vendor/nature-skills/NOTICE.md +7 -0
  67. package/vendor/nature-skills/PSYCLAW_SOURCE.json +19 -0
  68. package/vendor/nature-skills/skills/nature-figure/README.md +107 -0
  69. package/vendor/nature-skills/skills/nature-figure/README_EN.md +107 -0
  70. package/vendor/nature-skills/skills/nature-figure/SKILL.md +154 -0
  71. package/vendor/nature-skills/skills/nature-figure/agents/openai.yaml +4 -0
  72. package/vendor/nature-skills/skills/nature-figure/evals/evals.json +325 -0
  73. package/vendor/nature-skills/skills/nature-figure/manifest.yaml +103 -0
  74. package/vendor/nature-skills/skills/nature-figure/references/ai-graphical-abstract-workflow.md +129 -0
  75. package/vendor/nature-skills/skills/nature-figure/references/api.md +576 -0
  76. package/vendor/nature-skills/skills/nature-figure/references/asset-adaptation.md +72 -0
  77. package/vendor/nature-skills/skills/nature-figure/references/backend-selection.md +118 -0
  78. package/vendor/nature-skills/skills/nature-figure/references/chart-types.md +348 -0
  79. package/vendor/nature-skills/skills/nature-figure/references/common-patterns.md +371 -0
  80. package/vendor/nature-skills/skills/nature-figure/references/demos.md +58 -0
  81. package/vendor/nature-skills/skills/nature-figure/references/design-theory.md +467 -0
  82. package/vendor/nature-skills/skills/nature-figure/references/figure-contract.md +122 -0
  83. package/vendor/nature-skills/skills/nature-figure/references/figure-legend-conventions.md +90 -0
  84. package/vendor/nature-skills/skills/nature-figure/references/multipanel-evidence-architecture.md +268 -0
  85. package/vendor/nature-skills/skills/nature-figure/references/nature-2026-observations.md +124 -0
  86. package/vendor/nature-skills/skills/nature-figure/references/nature-article-requirements.md +149 -0
  87. package/vendor/nature-skills/skills/nature-figure/references/openrouter-image-generation.md +141 -0
  88. package/vendor/nature-skills/skills/nature-figure/references/qa-contract.md +344 -0
  89. package/vendor/nature-skills/skills/nature-figure/references/r-template-index.md +66 -0
  90. package/vendor/nature-skills/skills/nature-figure/references/r-workflow.md +234 -0
  91. package/vendor/nature-skills/skills/nature-figure/references/template-catalog.md +33 -0
  92. package/vendor/nature-skills/skills/nature-figure/references/tutorials.md +260 -0
  93. package/vendor/nature-skills/skills/nature-figure/requirements.txt +1 -0
  94. package/vendor/nature-skills/skills/nature-figure/scripts/audit_figure_collisions.py +742 -0
  95. package/vendor/nature-skills/skills/nature-figure/scripts/audit_panel_alignment.py +933 -0
  96. package/vendor/nature-skills/skills/nature-figure/scripts/audit_pdf_text.py +152 -0
  97. package/vendor/nature-skills/skills/nature-figure/scripts/figure_safety.py +50 -0
  98. package/vendor/nature-skills/skills/nature-figure/scripts/generate_openrouter_schematic.py +260 -0
  99. package/vendor/nature-skills/skills/nature-figure/scripts/nature_figure_backend.py +93 -0
  100. package/vendor/nature-skills/skills/nature-figure/scripts/panel_alignment.R +188 -0
  101. package/vendor/nature-skills/skills/nature-figure/scripts/plot_templates.py +604 -0
  102. package/vendor/nature-skills/skills/nature-figure/scripts/validate_figure.py +835 -0
  103. package/vendor/nature-skills/skills/nature-figure/static/core/contract.md +55 -0
  104. package/vendor/nature-skills/skills/nature-figure/static/core/stance.md +41 -0
  105. package/vendor/nature-skills/skills/nature-figure/static/fragments/backend/python.md +56 -0
  106. package/vendor/nature-skills/skills/nature-figure/static/fragments/backend/r.md +63 -0
  107. package/vendor/nature-skills/skills/nature-figure/tests/test_figure_safety.py +209 -0
  108. package/vendor/nature-skills/skills/nature-polishing/README.md +58 -0
  109. package/vendor/nature-skills/skills/nature-polishing/README_EN.md +58 -0
  110. package/vendor/nature-skills/skills/nature-polishing/SKILL.md +111 -0
  111. package/vendor/nature-skills/skills/nature-polishing/agents/openai.yaml +4 -0
  112. package/vendor/nature-skills/skills/nature-polishing/manifest.yaml +101 -0
  113. package/vendor/nature-skills/skills/nature-polishing/references/latex-layout.md +211 -0
  114. package/vendor/nature-skills/skills/nature-polishing/references/nat-comms-2025-diction.md +73 -0
  115. package/vendor/nature-skills/skills/nature-polishing/references/phrasebank-playbook.md +175 -0
  116. package/vendor/nature-skills/skills/nature-polishing/references/published-article-patterns.md +126 -0
  117. package/vendor/nature-skills/skills/nature-polishing/references/section-moves.md +252 -0
  118. package/vendor/nature-skills/skills/nature-polishing/references/style-guardrails.md +94 -0
  119. package/vendor/nature-skills/skills/nature-polishing/references/writing-strategy.md +160 -0
  120. package/vendor/nature-skills/skills/nature-polishing/static/core/failure-modes.md +29 -0
  121. package/vendor/nature-skills/skills/nature-polishing/static/core/output-format.md +21 -0
  122. package/vendor/nature-skills/skills/nature-polishing/static/core/stance.md +26 -0
  123. package/vendor/nature-skills/skills/nature-polishing/static/fragments/journal/generic.md +17 -0
  124. package/vendor/nature-skills/skills/nature-polishing/static/fragments/journal/nat-comms.md +38 -0
  125. package/vendor/nature-skills/skills/nature-polishing/static/fragments/journal/nat-mach-intell.md +102 -0
  126. package/vendor/nature-skills/skills/nature-polishing/static/fragments/journal/nature.md +19 -0
  127. package/vendor/nature-skills/skills/nature-polishing/static/fragments/language/en.md +19 -0
  128. package/vendor/nature-skills/skills/nature-polishing/static/fragments/language/zh-to-en.md +19 -0
  129. package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/algorithmic.md +18 -0
  130. package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/hypothesis.md +17 -0
  131. package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/methods.md +35 -0
  132. package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/research.md +29 -0
  133. package/vendor/nature-skills/skills/nature-polishing/static/fragments/paper_type/review.md +17 -0
  134. package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/abstract.md +26 -0
  135. package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/conclusion.md +15 -0
  136. package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/discussion.md +48 -0
  137. package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/intro.md +33 -0
  138. package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/methods.md +26 -0
  139. package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/results.md +61 -0
  140. package/vendor/nature-skills/skills/nature-polishing/static/fragments/section/title.md +17 -0
  141. package/vendor/nature-skills/skills/nature-ref-verifier/README.md +44 -0
  142. package/vendor/nature-skills/skills/nature-ref-verifier/README_EN.md +44 -0
  143. package/vendor/nature-skills/skills/nature-ref-verifier/SKILL.md +196 -0
  144. package/vendor/nature-skills/skills/nature-ref-verifier/agents/openai.yaml +4 -0
  145. package/vendor/nature-skills/skills/nature-ref-verifier/manifest.yaml +19 -0
  146. package/vendor/nature-skills/skills/nature-ref-verifier/references/common-patterns.md +96 -0
  147. package/vendor/nature-skills/skills/nature-shared/README.md +43 -0
  148. package/vendor/nature-skills/skills/nature-shared/README_EN.md +43 -0
  149. package/vendor/nature-skills/skills/nature-shared/SKILL.md +33 -0
  150. package/vendor/nature-skills/skills/nature-shared/agents/openai.yaml +6 -0
  151. package/vendor/nature-skills/skills/nature-shared/core/consistency-sweep.md +122 -0
  152. package/vendor/nature-skills/skills/nature-shared/core/discussion-argument-language.md +192 -0
  153. package/vendor/nature-skills/skills/nature-shared/core/ethics.md +88 -0
  154. package/vendor/nature-skills/skills/nature-shared/core/main-text-discipline.md +179 -0
  155. package/vendor/nature-skills/skills/nature-shared/core/nature-abstract.md +171 -0
  156. package/vendor/nature-skills/skills/nature-shared/core/nature-introduction.md +164 -0
  157. package/vendor/nature-skills/skills/nature-shared/core/nature-results-discussion.md +215 -0
  158. package/vendor/nature-skills/skills/nature-shared/core/paper-type-taxonomy.md +41 -0
  159. package/vendor/nature-skills/skills/nature-shared/core/reader-workflow.md +21 -0
  160. package/vendor/nature-skills/skills/nature-shared/core/research-compliance.md +192 -0
  161. package/vendor/nature-skills/skills/nature-shared/core/terminology-ledger.md +58 -0
  162. package/vendor/nature-skills/skills/nature-shared/journal-formats/nat-comms.md +139 -0
  163. package/vendor/nature-skills/skills/nature-shared/journal-formats/nature-machine-intelligence.md +431 -0
  164. package/vendor/nature-skills/skills/nature-shared/journal-formats/nature.md +313 -0
  165. package/vendor/nature-skills/skills/nature-shared/manifest.yaml +52 -0
  166. package/vendor/nature-skills/skills/nature-shared/scripts/check_consistency.py +273 -0
  167. package/vendor/nature-skills/skills/nature-shared/tests/test_check_consistency.py +63 -0
@@ -0,0 +1,550 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Final Paper Evaluation Script
4
+
5
+ This script evaluates the complete paper against quality standards before submission.
6
+ Uses 7-dimension assessment (10 points each, 70 total).
7
+ """
8
+
9
+ import json
10
+ from datetime import datetime
11
+ from typing import Dict, List
12
+
13
+ def create_final_evaluation_template() -> Dict:
14
+ """Create template for final paper evaluation."""
15
+ return {
16
+ "paper_title": "",
17
+ "total_word_count": 0,
18
+ "target_platform": "",
19
+ "evaluation_date": "",
20
+ "evaluation": {
21
+ "overall_argument_quality": {
22
+ "score": 0, # 1-10
23
+ "notes": ""
24
+ },
25
+ "literature_integration": {
26
+ "score": 0, # 1-10
27
+ "citation_count": 0,
28
+ "notes": ""
29
+ },
30
+ "clarity_accessibility": {
31
+ "score": 0, # 1-10
32
+ "notes": ""
33
+ },
34
+ "originality_contribution": {
35
+ "score": 0, # 1-10
36
+ "notes": ""
37
+ },
38
+ "methodological_rigor": {
39
+ "score": 0, # 1-10
40
+ "notes": ""
41
+ },
42
+ "structure_organization": {
43
+ "score": 0, # 1-10
44
+ "notes": ""
45
+ },
46
+ "platform_conformity": {
47
+ "score": 0, # 1-10
48
+ "notes": ""
49
+ }
50
+ },
51
+ "completeness_checklist": {
52
+ "structural": {
53
+ "abstract": False,
54
+ "introduction": False,
55
+ "main_chapters": False,
56
+ "conclusion": False,
57
+ "references": False
58
+ },
59
+ "content": {
60
+ "promises_fulfilled": False,
61
+ "claims_supported": False,
62
+ "terms_defined": False,
63
+ "objections_addressed": False,
64
+ "limitations_acknowledged": False
65
+ },
66
+ "citations": {
67
+ "text_has_bibliography": False,
68
+ "bibliography_cited": False,
69
+ "format_consistent": False,
70
+ "complete_information": False
71
+ },
72
+ "format": {
73
+ "title_page": False,
74
+ "section_numbering": False,
75
+ "heading_hierarchy": False,
76
+ "platform_requirements": False
77
+ }
78
+ },
79
+ "identified_issues": [],
80
+ "submission_ready": False
81
+ }
82
+
83
+ def calculate_final_score(evaluation: Dict) -> Dict:
84
+ """Calculate total score and determine submission readiness."""
85
+ scores = evaluation.get("evaluation", {})
86
+
87
+ total = sum([
88
+ scores.get("overall_argument_quality", {}).get("score", 0),
89
+ scores.get("literature_integration", {}).get("score", 0),
90
+ scores.get("clarity_accessibility", {}).get("score", 0),
91
+ scores.get("originality_contribution", {}).get("score", 0),
92
+ scores.get("methodological_rigor", {}).get("score", 0),
93
+ scores.get("structure_organization", {}).get("score", 0),
94
+ scores.get("platform_conformity", {}).get("score", 0)
95
+ ])
96
+
97
+ percentage = (total / 70) * 100
98
+ passes = total >= 56 # 80% threshold
99
+
100
+ # Categorize quality
101
+ if total >= 63: # 90%
102
+ quality_level = "Excellent"
103
+ recommendation = "Ready for immediate submission"
104
+ elif total >= 56: # 80%
105
+ quality_level = "Good"
106
+ recommendation = "Ready for submission with minor optional improvements"
107
+ elif total >= 49: # 70%
108
+ quality_level = "Acceptable"
109
+ recommendation = "Moderate revisions recommended before submission"
110
+ else:
111
+ quality_level = "Needs Improvement"
112
+ recommendation = "Major revisions required before submission"
113
+
114
+ return {
115
+ "total_score": total,
116
+ "max_score": 70,
117
+ "percentage": round(percentage, 1),
118
+ "passes_threshold": passes,
119
+ "quality_level": quality_level,
120
+ "recommendation": recommendation
121
+ }
122
+
123
+ def evaluate_completeness(checklist: Dict) -> Dict:
124
+ """Evaluate completeness across all categories."""
125
+ categories = ["structural", "content", "citations", "format"]
126
+
127
+ results = {}
128
+ total_items = 0
129
+ completed_items = 0
130
+
131
+ for category in categories:
132
+ cat_data = checklist.get(category, {})
133
+ cat_total = len(cat_data)
134
+ cat_completed = sum(1 for v in cat_data.values() if v)
135
+
136
+ results[category] = {
137
+ "completed": cat_completed,
138
+ "total": cat_total,
139
+ "percentage": (cat_completed / cat_total * 100) if cat_total > 0 else 0,
140
+ "complete": cat_completed == cat_total
141
+ }
142
+
143
+ total_items += cat_total
144
+ completed_items += cat_completed
145
+
146
+ overall_complete = completed_items == total_items
147
+
148
+ return {
149
+ "by_category": results,
150
+ "overall": {
151
+ "completed": completed_items,
152
+ "total": total_items,
153
+ "percentage": (completed_items / total_items * 100) if total_items > 0 else 0,
154
+ "complete": overall_complete
155
+ }
156
+ }
157
+
158
+ def identify_weak_dimensions(evaluation: Dict) -> List[Dict]:
159
+ """Identify dimensions scoring below 7."""
160
+ scores = evaluation.get("evaluation", {})
161
+ weak_dimensions = []
162
+
163
+ dimensions = [
164
+ ("overall_argument_quality", "Overall Argument Quality"),
165
+ ("literature_integration", "Literature Integration"),
166
+ ("clarity_accessibility", "Clarity & Accessibility"),
167
+ ("originality_contribution", "Originality & Contribution"),
168
+ ("methodological_rigor", "Methodological Rigor"),
169
+ ("structure_organization", "Structure & Organization"),
170
+ ("platform_conformity", "Platform & Style Conformity")
171
+ ]
172
+
173
+ for key, name in dimensions:
174
+ dim_data = scores.get(key, {})
175
+ score = dim_data.get("score", 0)
176
+
177
+ if score < 7:
178
+ severity = "high" if score <= 4 else "medium"
179
+ weak_dimensions.append({
180
+ "dimension": name,
181
+ "score": score,
182
+ "max_score": 10,
183
+ "notes": dim_data.get("notes", ""),
184
+ "severity": severity
185
+ })
186
+
187
+ return weak_dimensions
188
+
189
+ def generate_recommendations(evaluation: Dict, weak_dims: List[Dict],
190
+ completeness: Dict) -> List[Dict]:
191
+ """Generate prioritized revision recommendations."""
192
+ recommendations = []
193
+
194
+ # Completeness issues
195
+ if not completeness['overall']['complete']:
196
+ for category, data in completeness['by_category'].items():
197
+ if not data['complete']:
198
+ recommendations.append({
199
+ "category": "completeness",
200
+ "priority": "high",
201
+ "issue": f"{category.title()} completeness: {data['completed']}/{data['total']} items",
202
+ "action": f"Complete all {category} checklist items before submission"
203
+ })
204
+
205
+ # Weak dimensions
206
+ for dim in weak_dims:
207
+ recommendations.append({
208
+ "category": dim["dimension"],
209
+ "priority": dim["severity"],
210
+ "issue": f"{dim['dimension']} scored {dim['score']}/10",
211
+ "action": f"Address: {dim['notes']}" if dim['notes'] else f"Improve {dim['dimension'].lower()}"
212
+ })
213
+
214
+ # Citation count check
215
+ lit_data = evaluation.get("evaluation", {}).get("literature_integration", {})
216
+ citation_count = lit_data.get("citation_count", 0)
217
+
218
+ if citation_count < 20:
219
+ recommendations.append({
220
+ "category": "citations",
221
+ "priority": "high",
222
+ "issue": f"Only {citation_count} citations (minimum 20 recommended)",
223
+ "action": "Expand literature review and add supporting citations"
224
+ })
225
+ elif citation_count < 30:
226
+ recommendations.append({
227
+ "category": "citations",
228
+ "priority": "medium",
229
+ "issue": f"{citation_count} citations (30-40 recommended for philosophy)",
230
+ "action": "Consider adding more citations to strengthen arguments"
231
+ })
232
+
233
+ # Custom issues
234
+ for issue in evaluation.get("identified_issues", []):
235
+ recommendations.append({
236
+ "category": "custom",
237
+ "priority": "high",
238
+ "issue": issue,
239
+ "action": "Address this specific issue"
240
+ })
241
+
242
+ # Sort by priority
243
+ priority_order = {"high": 0, "medium": 1, "low": 2}
244
+ recommendations.sort(key=lambda x: priority_order.get(x["priority"], 3))
245
+
246
+ return recommendations
247
+
248
+ def generate_final_report(evaluation: Dict) -> str:
249
+ """Generate comprehensive final evaluation report."""
250
+ score_result = calculate_final_score(evaluation)
251
+ completeness = evaluate_completeness(evaluation.get("completeness_checklist", {}))
252
+ weak_dims = identify_weak_dimensions(evaluation)
253
+ recommendations = generate_recommendations(evaluation, weak_dims, completeness)
254
+
255
+ report = f"""
256
+ # Final Paper Evaluation Report
257
+
258
+ Generated: {datetime.now().strftime('%Y-%m-%d %H:%M')}
259
+
260
+ ## Paper Information
261
+
262
+ - **Title**: {evaluation.get('paper_title', 'N/A')}
263
+ - **Total word count**: {evaluation.get('total_word_count', 'N/A')}
264
+ - **Target platform**: {evaluation.get('target_platform', 'N/A')}
265
+ - **Evaluation date**: {evaluation.get('evaluation_date', datetime.now().strftime('%Y-%m-%d'))}
266
+
267
+ ---
268
+
269
+ ## Overall Assessment
270
+
271
+ - **Total Score**: {score_result['total_score']}/{score_result['max_score']} ({score_result['percentage']}%)
272
+ - **Quality Level**: {score_result['quality_level']}
273
+ - **Passes Threshold**: {'✓ YES' if score_result['passes_threshold'] else '✗ NO (56/70 required)'}
274
+ - **Recommendation**: {score_result['recommendation']}
275
+
276
+ ---
277
+
278
+ ## 7-Dimension Evaluation
279
+
280
+ """
281
+
282
+ # Dimension scores
283
+ scores = evaluation.get("evaluation", {})
284
+ dimensions = [
285
+ ("overall_argument_quality", "Overall Argument Quality"),
286
+ ("literature_integration", "Literature Integration"),
287
+ ("clarity_accessibility", "Clarity & Accessibility"),
288
+ ("originality_contribution", "Originality & Contribution"),
289
+ ("methodological_rigor", "Methodological Rigor"),
290
+ ("structure_organization", "Structure & Organization"),
291
+ ("platform_conformity", "Platform & Style Conformity")
292
+ ]
293
+
294
+ for key, name in dimensions:
295
+ dim_data = scores.get(key, {})
296
+ score = dim_data.get("score", 0)
297
+ notes = dim_data.get("notes", "No notes provided")
298
+
299
+ icon = "✓" if score >= 7 else "⚠"
300
+ report += f"### {icon} {name}: {score}/10\n\n"
301
+ report += f"{notes}\n\n"
302
+
303
+ # Add citation count for literature dimension
304
+ if key == "literature_integration":
305
+ citation_count = dim_data.get("citation_count", 0)
306
+ report += f"**Citation count**: {citation_count}\n\n"
307
+
308
+ # Completeness assessment
309
+ report += "---\n\n## Completeness Assessment\n\n"
310
+
311
+ overall_comp = completeness['overall']
312
+ report += f"**Overall**: {overall_comp['completed']}/{overall_comp['total']} items complete ({overall_comp['percentage']:.1f}%)\n\n"
313
+
314
+ for category, data in completeness['by_category'].items():
315
+ icon = "✓" if data['complete'] else "⚠"
316
+ report += f"### {icon} {category.title()}: {data['completed']}/{data['total']} ({data['percentage']:.1f}%)\n\n"
317
+
318
+ # List incomplete items
319
+ cat_checklist = evaluation.get("completeness_checklist", {}).get(category, {})
320
+ incomplete = [item for item, done in cat_checklist.items() if not done]
321
+
322
+ if incomplete:
323
+ report += "**Incomplete items**:\n"
324
+ for item in incomplete:
325
+ report += f"- {item.replace('_', ' ').title()}\n"
326
+ report += "\n"
327
+
328
+ # Weak dimensions
329
+ if weak_dims:
330
+ report += "---\n\n## Weak Dimensions (Score <7)\n\n"
331
+ for dim in weak_dims:
332
+ report += f"### {dim['dimension']}: {dim['score']}/10 ({dim['severity'].upper()} priority)\n\n"
333
+ if dim['notes']:
334
+ report += f"{dim['notes']}\n\n"
335
+
336
+ # Recommendations
337
+ if recommendations:
338
+ report += "---\n\n## Revision Recommendations\n\n"
339
+ report += "Prioritized list of recommended revisions:\n\n"
340
+
341
+ for i, rec in enumerate(recommendations, 1):
342
+ priority_icon = {"high": "🔴", "medium": "🟡", "low": "🟢"}.get(rec['priority'], "⚪")
343
+ report += f"{i}. {priority_icon} **{rec['category'].title()}** ({rec['priority'].upper()} priority)\n"
344
+ report += f" - Issue: {rec['issue']}\n"
345
+ report += f" - Action: {rec['action']}\n\n"
346
+
347
+ # Submission decision
348
+ report += "---\n\n## Submission Decision\n\n"
349
+
350
+ submission_ready = evaluation.get('submission_ready', False)
351
+
352
+ if score_result['passes_threshold'] and completeness['overall']['complete']:
353
+ report += f"✓ **READY FOR SUBMISSION**: Paper meets quality threshold ({score_result['percentage']}%) and all completeness checks passed.\n\n"
354
+
355
+ if score_result['percentage'] >= 90:
356
+ report += "**Quality**: Excellent. No revisions required.\n\n"
357
+ else:
358
+ report += "**Optional improvements**:\n"
359
+ if recommendations:
360
+ for rec in recommendations[:3]: # Top 3
361
+ report += f"- {rec['action']}\n"
362
+ else:
363
+ report += "- No critical issues identified\n"
364
+ report += "\n**Note**: These improvements are optional. Paper is ready for submission as is.\n"
365
+
366
+ else:
367
+ report += f"✗ **NOT READY**: Paper requires revisions before submission.\n\n"
368
+
369
+ if not score_result['passes_threshold']:
370
+ report += f"**Quality issue**: Score {score_result['total_score']}/70 is below 56/70 threshold.\n"
371
+
372
+ if not completeness['overall']['complete']:
373
+ report += f"**Completeness issue**: {overall_comp['total'] - overall_comp['completed']} checklist items incomplete.\n"
374
+
375
+ report += "\n**Required actions**:\n"
376
+ report += "1. Address all HIGH priority recommendations\n"
377
+ report += "2. Complete all checklist items\n"
378
+ report += "3. Re-evaluate paper after revisions\n"
379
+ report += "4. Verify score ≥56/70 and all items complete\n"
380
+
381
+ # Platform-specific submission checklist
382
+ report += "\n---\n\n## Platform-Specific Submission Checklist\n\n"
383
+
384
+ platform = evaluation.get('target_platform', '').lower()
385
+
386
+ if 'philarchive' in platform or 'philpapers' in platform:
387
+ report += """**PhilArchive/PhilPapers**:
388
+ - [ ] PDF format
389
+ - [ ] Abstract <500 words
390
+ - [ ] Proper metadata (title, keywords, AMS classification)
391
+ - [ ] Author information complete
392
+ - [ ] No formatting issues in PDF
393
+ """
394
+
395
+ elif 'arxiv' in platform:
396
+ report += """**arXiv**:
397
+ - [ ] LaTeX or PDF format
398
+ - [ ] Abstract <1920 characters
399
+ - [ ] Proper category selection (cs.AI, q-bio.NC, etc.)
400
+ - [ ] No embedded fonts issues
401
+ - [ ] Author affiliations included
402
+ """
403
+
404
+ elif 'philsci' in platform:
405
+ report += """**PhilSci-Archive**:
406
+ - [ ] PDF format
407
+ - [ ] Proper subject classification
408
+ - [ ] Keywords provided (3-5 recommended)
409
+ - [ ] No copyrighted material without permission
410
+ - [ ] Author contact information
411
+ """
412
+
413
+ else:
414
+ report += f"**{evaluation.get('target_platform', 'Platform')}**:\n"
415
+ report += "- [ ] Check platform-specific requirements\n"
416
+ report += "- [ ] Verify format compliance\n"
417
+ report += "- [ ] Prepare all required metadata\n"
418
+
419
+ report += "\n---\n\n## Next Steps\n\n"
420
+
421
+ if score_result['passes_threshold'] and completeness['overall']['complete']:
422
+ report += "1. Review optional improvements (if desired)\n"
423
+ report += "2. Complete platform-specific submission checklist\n"
424
+ report += "3. Generate final PDF\n"
425
+ report += "4. Submit to platform\n"
426
+ report += "5. Monitor for feedback/acceptance\n"
427
+ else:
428
+ report += "1. Implement HIGH priority revisions\n"
429
+ report += "2. Complete all checklist items\n"
430
+ report += "3. Re-run final evaluation\n"
431
+ report += "4. When passing, proceed with submission steps\n"
432
+
433
+ return report
434
+
435
+ def validate_evaluation(evaluation: Dict) -> Dict:
436
+ """Validate that evaluation is complete and properly formatted."""
437
+ issues = []
438
+ warnings = []
439
+
440
+ # Check required fields
441
+ required_fields = ["paper_title", "total_word_count", "target_platform"]
442
+ for field in required_fields:
443
+ if not evaluation.get(field):
444
+ warnings.append(f"Missing recommended field: {field}")
445
+
446
+ # Check all dimensions scored
447
+ eval_data = evaluation.get("evaluation", {})
448
+ dimensions = ["overall_argument_quality", "literature_integration",
449
+ "clarity_accessibility", "originality_contribution",
450
+ "methodological_rigor", "structure_organization",
451
+ "platform_conformity"]
452
+
453
+ for dim in dimensions:
454
+ if dim not in eval_data:
455
+ issues.append(f"Missing dimension: {dim}")
456
+ else:
457
+ score = eval_data[dim].get("score", 0)
458
+ if not isinstance(score, int) or score < 1 or score > 10:
459
+ issues.append(f"Invalid score for {dim}: {score} (must be 1-10)")
460
+
461
+ if not eval_data[dim].get("notes"):
462
+ warnings.append(f"No notes provided for {dim} (recommended)")
463
+
464
+ # Check completeness checklist
465
+ checklist = evaluation.get("completeness_checklist", {})
466
+ if not checklist:
467
+ issues.append("Missing completeness_checklist")
468
+
469
+ return {
470
+ "valid": len(issues) == 0,
471
+ "issues": issues,
472
+ "warnings": warnings
473
+ }
474
+
475
+ def main():
476
+ """Interactive final evaluation interface."""
477
+ print("=" * 60)
478
+ print("Final Paper Evaluation Tool")
479
+ print("=" * 60)
480
+ print()
481
+
482
+ print("Options:")
483
+ print("1. Create evaluation template")
484
+ print("2. Evaluate paper from JSON")
485
+ print()
486
+
487
+ choice = input("Select option (1-2): ").strip()
488
+
489
+ if choice == "1":
490
+ # Create template
491
+ title = input("Paper title: ").strip()
492
+ word_count = int(input("Total word count: ").strip())
493
+ platform = input("Target platform: ").strip()
494
+
495
+ template = create_final_evaluation_template()
496
+ template["paper_title"] = title
497
+ template["total_word_count"] = word_count
498
+ template["target_platform"] = platform
499
+ template["evaluation_date"] = datetime.now().strftime('%Y-%m-%d')
500
+
501
+ filename = "final_evaluation.json"
502
+ with open(filename, 'w') as f:
503
+ json.dump(template, f, indent=2)
504
+
505
+ print(f"\nTemplate saved to {filename}")
506
+ print("Fill in the evaluation scores, notes, and checklist, then use option 2 to generate report.")
507
+
508
+ elif choice == "2":
509
+ # Evaluate paper
510
+ filename = input("Enter evaluation JSON filename: ").strip()
511
+ try:
512
+ with open(filename, 'r') as f:
513
+ evaluation = json.load(f)
514
+
515
+ # Validate
516
+ validation = validate_evaluation(evaluation)
517
+
518
+ if not validation['valid']:
519
+ print("\n⚠ Validation Issues:")
520
+ for issue in validation['issues']:
521
+ print(f" - {issue}")
522
+ print("\nPlease fix issues before generating report.")
523
+ return
524
+
525
+ if validation['warnings']:
526
+ print("\nℹ️ Warnings:")
527
+ for warning in validation['warnings']:
528
+ print(f" - {warning}")
529
+ print()
530
+
531
+ # Generate report
532
+ report = generate_final_report(evaluation)
533
+ print("\n" + report)
534
+
535
+ # Save report
536
+ report_filename = filename.replace('.json', '_report.md')
537
+ with open(report_filename, 'w') as f:
538
+ f.write(report)
539
+ print(f"\nReport saved to {report_filename}")
540
+
541
+ except FileNotFoundError:
542
+ print(f"Error: File '{filename}' not found")
543
+ except json.JSONDecodeError:
544
+ print(f"Error: '{filename}' is not valid JSON")
545
+
546
+ else:
547
+ print("Invalid option")
548
+
549
+ if __name__ == "__main__":
550
+ main()