dsh-aris-panel 0.1.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.
Files changed (442) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +98 -0
  3. package/README_CN.md +87 -0
  4. package/dsh/checkout.patch.yml +38 -0
  5. package/dsh/client.js +634 -0
  6. package/dsh/cordis.patch.yml +44 -0
  7. package/dsh/index.mjs +76 -0
  8. package/dsh/run-status.mjs +182 -0
  9. package/dsh/scope-limits.mjs +50 -0
  10. package/dsh/workbench.mjs +291 -0
  11. package/mcp-servers/claude-review/README.md +93 -0
  12. package/mcp-servers/claude-review/run_with_claude_aws.sh +49 -0
  13. package/mcp-servers/claude-review/server.py +718 -0
  14. package/mcp-servers/codex-image2/README.md +65 -0
  15. package/mcp-servers/codex-image2/server.py +893 -0
  16. package/mcp-servers/feishu-bridge/requirements.txt +1 -0
  17. package/mcp-servers/feishu-bridge/server.py +240 -0
  18. package/mcp-servers/gemini-review/README.md +171 -0
  19. package/mcp-servers/gemini-review/server.py +1856 -0
  20. package/mcp-servers/llm-chat/requirements.txt +1 -0
  21. package/mcp-servers/llm-chat/server.py +664 -0
  22. package/mcp-servers/manual-review/README.md +133 -0
  23. package/mcp-servers/manual-review/server.py +910 -0
  24. package/mcp-servers/manual-review/ui.html +279 -0
  25. package/mcp-servers/minimax-chat/requirements.txt +1 -0
  26. package/mcp-servers/minimax-chat/server.py +381 -0
  27. package/package.json +51 -0
  28. package/skills/ablation-planner/SKILL.md +123 -0
  29. package/skills/alphaxiv/SKILL.md +196 -0
  30. package/skills/analyze-results/SKILL.md +46 -0
  31. package/skills/arxiv/SKILL.md +248 -0
  32. package/skills/auto-paper-improvement-loop/SKILL.md +651 -0
  33. package/skills/auto-review-loop/SKILL.md +1137 -0
  34. package/skills/auto-review-loop-llm/SKILL.md +259 -0
  35. package/skills/auto-review-loop-minimax/SKILL.md +302 -0
  36. package/skills/citation-audit/SKILL.md +502 -0
  37. package/skills/claims-drafting/SKILL.md +227 -0
  38. package/skills/comm-lit-review/SKILL.md +297 -0
  39. package/skills/deepxiv/SKILL.md +263 -0
  40. package/skills/dse-loop/SKILL.md +296 -0
  41. package/skills/embodiment-description/SKILL.md +129 -0
  42. package/skills/exa-search/SKILL.md +205 -0
  43. package/skills/experiment-audit/SKILL.md +311 -0
  44. package/skills/experiment-bridge/SKILL.md +376 -0
  45. package/skills/experiment-plan/SKILL.md +249 -0
  46. package/skills/experiment-queue/SKILL.md +431 -0
  47. package/skills/experiment-queue/scripts/build_manifest.py +142 -0
  48. package/skills/experiment-queue/scripts/queue_manager.py +433 -0
  49. package/skills/feishu-notify/SKILL.md +156 -0
  50. package/skills/figure-description/SKILL.md +138 -0
  51. package/skills/figure-spec/SKILL.md +262 -0
  52. package/skills/figure-spec/scripts/figure_renderer.py +799 -0
  53. package/skills/formula-derivation/SKILL.md +280 -0
  54. package/skills/gemini-search/SKILL.md +231 -0
  55. package/skills/grant-proposal/SKILL.md +698 -0
  56. package/skills/idea-creator/SKILL.md +542 -0
  57. package/skills/idea-discovery/SKILL.md +521 -0
  58. package/skills/idea-discovery-robot/SKILL.md +363 -0
  59. package/skills/integrity-forensics/SKILL.md +284 -0
  60. package/skills/interview-cheatsheet/SKILL.md +245 -0
  61. package/skills/invention-structuring/SKILL.md +188 -0
  62. package/skills/jurisdiction-format/SKILL.md +192 -0
  63. package/skills/kill-argument/SKILL.md +437 -0
  64. package/skills/mermaid-diagram/SKILL.md +419 -0
  65. package/skills/meta-apply/SKILL.md +141 -0
  66. package/skills/meta-optimize/SKILL.md +437 -0
  67. package/skills/monitor-experiment/SKILL.md +140 -0
  68. package/skills/novelty-check/SKILL.md +101 -0
  69. package/skills/openalex/SKILL.md +237 -0
  70. package/skills/overleaf-sync/SKILL.md +220 -0
  71. package/skills/paper-claim-audit/SKILL.md +348 -0
  72. package/skills/paper-compile/SKILL.md +266 -0
  73. package/skills/paper-figure/SKILL.md +312 -0
  74. package/skills/paper-illustration/SKILL.md +736 -0
  75. package/skills/paper-illustration-image2/SKILL.md +391 -0
  76. package/skills/paper-illustration-image2/scripts/paper_illustration_image2.py +255 -0
  77. package/skills/paper-plan/SKILL.md +386 -0
  78. package/skills/paper-poster/SKILL.md +19 -0
  79. package/skills/paper-poster-html/DESIGN_FINAL.md +176 -0
  80. package/skills/paper-poster-html/IMPLEMENTATION_CONVENTIONS.md +161 -0
  81. package/skills/paper-poster-html/LICENSES/posterly-MIT.txt +21 -0
  82. package/skills/paper-poster-html/NOTICE.md +57 -0
  83. package/skills/paper-poster-html/SKILL.md +323 -0
  84. package/skills/paper-poster-html/scripts/_posterly/__init__.py +0 -0
  85. package/skills/paper-poster-html/scripts/_posterly/canvas.py +200 -0
  86. package/skills/paper-poster-html/scripts/_posterly/measure.py +588 -0
  87. package/skills/paper-poster-html/scripts/_posterly/polish.py +498 -0
  88. package/skills/paper-poster-html/scripts/_posterly/preflight.py +489 -0
  89. package/skills/paper-poster-html/scripts/_posterly/render.py +215 -0
  90. package/skills/paper-poster-html/scripts/_posterly/textutil.py +16 -0
  91. package/skills/paper-poster-html/scripts/_posterly/verify_final.py +171 -0
  92. package/skills/paper-poster-html/scripts/asset_check.py +897 -0
  93. package/skills/paper-poster-html/scripts/extract_pdf_figures.py +666 -0
  94. package/skills/paper-poster-html/scripts/poster_check.py +251 -0
  95. package/skills/paper-poster-html/scripts/preprocess_figures.py +238 -0
  96. package/skills/paper-poster-html/scripts/render_preview.py +217 -0
  97. package/skills/paper-poster-html/scripts/run_gates.py +556 -0
  98. package/skills/paper-poster-html/scripts/style_check.py +1324 -0
  99. package/skills/paper-poster-html/templates/COMPONENTS.md +462 -0
  100. package/skills/paper-poster-html/templates/README.md +170 -0
  101. package/skills/paper-poster-html/templates/landscape_4col.html +1032 -0
  102. package/skills/paper-poster-html/templates/landscape_hero.html +1046 -0
  103. package/skills/paper-poster-html/templates/portrait_2col.html +947 -0
  104. package/skills/paper-poster-html/templates/tokens/acl.json +9 -0
  105. package/skills/paper-poster-html/templates/tokens/cvpr.json +9 -0
  106. package/skills/paper-poster-html/templates/tokens/generic.json +9 -0
  107. package/skills/paper-poster-html/templates/tokens/iclr.json +9 -0
  108. package/skills/paper-poster-html/templates/tokens/icml.json +9 -0
  109. package/skills/paper-poster-html/templates/tokens/neurips.json +9 -0
  110. package/skills/paper-slides/SKILL.md +635 -0
  111. package/skills/paper-talk/SKILL.md +381 -0
  112. package/skills/paper-write/SKILL.md +604 -0
  113. package/skills/paper-write/templates/IEEEtran.bst +2409 -0
  114. package/skills/paper-write/templates/IEEEtran.cls +6347 -0
  115. package/skills/paper-write/templates/iclr2026.tex +84 -0
  116. package/skills/paper-write/templates/icml2025.tex +87 -0
  117. package/skills/paper-write/templates/ieee_conference.tex +89 -0
  118. package/skills/paper-write/templates/ieee_journal.tex +93 -0
  119. package/skills/paper-write/templates/math_commands.tex +48 -0
  120. package/skills/paper-write/templates/neurips2025.tex +80 -0
  121. package/skills/paper-writing/SKILL.md +916 -0
  122. package/skills/patent-novelty-check/SKILL.md +153 -0
  123. package/skills/patent-pipeline/SKILL.md +344 -0
  124. package/skills/patent-review/SKILL.md +203 -0
  125. package/skills/pixel-art/SKILL.md +137 -0
  126. package/skills/prior-art-search/SKILL.md +146 -0
  127. package/skills/proof-checker/SKILL.md +866 -0
  128. package/skills/proof-orchestrator/NOTICE.md +24 -0
  129. package/skills/proof-orchestrator/SKILL.md +254 -0
  130. package/skills/proof-orchestrator/references/audit-output-contract.md +126 -0
  131. package/skills/proof-orchestrator/references/deepseek-routing.md +74 -0
  132. package/skills/proof-orchestrator/references/dispatch-prompts.md +227 -0
  133. package/skills/proof-orchestrator/references/notation-audit.md +135 -0
  134. package/skills/proof-orchestrator/references/proof-audit-rubric.md +70 -0
  135. package/skills/proof-orchestrator/references/stress-tests.md +38 -0
  136. package/skills/proof-writer/SKILL.md +223 -0
  137. package/skills/qzcli/SKILL.md +324 -0
  138. package/skills/rebuttal/SKILL.md +376 -0
  139. package/skills/render-html/SKILL.md +316 -0
  140. package/skills/render-html/scripts/render_html.py +1006 -0
  141. package/skills/render-html/scripts/templates/academic.html +703 -0
  142. package/skills/render-html/scripts/templates/dashboard.html +333 -0
  143. package/skills/research-lit/SKILL.md +756 -0
  144. package/skills/research-pipeline/SKILL.md +384 -0
  145. package/skills/research-refine/SKILL.md +770 -0
  146. package/skills/research-refine-pipeline/SKILL.md +186 -0
  147. package/skills/research-review/SKILL.md +198 -0
  148. package/skills/research-wiki/SKILL.md +461 -0
  149. package/skills/resubmit-pipeline/SKILL.md +447 -0
  150. package/skills/result-to-claim/SKILL.md +311 -0
  151. package/skills/run-experiment/SKILL.md +313 -0
  152. package/skills/semantic-scholar/SKILL.md +236 -0
  153. package/skills/serverless-modal/SKILL.md +335 -0
  154. package/skills/shared-references/acceptance-gate.md +324 -0
  155. package/skills/shared-references/assurance-contract.md +248 -0
  156. package/skills/shared-references/capture-antipatterns.md +78 -0
  157. package/skills/shared-references/citation-discipline.md +583 -0
  158. package/skills/shared-references/compute-env-contract.md +163 -0
  159. package/skills/shared-references/effort-contract.md +183 -0
  160. package/skills/shared-references/evidence-precheck.md +65 -0
  161. package/skills/shared-references/experiment-integrity.md +49 -0
  162. package/skills/shared-references/external-cadence.md +326 -0
  163. package/skills/shared-references/fan-out-pattern.md +366 -0
  164. package/skills/shared-references/injection-hygiene.md +127 -0
  165. package/skills/shared-references/integration-contract.md +461 -0
  166. package/skills/shared-references/output-composition.md +93 -0
  167. package/skills/shared-references/output-language.md +45 -0
  168. package/skills/shared-references/output-manifest.md +49 -0
  169. package/skills/shared-references/output-versioning.md +111 -0
  170. package/skills/shared-references/patent-format-cn.md +199 -0
  171. package/skills/shared-references/patent-format-ep.md +173 -0
  172. package/skills/shared-references/patent-format-us.md +161 -0
  173. package/skills/shared-references/patent-writing-principles.md +197 -0
  174. package/skills/shared-references/prior-art-databases.md +141 -0
  175. package/skills/shared-references/resumable-runs.md +109 -0
  176. package/skills/shared-references/review-scope-limits.md +81 -0
  177. package/skills/shared-references/review-tracing.md +391 -0
  178. package/skills/shared-references/reviewer-independence.md +79 -0
  179. package/skills/shared-references/reviewer-routing.md +852 -0
  180. package/skills/shared-references/skill-governance.md +104 -0
  181. package/skills/shared-references/taste-calibration.md +85 -0
  182. package/skills/shared-references/venue-checklists.md +114 -0
  183. package/skills/shared-references/wiki-helper-resolution.md +134 -0
  184. package/skills/shared-references/writing-principles.md +525 -0
  185. package/skills/skills-codex/README.md +102 -0
  186. package/skills/skills-codex/README_CN.md +100 -0
  187. package/skills/skills-codex/ablation-planner/SKILL.md +126 -0
  188. package/skills/skills-codex/alphaxiv/SKILL.md +186 -0
  189. package/skills/skills-codex/analyze-results/SKILL.md +45 -0
  190. package/skills/skills-codex/arxiv/SKILL.md +210 -0
  191. package/skills/skills-codex/auto-paper-improvement-loop/SKILL.md +574 -0
  192. package/skills/skills-codex/auto-review-loop/SKILL.md +500 -0
  193. package/skills/skills-codex/auto-review-loop-llm/SKILL.md +247 -0
  194. package/skills/skills-codex/auto-review-loop-minimax/SKILL.md +290 -0
  195. package/skills/skills-codex/citation-audit/SKILL.md +504 -0
  196. package/skills/skills-codex/claims-drafting/SKILL.md +239 -0
  197. package/skills/skills-codex/comm-lit-review/SKILL.md +299 -0
  198. package/skills/skills-codex/comm-lit-review/references/domain-taxonomy.md +57 -0
  199. package/skills/skills-codex/comm-lit-review/references/output-template.md +37 -0
  200. package/skills/skills-codex/comm-lit-review/references/source-policy.md +99 -0
  201. package/skills/skills-codex/comm-lit-review/references/venue-tiering.md +112 -0
  202. package/skills/skills-codex/deepxiv/SKILL.md +142 -0
  203. package/skills/skills-codex/dse-loop/SKILL.md +285 -0
  204. package/skills/skills-codex/embodiment-description/SKILL.md +129 -0
  205. package/skills/skills-codex/exa-search/SKILL.md +192 -0
  206. package/skills/skills-codex/experiment-audit/SKILL.md +286 -0
  207. package/skills/skills-codex/experiment-bridge/SKILL.md +356 -0
  208. package/skills/skills-codex/experiment-plan/SKILL.md +249 -0
  209. package/skills/skills-codex/experiment-queue/SKILL.md +401 -0
  210. package/skills/skills-codex/feishu-notify/SKILL.md +155 -0
  211. package/skills/skills-codex/figure-description/SKILL.md +138 -0
  212. package/skills/skills-codex/figure-spec/SKILL.md +252 -0
  213. package/skills/skills-codex/formula-derivation/SKILL.md +280 -0
  214. package/skills/skills-codex/gemini-search/SKILL.md +205 -0
  215. package/skills/skills-codex/grant-proposal/SKILL.md +626 -0
  216. package/skills/skills-codex/idea-creator/SKILL.md +405 -0
  217. package/skills/skills-codex/idea-discovery/SKILL.md +475 -0
  218. package/skills/skills-codex/idea-discovery-robot/SKILL.md +362 -0
  219. package/skills/skills-codex/integrity-forensics/SKILL.md +106 -0
  220. package/skills/skills-codex/interview-cheatsheet/SKILL.md +245 -0
  221. package/skills/skills-codex/invention-structuring/SKILL.md +188 -0
  222. package/skills/skills-codex/jurisdiction-format/SKILL.md +192 -0
  223. package/skills/skills-codex/kill-argument/SKILL.md +403 -0
  224. package/skills/skills-codex/mermaid-diagram/SKILL.md +379 -0
  225. package/skills/skills-codex/meta-apply/SKILL.md +154 -0
  226. package/skills/skills-codex/meta-optimize/SKILL.md +348 -0
  227. package/skills/skills-codex/monitor-experiment/SKILL.md +98 -0
  228. package/skills/skills-codex/novelty-check/SKILL.md +89 -0
  229. package/skills/skills-codex/openalex/SKILL.md +228 -0
  230. package/skills/skills-codex/overleaf-sync/SKILL.md +220 -0
  231. package/skills/skills-codex/paper-claim-audit/SKILL.md +350 -0
  232. package/skills/skills-codex/paper-compile/SKILL.md +253 -0
  233. package/skills/skills-codex/paper-figure/SKILL.md +311 -0
  234. package/skills/skills-codex/paper-illustration/SKILL.md +690 -0
  235. package/skills/skills-codex/paper-illustration-image2/SKILL.md +383 -0
  236. package/skills/skills-codex/paper-illustration-image2/scripts/paper_illustration_image2.py +255 -0
  237. package/skills/skills-codex/paper-plan/SKILL.md +278 -0
  238. package/skills/skills-codex/paper-poster/SKILL.md +19 -0
  239. package/skills/skills-codex/paper-poster-html/SKILL.md +377 -0
  240. package/skills/skills-codex/paper-slides/SKILL.md +571 -0
  241. package/skills/skills-codex/paper-talk/SKILL.md +381 -0
  242. package/skills/skills-codex/paper-write/SKILL.md +411 -0
  243. package/skills/skills-codex/paper-write/templates/IEEEtran.bst +2409 -0
  244. package/skills/skills-codex/paper-write/templates/IEEEtran.cls +6347 -0
  245. package/skills/skills-codex/paper-write/templates/aaai2026.bst +1493 -0
  246. package/skills/skills-codex/paper-write/templates/aaai2026.sty +315 -0
  247. package/skills/skills-codex/paper-write/templates/aaai2026.tex +952 -0
  248. package/skills/skills-codex/paper-write/templates/acl.sty +312 -0
  249. package/skills/skills-codex/paper-write/templates/acl2026.tex +377 -0
  250. package/skills/skills-codex/paper-write/templates/acl_natbib.bst +1940 -0
  251. package/skills/skills-codex/paper-write/templates/acm.bst +3081 -0
  252. package/skills/skills-codex/paper-write/templates/acm_mm2026.tex +204 -0
  253. package/skills/skills-codex/paper-write/templates/acmart.cls +3520 -0
  254. package/skills/skills-codex/paper-write/templates/cvpr.bst +1448 -0
  255. package/skills/skills-codex/paper-write/templates/cvpr.sty +508 -0
  256. package/skills/skills-codex/paper-write/templates/cvpr2026.tex +63 -0
  257. package/skills/skills-codex/paper-write/templates/iclr2026.tex +84 -0
  258. package/skills/skills-codex/paper-write/templates/iclr2026_conference.bst +1440 -0
  259. package/skills/skills-codex/paper-write/templates/iclr2026_conference.sty +246 -0
  260. package/skills/skills-codex/paper-write/templates/icml2026.sty +767 -0
  261. package/skills/skills-codex/paper-write/templates/icml2026.tex +662 -0
  262. package/skills/skills-codex/paper-write/templates/ieee_conference.tex +89 -0
  263. package/skills/skills-codex/paper-write/templates/ieee_journal.tex +93 -0
  264. package/skills/skills-codex/paper-write/templates/math_commands.tex +48 -0
  265. package/skills/skills-codex/paper-write/templates/neurips2026.tex +493 -0
  266. package/skills/skills-codex/paper-write/templates/neurips_2026.sty +437 -0
  267. package/skills/skills-codex/paper-writing/SKILL.md +731 -0
  268. package/skills/skills-codex/patent-novelty-check/SKILL.md +153 -0
  269. package/skills/skills-codex/patent-pipeline/SKILL.md +344 -0
  270. package/skills/skills-codex/patent-review/SKILL.md +202 -0
  271. package/skills/skills-codex/pixel-art/SKILL.md +139 -0
  272. package/skills/skills-codex/prior-art-search/SKILL.md +146 -0
  273. package/skills/skills-codex/proof-checker/SKILL.md +554 -0
  274. package/skills/skills-codex/proof-orchestrator/SKILL.md +260 -0
  275. package/skills/skills-codex/proof-orchestrator/references/audit-output-contract.md +126 -0
  276. package/skills/skills-codex/proof-orchestrator/references/deepseek-routing.md +76 -0
  277. package/skills/skills-codex/proof-orchestrator/references/dispatch-prompts.md +227 -0
  278. package/skills/skills-codex/proof-orchestrator/references/notation-audit.md +135 -0
  279. package/skills/skills-codex/proof-orchestrator/references/proof-audit-rubric.md +70 -0
  280. package/skills/skills-codex/proof-orchestrator/references/stress-tests.md +38 -0
  281. package/skills/skills-codex/proof-writer/SKILL.md +222 -0
  282. package/skills/skills-codex/qzcli/SKILL.md +324 -0
  283. package/skills/skills-codex/rebuttal/SKILL.md +305 -0
  284. package/skills/skills-codex/render-html/SKILL.md +305 -0
  285. package/skills/skills-codex/render-html/scripts/__pycache__/render_html.cpython-314.pyc +0 -0
  286. package/skills/skills-codex/render-html/scripts/render_html.py +909 -0
  287. package/skills/skills-codex/render-html/scripts/templates/academic.html +342 -0
  288. package/skills/skills-codex/render-html/scripts/templates/dashboard.html +333 -0
  289. package/skills/skills-codex/research-lit/SKILL.md +464 -0
  290. package/skills/skills-codex/research-pipeline/SKILL.md +340 -0
  291. package/skills/skills-codex/research-refine/SKILL.md +721 -0
  292. package/skills/skills-codex/research-refine-pipeline/SKILL.md +186 -0
  293. package/skills/skills-codex/research-review/SKILL.md +135 -0
  294. package/skills/skills-codex/research-wiki/SKILL.md +421 -0
  295. package/skills/skills-codex/resubmit-pipeline/SKILL.md +444 -0
  296. package/skills/skills-codex/result-to-claim/SKILL.md +246 -0
  297. package/skills/skills-codex/run-experiment/SKILL.md +236 -0
  298. package/skills/skills-codex/semantic-scholar/SKILL.md +219 -0
  299. package/skills/skills-codex/serverless-modal/SKILL.md +335 -0
  300. package/skills/skills-codex/shared-references/acceptance-gate.md +336 -0
  301. package/skills/skills-codex/shared-references/assurance-contract.md +139 -0
  302. package/skills/skills-codex/shared-references/capture-antipatterns.md +84 -0
  303. package/skills/skills-codex/shared-references/citation-discipline.md +452 -0
  304. package/skills/skills-codex/shared-references/compute-env-contract.md +163 -0
  305. package/skills/skills-codex/shared-references/effort-contract.md +143 -0
  306. package/skills/skills-codex/shared-references/evidence-precheck.md +73 -0
  307. package/skills/skills-codex/shared-references/experiment-integrity.md +49 -0
  308. package/skills/skills-codex/shared-references/external-cadence.md +334 -0
  309. package/skills/skills-codex/shared-references/fan-out-pattern.md +375 -0
  310. package/skills/skills-codex/shared-references/injection-hygiene.md +132 -0
  311. package/skills/skills-codex/shared-references/integration-contract.md +372 -0
  312. package/skills/skills-codex/shared-references/output-composition.md +98 -0
  313. package/skills/skills-codex/shared-references/output-language.md +45 -0
  314. package/skills/skills-codex/shared-references/output-manifest.md +40 -0
  315. package/skills/skills-codex/shared-references/output-versioning.md +111 -0
  316. package/skills/skills-codex/shared-references/patent-format-cn.md +199 -0
  317. package/skills/skills-codex/shared-references/patent-format-ep.md +173 -0
  318. package/skills/skills-codex/shared-references/patent-format-us.md +161 -0
  319. package/skills/skills-codex/shared-references/patent-writing-principles.md +197 -0
  320. package/skills/skills-codex/shared-references/prior-art-databases.md +141 -0
  321. package/skills/skills-codex/shared-references/resumable-runs.md +125 -0
  322. package/skills/skills-codex/shared-references/review-scope-limits.md +81 -0
  323. package/skills/skills-codex/shared-references/review-tracing.md +144 -0
  324. package/skills/skills-codex/shared-references/reviewer-independence.md +66 -0
  325. package/skills/skills-codex/shared-references/reviewer-routing.md +128 -0
  326. package/skills/skills-codex/shared-references/skill-governance.md +119 -0
  327. package/skills/skills-codex/shared-references/taste-calibration.md +90 -0
  328. package/skills/skills-codex/shared-references/venue-checklists.md +73 -0
  329. package/skills/skills-codex/shared-references/wiki-helper-resolution.md +69 -0
  330. package/skills/skills-codex/shared-references/writing-principles.md +525 -0
  331. package/skills/skills-codex/slides-polish/SKILL.md +563 -0
  332. package/skills/skills-codex/specification-writing/SKILL.md +211 -0
  333. package/skills/skills-codex/system-profile/SKILL.md +103 -0
  334. package/skills/skills-codex/training-check/SKILL.md +83 -0
  335. package/skills/skills-codex/vast-gpu/SKILL.md +394 -0
  336. package/skills/skills-codex/web-debug-search/SKILL.md +334 -0
  337. package/skills/skills-codex/wiki-enrich/SKILL.md +255 -0
  338. package/skills/skills-codex/writing-systems-papers/SKILL.md +184 -0
  339. package/skills/skills-codex-claude-review/README.md +79 -0
  340. package/skills/skills-codex-claude-review/README_CN.md +78 -0
  341. package/skills/skills-codex-claude-review/auto-paper-improvement-loop/SKILL.md +581 -0
  342. package/skills/skills-codex-claude-review/auto-review-loop/SKILL.md +510 -0
  343. package/skills/skills-codex-claude-review/novelty-check/SKILL.md +102 -0
  344. package/skills/skills-codex-claude-review/paper-figure/SKILL.md +319 -0
  345. package/skills/skills-codex-claude-review/paper-plan/SKILL.md +287 -0
  346. package/skills/skills-codex-claude-review/paper-write/SKILL.md +420 -0
  347. package/skills/skills-codex-claude-review/research-refine/SKILL.md +732 -0
  348. package/skills/skills-codex-claude-review/research-review/SKILL.md +149 -0
  349. package/skills/skills-codex-gemini-review/README.md +176 -0
  350. package/skills/skills-codex-gemini-review/README_CN.md +175 -0
  351. package/skills/skills-codex-gemini-review/auto-paper-improvement-loop/SKILL.md +331 -0
  352. package/skills/skills-codex-gemini-review/auto-review-loop/SKILL.md +304 -0
  353. package/skills/skills-codex-gemini-review/grant-proposal/SKILL.md +630 -0
  354. package/skills/skills-codex-gemini-review/idea-creator/SKILL.md +263 -0
  355. package/skills/skills-codex-gemini-review/idea-discovery/SKILL.md +275 -0
  356. package/skills/skills-codex-gemini-review/idea-discovery-robot/SKILL.md +365 -0
  357. package/skills/skills-codex-gemini-review/novelty-check/SKILL.md +92 -0
  358. package/skills/skills-codex-gemini-review/paper-figure/SKILL.md +289 -0
  359. package/skills/skills-codex-gemini-review/paper-plan/SKILL.md +265 -0
  360. package/skills/skills-codex-gemini-review/paper-poster-html/SKILL.md +102 -0
  361. package/skills/skills-codex-gemini-review/paper-slides/SKILL.md +582 -0
  362. package/skills/skills-codex-gemini-review/paper-write/SKILL.md +346 -0
  363. package/skills/skills-codex-gemini-review/paper-writing/SKILL.md +312 -0
  364. package/skills/skills-codex-gemini-review/research-refine/SKILL.md +674 -0
  365. package/skills/skills-codex-gemini-review/research-review/SKILL.md +112 -0
  366. package/skills/slides-polish/SKILL.md +565 -0
  367. package/skills/specification-writing/SKILL.md +211 -0
  368. package/skills/system-profile/SKILL.md +103 -0
  369. package/skills/training-check/SKILL.md +132 -0
  370. package/skills/vast-gpu/SKILL.md +394 -0
  371. package/skills/web-debug-search/SKILL.md +334 -0
  372. package/skills/wiki-enrich/SKILL.md +257 -0
  373. package/skills/writing-systems-papers/SKILL.md +184 -0
  374. package/templates/CLAUDE_MD_TEMPLATE.md +29 -0
  375. package/templates/EXPERIMENT_LOG_TEMPLATE.md +47 -0
  376. package/templates/EXPERIMENT_PLAN_TEMPLATE.md +51 -0
  377. package/templates/EXPERIMENT_PLAN_TEMPLATE_CN.md +53 -0
  378. package/templates/FINDINGS_TEMPLATE.md +52 -0
  379. package/templates/IDEA_CANDIDATES_TEMPLATE.md +47 -0
  380. package/templates/IDEA_CANDIDATES_TEMPLATE_CN.md +47 -0
  381. package/templates/INVENTION_BRIEF_TEMPLATE.md +87 -0
  382. package/templates/MANIFEST_TEMPLATE.md +7 -0
  383. package/templates/NARRATIVE_REPORT_TEMPLATE.md +49 -0
  384. package/templates/PAPER_PLAN_TEMPLATE.md +47 -0
  385. package/templates/PATENT_CLAIMS_TEMPLATE.md +78 -0
  386. package/templates/PATENT_SPECIFICATION_TEMPLATE.md +68 -0
  387. package/templates/README.md +57 -0
  388. package/templates/RESEARCH_BRIEF_TEMPLATE.md +35 -0
  389. package/templates/RESEARCH_BRIEF_TEMPLATE_CN.md +41 -0
  390. package/templates/RESEARCH_CONTRACT_TEMPLATE.md +60 -0
  391. package/templates/claude-hooks/corpus_write_guard.json +16 -0
  392. package/templates/claude-hooks/corpus_write_guard.py +85 -0
  393. package/templates/claude-hooks/meta_logging.json +74 -0
  394. package/templates/gitignore-trace.txt +3 -0
  395. package/tools/__pycache__/check_skills_inventory.cpython-314.pyc +0 -0
  396. package/tools/arxiv_fetch.py +311 -0
  397. package/tools/capture_filter.py +126 -0
  398. package/tools/check_skills_inventory.py +273 -0
  399. package/tools/convert_skills_to_llm_chat.py +282 -0
  400. package/tools/copilot_native_evidence.py +818 -0
  401. package/tools/deepxiv_fetch.py +213 -0
  402. package/tools/evidence_check.py +212 -0
  403. package/tools/exa_search.py +425 -0
  404. package/tools/experiment_queue/README.md +118 -0
  405. package/tools/experiment_queue/build_manifest.py +44 -0
  406. package/tools/experiment_queue/queue_manager.py +44 -0
  407. package/tools/extract_paper_style.py +560 -0
  408. package/tools/figure_renderer.py +69 -0
  409. package/tools/forensics_gate.py +669 -0
  410. package/tools/generate_codex_claude_review_overrides.py +299 -0
  411. package/tools/idea_discovery_gate.py +256 -0
  412. package/tools/install_aris.ps1 +1372 -0
  413. package/tools/install_aris.sh +1370 -0
  414. package/tools/install_aris_codex.sh +1023 -0
  415. package/tools/install_aris_copilot.sh +1052 -0
  416. package/tools/iteration_log.py +143 -0
  417. package/tools/lint_skills_helpers.sh +84 -0
  418. package/tools/meta_opt/check_ready.sh +80 -0
  419. package/tools/meta_opt/log_event.sh +91 -0
  420. package/tools/meta_opt/trigger_eval.py +280 -0
  421. package/tools/meta_opt/trigger_evals.sample.json +28 -0
  422. package/tools/openalex_fetch.py +326 -0
  423. package/tools/overleaf_audit.sh +104 -0
  424. package/tools/overleaf_setup.sh +150 -0
  425. package/tools/paper_illustration_image2.py +62 -0
  426. package/tools/provenance.py +294 -0
  427. package/tools/research_wiki.py +1720 -0
  428. package/tools/review_gate.py +502 -0
  429. package/tools/run_state.py +399 -0
  430. package/tools/save_trace.sh +477 -0
  431. package/tools/semantic_scholar_fetch.py +438 -0
  432. package/tools/skill-groups.tsv +116 -0
  433. package/tools/skill_picker.py +238 -0
  434. package/tools/smart_update.ps1 +521 -0
  435. package/tools/smart_update.sh +591 -0
  436. package/tools/smart_update_codex.sh +419 -0
  437. package/tools/smart_update_copilot.sh +605 -0
  438. package/tools/threat_scan.py +222 -0
  439. package/tools/verify_paper_audits.sh +487 -0
  440. package/tools/verify_papers.py +613 -0
  441. package/tools/verify_wiki_coverage.sh +176 -0
  442. package/tools/watchdog.py +485 -0
@@ -0,0 +1,556 @@
1
+ #!/usr/bin/env python3
2
+ """run_gates - canonical gate orchestrator for HTML academic posters.
3
+
4
+ Runs the five poster gates in their fixed canonical order and writes a
5
+ single ``GATE_REPORT.json`` that the SKILL workflow (and any reviewer)
6
+ reads to decide pass/fail and find the full fix surface in one shot::
7
+
8
+ preflight -> style -> asset -> measure -> polish
9
+
10
+ WHY an orchestrator instead of calling each gate by hand:
11
+
12
+ - The order is load-bearing. ``preflight`` is a cheap static lint that
13
+ catches the bugs (LaTeX residue, missing images, broken roles) that
14
+ would otherwise burn an expensive render cycle in ``measure`` /
15
+ ``polish``; ``style`` and ``asset`` source-gate the design before we
16
+ pay for rendering at all. Putting that order in one script keeps it
17
+ from drifting across callers.
18
+ - Default ACCUMULATE: a poster author wants the WHOLE fix surface at
19
+ once, not a stop-at-first-error trickle. ``--fail-fast`` is opt-in
20
+ for CI that only cares whether the build is green.
21
+ - The vendored ``poster_check.py`` keeps its own subcommand CLI
22
+ (preflight / measure / polish) and the new sibling gates
23
+ (style_check.py / asset_check.py) keep theirs, so the vendor diff
24
+ stays clean. This file is pure orchestration: it shells out to each,
25
+ parses what it can, and aggregates into the §7 schema.
26
+
27
+ Integration contract (DESIGN_FINAL.md §7, IMPLEMENTATION_CONVENTIONS.md
28
+ §C): child processes run with ``sys.executable``, ``cwd`` = the poster
29
+ HTML's directory (so relative ``assets/...`` paths resolve), and the
30
+ gate script paths are resolved relative to THIS file's location -- never
31
+ the cwd -- so the orchestrator is position-independent.
32
+
33
+ Exit code: 0 = overall PASS (zero hard failures), 1 = at least one hard
34
+ failure, 2 = usage / environment error.
35
+ """
36
+ from __future__ import annotations
37
+
38
+ import argparse
39
+ import datetime
40
+ import json
41
+ import os
42
+ import subprocess
43
+ import sys
44
+ from pathlib import Path
45
+ from typing import Any
46
+
47
+ # Make ``_posterly`` importable when this file is run directly, exactly
48
+ # like the vendored poster_check.py / render_preview.py do.
49
+ _THIS_DIR = os.path.dirname(os.path.abspath(__file__))
50
+ if _THIS_DIR not in sys.path:
51
+ sys.path.insert(0, _THIS_DIR)
52
+
53
+ from _posterly import canvas as _canvas # noqa: E402
54
+ from _posterly.textutil import ascii_safe # noqa: E402
55
+
56
+ SCHEMA_VERSION = 1
57
+ SKILL_NAME = "paper-poster-html"
58
+
59
+ # Canonical gate order. The orchestration depends on this list order, so
60
+ # it is the single source of truth for "what runs and in what sequence".
61
+ CANONICAL_ORDER = ["preflight", "style", "asset", "measure", "polish"]
62
+
63
+ # Severity of each gate as a whole. ``preflight``, ``style``, ``asset``,
64
+ # and ``measure`` are HARD gates: a FAIL blocks ``overall``. ``polish``
65
+ # is SOFT by default (its findings are WARN) and only becomes hard under
66
+ # ``--strict-polish`` (which maps to ``poster_check.py polish --strict``).
67
+ GATE_SEVERITY = {
68
+ "preflight": "hard",
69
+ "style": "hard",
70
+ "asset": "hard",
71
+ "measure": "hard",
72
+ "polish": "soft",
73
+ }
74
+
75
+ # How many trailing lines of child stdout/stderr to keep in the report
76
+ # summary for the vendored gates (which have no machine-readable output).
77
+ # Enough to capture the "[gate] PASS/FAIL" verdict line and the couple of
78
+ # FAIL: lines above it without bloating the JSON.
79
+ TAIL_LINES = 8
80
+
81
+
82
+ def _eprint(*args: Any, **kw: Any) -> None:
83
+ print(*args, file=sys.stderr, **kw)
84
+
85
+
86
+ def _tail(text: str, n: int = TAIL_LINES) -> str:
87
+ """Return the last ``n`` non-empty lines of ``text``, ascii-safe.
88
+
89
+ Used to summarise a vendored gate's human output when it offers no
90
+ ``--json``. Non-empty filtering drops the trailing newline noise so
91
+ the verdict line lands at the end of the tail.
92
+ """
93
+ lines = [ln for ln in text.splitlines() if ln.strip()]
94
+ return ascii_safe("\n".join(lines[-n:]))
95
+
96
+
97
+ def _now_iso() -> str:
98
+ """UTC timestamp, second precision, ``Z`` suffix -- stable for diffs."""
99
+ return (
100
+ datetime.datetime.now(datetime.timezone.utc)
101
+ .replace(microsecond=0)
102
+ .isoformat()
103
+ .replace("+00:00", "Z")
104
+ )
105
+
106
+
107
+ # --------------------------------------------------------------------------
108
+ # Canvas resolution (GATE_REPORT.json `canvas` block).
109
+ # --------------------------------------------------------------------------
110
+ def _orientation(width: float, height: float) -> str:
111
+ """Landscape when wider than tall, else portrait (square -> portrait)."""
112
+ return "landscape" if width > height else "portrait"
113
+
114
+
115
+ def resolve_canvas(html_path: Path) -> dict[str, Any]:
116
+ """Build the ``canvas`` block for the report.
117
+
118
+ Source priority (DESIGN_FINAL §7):
119
+ 1. ``POSTER_STATE.json`` sitting next to the poster HTML, if it
120
+ carries canvas dimensions -- the workflow records the resolved
121
+ venue canvas there, so it is authoritative once present.
122
+ 2. The ``@page { size }`` rule parsed from the HTML via
123
+ ``_posterly.canvas`` -- source tagged ``"page-rule"``.
124
+ 3. ``None`` everywhere with source ``"unknown"`` -- we never invent
125
+ a default; a downstream consumer must notice the canvas is not
126
+ resolved rather than trust a fabricated size.
127
+ """
128
+ state_path = html_path.parent / "POSTER_STATE.json"
129
+ if state_path.exists():
130
+ block = _canvas_from_state(state_path)
131
+ if block is not None:
132
+ return block
133
+
134
+ # Fall back to the @page rule. canvas.py returns inches; the report
135
+ # schema is in centimetres.
136
+ parsed = _canvas.read_canvas_from_html(html_path)
137
+ if parsed is not None:
138
+ w_cm = round(parsed[0] * 2.54, 2)
139
+ h_cm = round(parsed[1] * 2.54, 2)
140
+ return {
141
+ "source": "page-rule",
142
+ "width_cm": w_cm,
143
+ "height_cm": h_cm,
144
+ "orientation": _orientation(w_cm, h_cm),
145
+ "source_url": None,
146
+ }
147
+
148
+ # Neither source resolved -- be explicit, do not fabricate a size.
149
+ return {
150
+ "source": "unknown",
151
+ "width_cm": None,
152
+ "height_cm": None,
153
+ "orientation": None,
154
+ "source_url": None,
155
+ }
156
+
157
+
158
+ def _canvas_from_state(state_path: Path) -> dict[str, Any] | None:
159
+ """Pull a canvas block out of POSTER_STATE.json, defensively.
160
+
161
+ The workflow owns POSTER_STATE.json's full shape; we only need the
162
+ canvas. Accept either a nested ``{"canvas": {...}}`` object or the
163
+ canvas fields at top level, and tolerate missing/garbage by returning
164
+ ``None`` so the caller can fall through to the @page rule. A partial
165
+ state (e.g. dimensions but no orientation) is completed where we can.
166
+ """
167
+ try:
168
+ data = json.loads(state_path.read_text(encoding="utf-8"))
169
+ except (OSError, ValueError):
170
+ return None
171
+ if not isinstance(data, dict):
172
+ return None
173
+
174
+ canvas = data.get("canvas") if isinstance(data.get("canvas"), dict) else data
175
+ width = canvas.get("width_cm")
176
+ height = canvas.get("height_cm")
177
+ if not isinstance(width, (int, float)) or not isinstance(height, (int, float)):
178
+ # No usable dimensions -> let the @page rule speak instead.
179
+ return None
180
+
181
+ orientation = canvas.get("orientation")
182
+ if orientation not in ("landscape", "portrait"):
183
+ orientation = _orientation(float(width), float(height))
184
+
185
+ return {
186
+ "source": canvas.get("source") or "poster-state",
187
+ "width_cm": round(float(width), 2),
188
+ "height_cm": round(float(height), 2),
189
+ "orientation": orientation,
190
+ "source_url": canvas.get("source_url"),
191
+ }
192
+
193
+
194
+ # --------------------------------------------------------------------------
195
+ # Child-process gate invocation.
196
+ # --------------------------------------------------------------------------
197
+ def _run_child(argv: list[str], cwd: Path) -> tuple[int, str, str]:
198
+ """Run a gate as a subprocess, return ``(returncode, stdout, stderr)``.
199
+
200
+ A child that cannot even start (e.g. its script file is missing, or
201
+ the interpreter rejects it) is surfaced as return code 2 with the
202
+ OSError text on stderr -- the same "environment error" code the
203
+ children themselves use -- so the gate is marked SKIPPED rather than
204
+ crashing the orchestrator.
205
+ """
206
+ try:
207
+ proc = subprocess.run(
208
+ argv,
209
+ cwd=str(cwd),
210
+ stdout=subprocess.PIPE,
211
+ stderr=subprocess.PIPE,
212
+ text=True,
213
+ )
214
+ except OSError as exc: # script missing, not executable, etc.
215
+ return 2, "", f"failed to launch {ascii_safe(argv)}: {ascii_safe(exc)}"
216
+ return proc.returncode, proc.stdout, proc.stderr
217
+
218
+
219
+ def _parse_json_gate(stdout: str) -> dict[str, Any] | None:
220
+ """Parse a JSON-emitting gate's stdout (style / asset).
221
+
222
+ Those gates write their structured verdict to a ``--json`` file, but
223
+ we also accept JSON on stdout as a fallback. We scan from the LAST
224
+ ``{`` so any leading human log lines don't poison the parse. Returns
225
+ ``None`` when no JSON object is found.
226
+ """
227
+ start = stdout.rfind("{")
228
+ if start == -1:
229
+ return None
230
+ candidate = stdout[start:]
231
+ try:
232
+ obj = json.loads(candidate)
233
+ except ValueError:
234
+ return None
235
+ return obj if isinstance(obj, dict) else None
236
+
237
+
238
+ def _status_from_returncode(returncode: int, severity: str) -> str:
239
+ """Map a child exit code to a gate status string.
240
+
241
+ 0 -> PASS, 1 -> FAIL (hard) / WARN (soft polish), 2 -> SKIPPED
242
+ (environment error: missing playwright, missing script, etc.). The
243
+ soft/hard distinction only matters at exit 1: a soft gate that exits
244
+ 1 *without* ``--strict`` would not have happened (it returns 0 on
245
+ warnings), so an exit-1 polish under ``--strict-polish`` is a real
246
+ FAIL; we still resolve via severity for safety.
247
+ """
248
+ if returncode == 0:
249
+ return "PASS"
250
+ if returncode == 1:
251
+ return "FAIL" if severity == "hard" else "WARN"
252
+ return "SKIPPED"
253
+
254
+
255
+ def _build_argv(
256
+ gate: str,
257
+ scripts_dir: Path,
258
+ html_path: Path,
259
+ opts: argparse.Namespace,
260
+ report_json_dir: Path,
261
+ ) -> list[str]:
262
+ """Construct the exact argv for one gate.
263
+
264
+ Script paths are resolved against ``scripts_dir`` (THIS file's
265
+ directory) so the orchestrator is position-independent. The HTML is
266
+ passed as an ABSOLUTE path because each child runs with cwd set to
267
+ the HTML's directory and we don't want to assume the child re-derives
268
+ it. Per-gate ``--json`` sidecar files (style / asset) are written
269
+ next to the report so the full machine-readable trail lives together.
270
+ """
271
+ py = sys.executable
272
+ html = str(html_path)
273
+
274
+ if gate == "preflight":
275
+ return [py, str(scripts_dir / "poster_check.py"), "preflight", html]
276
+
277
+ if gate == "style":
278
+ argv = [py, str(scripts_dir / "style_check.py"), html]
279
+ if opts.tokens:
280
+ argv += ["--tokens", str(Path(opts.tokens).resolve())]
281
+ if opts.no_render:
282
+ argv += ["--no-render"]
283
+ argv += ["--json", str(report_json_dir / "style_check.json")]
284
+ return argv
285
+
286
+ if gate == "asset":
287
+ argv = [py, str(scripts_dir / "asset_check.py"), html]
288
+ # asset_check requires --manifest; pass through whatever we got
289
+ # (its absence is the child's job to report as a hard FAIL).
290
+ if opts.manifest:
291
+ argv += ["--manifest", str(Path(opts.manifest).resolve())]
292
+ if opts.waive_total_area:
293
+ argv += ["--waive-total-area"]
294
+ if opts.no_render:
295
+ argv += ["--no-render"]
296
+ argv += ["--json", str(report_json_dir / "asset_check.json")]
297
+ return argv
298
+
299
+ if gate == "measure":
300
+ return [py, str(scripts_dir / "poster_check.py"), "measure", html]
301
+
302
+ if gate == "polish":
303
+ argv = [py, str(scripts_dir / "poster_check.py"), "polish", html]
304
+ if opts.strict_polish:
305
+ argv += ["--strict"]
306
+ return argv
307
+
308
+ raise ValueError(f"unknown gate: {gate}") # pragma: no cover
309
+
310
+
311
+ def _summarize_gate(
312
+ gate: str,
313
+ returncode: int,
314
+ stdout: str,
315
+ stderr: str,
316
+ report_json_dir: Path,
317
+ ) -> tuple[str | dict[str, Any], list[str]]:
318
+ """Build ``(summary, artifacts)`` for one finished gate.
319
+
320
+ style / asset speak JSON, so we prefer their structured verdict
321
+ (sidecar file first, then stdout). The vendored gates (preflight /
322
+ measure / polish) have no machine format, so we keep a tail of their
323
+ combined stdout+stderr -- that captures the ``[gate] PASS/FAIL``
324
+ verdict line and any ``FAIL:`` lines, which is all a human needs to
325
+ locate the failure without re-running.
326
+ """
327
+ artifacts: list[str] = []
328
+
329
+ if gate in ("style", "asset"):
330
+ sidecar = report_json_dir / f"{gate}_check.json"
331
+ obj: dict[str, Any] | None = None
332
+ if sidecar.exists():
333
+ try:
334
+ obj = json.loads(sidecar.read_text(encoding="utf-8"))
335
+ artifacts.append(str(sidecar))
336
+ except (OSError, ValueError):
337
+ obj = None
338
+ if obj is None:
339
+ obj = _parse_json_gate(stdout)
340
+ if obj is not None:
341
+ return obj, artifacts
342
+ # No JSON at all -> the gate likely failed to start; fall back to
343
+ # the stderr/stdout tail so the report still says something useful.
344
+ return _tail(stdout + "\n" + stderr), artifacts
345
+
346
+ # Vendored gate: heuristic stdout/stderr tail + exit code.
347
+ combined = (stdout + "\n" + stderr).strip()
348
+ return {
349
+ "exit_code": returncode,
350
+ "tail": _tail(combined),
351
+ }, artifacts
352
+
353
+
354
+ def run_gate(
355
+ gate: str,
356
+ scripts_dir: Path,
357
+ html_path: Path,
358
+ opts: argparse.Namespace,
359
+ report_json_dir: Path,
360
+ ) -> dict[str, Any]:
361
+ """Run one gate and return its report entry (DESIGN_FINAL §7 shape)."""
362
+ severity = GATE_SEVERITY[gate]
363
+ argv = _build_argv(gate, scripts_dir, html_path, opts, report_json_dir)
364
+ returncode, stdout, stderr = _run_child(argv, cwd=html_path.parent)
365
+ status = _status_from_returncode(returncode, severity)
366
+ summary, artifacts = _summarize_gate(
367
+ gate, returncode, stdout, stderr, report_json_dir
368
+ )
369
+ return {
370
+ "name": gate,
371
+ "severity": severity,
372
+ "status": status,
373
+ "command": argv,
374
+ "summary": summary,
375
+ "artifacts": artifacts,
376
+ }
377
+
378
+
379
+ # --------------------------------------------------------------------------
380
+ # Orchestration.
381
+ # --------------------------------------------------------------------------
382
+ def run_all(html_path: Path, opts: argparse.Namespace) -> dict[str, Any]:
383
+ """Run the canonical gate sequence and assemble the GATE_REPORT dict."""
384
+ scripts_dir = Path(__file__).resolve().parent
385
+ report_path = (
386
+ Path(opts.report).resolve()
387
+ if opts.report
388
+ else html_path.parent / "GATE_REPORT.json"
389
+ )
390
+ # Sidecar JSON (style/asset --json) lands next to the report.
391
+ report_json_dir = report_path.parent
392
+
393
+ gates: list[dict[str, Any]] = []
394
+ hard_failures = 0
395
+ warnings = 0
396
+
397
+ for gate in CANONICAL_ORDER:
398
+ entry = run_gate(gate, scripts_dir, html_path, opts, report_json_dir)
399
+ gates.append(entry)
400
+ is_hard = entry["severity"] == "hard"
401
+ if entry["status"] == "FAIL" and is_hard:
402
+ hard_failures += 1
403
+ if opts.fail_fast:
404
+ # Stop scheduling further gates; mark the rest SKIPPED so
405
+ # the report still enumerates the full canonical sequence.
406
+ gates.extend(_skipped_remainder(gate))
407
+ break
408
+ elif entry["status"] == "WARN":
409
+ warnings += 1
410
+ # A soft polish FAIL only happens under --strict-polish, where it
411
+ # counts as a hard failure for `overall`.
412
+ if entry["status"] == "FAIL" and not is_hard:
413
+ hard_failures += 1
414
+ if opts.fail_fast:
415
+ gates.extend(_skipped_remainder(gate))
416
+ break
417
+
418
+ overall = "PASS" if hard_failures == 0 else "FAIL"
419
+
420
+ return {
421
+ "schema_version": SCHEMA_VERSION,
422
+ "skill": SKILL_NAME,
423
+ "timestamp": _now_iso(),
424
+ "poster_html": str(html_path),
425
+ "canvas": resolve_canvas(html_path),
426
+ "overall": overall,
427
+ "hard_failures": hard_failures,
428
+ "warnings": warnings,
429
+ "gates": gates,
430
+ }
431
+
432
+
433
+ def _skipped_remainder(stopped_at: str) -> list[dict[str, Any]]:
434
+ """Build SKIPPED entries for every gate after ``stopped_at``.
435
+
436
+ Under ``--fail-fast`` we abort the run on the first hard failure but
437
+ still want the report to list the full canonical sequence, with the
438
+ not-run gates explicitly marked SKIPPED (reason: fail-fast) rather
439
+ than silently absent.
440
+ """
441
+ idx = CANONICAL_ORDER.index(stopped_at)
442
+ out: list[dict[str, Any]] = []
443
+ for gate in CANONICAL_ORDER[idx + 1:]:
444
+ out.append({
445
+ "name": gate,
446
+ "severity": GATE_SEVERITY[gate],
447
+ "status": "SKIPPED",
448
+ "command": [],
449
+ "summary": {"skipped": "fail-fast: a prior hard gate failed"},
450
+ "artifacts": [],
451
+ })
452
+ return out
453
+
454
+
455
+ def _print_human_summary(report: dict[str, Any]) -> None:
456
+ """Print a compact human-readable digest to stdout alongside the JSON
457
+ file write, so a terminal run isn't silent."""
458
+ print(f"[run_gates] {ascii_safe(report['poster_html'])}")
459
+ canvas = report["canvas"]
460
+ if canvas["width_cm"] is not None:
461
+ print(
462
+ f" canvas: {canvas['width_cm']} x {canvas['height_cm']} cm "
463
+ f"{canvas['orientation']} (source: {canvas['source']})"
464
+ )
465
+ else:
466
+ print(f" canvas: UNRESOLVED (source: {canvas['source']})")
467
+ for g in report["gates"]:
468
+ print(f" {g['name']:9s} [{g['severity']:4s}] -> {g['status']}")
469
+ print(
470
+ f" overall: {report['overall']} "
471
+ f"hard_failures: {report['hard_failures']} "
472
+ f"warnings: {report['warnings']}"
473
+ )
474
+
475
+
476
+ def build_parser() -> argparse.ArgumentParser:
477
+ p = argparse.ArgumentParser(
478
+ prog="run_gates",
479
+ description=(
480
+ "Run the canonical poster gate sequence "
481
+ "(preflight -> style -> asset -> measure -> polish) and write "
482
+ "GATE_REPORT.json. Default accumulates all results; "
483
+ "--fail-fast stops at the first hard failure."
484
+ ),
485
+ )
486
+ p.add_argument("html", help="path to poster.html")
487
+ p.add_argument(
488
+ "--report", default=None,
489
+ help="output GATE_REPORT.json path "
490
+ "(default: GATE_REPORT.json next to the HTML)",
491
+ )
492
+ p.add_argument(
493
+ "--fail-fast", action="store_true",
494
+ help="stop at the first HARD failure instead of accumulating "
495
+ "the full fix surface",
496
+ )
497
+ p.add_argument(
498
+ "--strict-polish", action="store_true",
499
+ help="treat polish warnings as failures "
500
+ "(maps to poster_check.py polish --strict)",
501
+ )
502
+ p.add_argument(
503
+ "--tokens", default=None,
504
+ help="design tokens JSON, passed through to style_check.py",
505
+ )
506
+ p.add_argument(
507
+ "--manifest", default=None,
508
+ help="FIGURE_MANIFEST.json, passed through to asset_check.py "
509
+ "(its absence makes the asset gate hard-fail)",
510
+ )
511
+ p.add_argument(
512
+ "--waive-total-area", action="store_true",
513
+ help="theory-paper waiver, passed through to asset_check.py",
514
+ )
515
+ p.add_argument(
516
+ "--no-render", action="store_true",
517
+ help="skip render-dependent checks; passed through to "
518
+ "style_check.py / asset_check.py (their render rules degrade "
519
+ "to SKIPPED / natural-size estimates)",
520
+ )
521
+ return p
522
+
523
+
524
+ def main(argv: list[str] | None = None) -> int:
525
+ args = build_parser().parse_args(argv)
526
+
527
+ html_path = Path(args.html).resolve()
528
+ if not html_path.exists():
529
+ _eprint(f"ERROR: HTML not found: {ascii_safe(html_path)}")
530
+ return 2
531
+
532
+ report = run_all(html_path, args)
533
+
534
+ report_path = (
535
+ Path(args.report).resolve()
536
+ if args.report
537
+ else html_path.parent / "GATE_REPORT.json"
538
+ )
539
+ try:
540
+ report_path.write_text(
541
+ json.dumps(report, indent=2, ensure_ascii=False) + "\n",
542
+ encoding="utf-8",
543
+ )
544
+ except OSError as exc:
545
+ _eprint(f"ERROR: cannot write report {ascii_safe(report_path)}: "
546
+ f"{ascii_safe(exc)}")
547
+ return 2
548
+
549
+ _print_human_summary(report)
550
+ print(f"[run_gates] report -> {ascii_safe(report_path)}")
551
+
552
+ return 0 if report["overall"] == "PASS" else 1
553
+
554
+
555
+ if __name__ == "__main__":
556
+ sys.exit(main())