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.
- package/LICENSE +21 -0
- package/README.md +98 -0
- package/README_CN.md +87 -0
- package/dsh/checkout.patch.yml +38 -0
- package/dsh/client.js +634 -0
- package/dsh/cordis.patch.yml +44 -0
- package/dsh/index.mjs +76 -0
- package/dsh/run-status.mjs +182 -0
- package/dsh/scope-limits.mjs +50 -0
- package/dsh/workbench.mjs +291 -0
- package/mcp-servers/claude-review/README.md +93 -0
- package/mcp-servers/claude-review/run_with_claude_aws.sh +49 -0
- package/mcp-servers/claude-review/server.py +718 -0
- package/mcp-servers/codex-image2/README.md +65 -0
- package/mcp-servers/codex-image2/server.py +893 -0
- package/mcp-servers/feishu-bridge/requirements.txt +1 -0
- package/mcp-servers/feishu-bridge/server.py +240 -0
- package/mcp-servers/gemini-review/README.md +171 -0
- package/mcp-servers/gemini-review/server.py +1856 -0
- package/mcp-servers/llm-chat/requirements.txt +1 -0
- package/mcp-servers/llm-chat/server.py +664 -0
- package/mcp-servers/manual-review/README.md +133 -0
- package/mcp-servers/manual-review/server.py +910 -0
- package/mcp-servers/manual-review/ui.html +279 -0
- package/mcp-servers/minimax-chat/requirements.txt +1 -0
- package/mcp-servers/minimax-chat/server.py +381 -0
- package/package.json +51 -0
- package/skills/ablation-planner/SKILL.md +123 -0
- package/skills/alphaxiv/SKILL.md +196 -0
- package/skills/analyze-results/SKILL.md +46 -0
- package/skills/arxiv/SKILL.md +248 -0
- package/skills/auto-paper-improvement-loop/SKILL.md +651 -0
- package/skills/auto-review-loop/SKILL.md +1137 -0
- package/skills/auto-review-loop-llm/SKILL.md +259 -0
- package/skills/auto-review-loop-minimax/SKILL.md +302 -0
- package/skills/citation-audit/SKILL.md +502 -0
- package/skills/claims-drafting/SKILL.md +227 -0
- package/skills/comm-lit-review/SKILL.md +297 -0
- package/skills/deepxiv/SKILL.md +263 -0
- package/skills/dse-loop/SKILL.md +296 -0
- package/skills/embodiment-description/SKILL.md +129 -0
- package/skills/exa-search/SKILL.md +205 -0
- package/skills/experiment-audit/SKILL.md +311 -0
- package/skills/experiment-bridge/SKILL.md +376 -0
- package/skills/experiment-plan/SKILL.md +249 -0
- package/skills/experiment-queue/SKILL.md +431 -0
- package/skills/experiment-queue/scripts/build_manifest.py +142 -0
- package/skills/experiment-queue/scripts/queue_manager.py +433 -0
- package/skills/feishu-notify/SKILL.md +156 -0
- package/skills/figure-description/SKILL.md +138 -0
- package/skills/figure-spec/SKILL.md +262 -0
- package/skills/figure-spec/scripts/figure_renderer.py +799 -0
- package/skills/formula-derivation/SKILL.md +280 -0
- package/skills/gemini-search/SKILL.md +231 -0
- package/skills/grant-proposal/SKILL.md +698 -0
- package/skills/idea-creator/SKILL.md +542 -0
- package/skills/idea-discovery/SKILL.md +521 -0
- package/skills/idea-discovery-robot/SKILL.md +363 -0
- package/skills/integrity-forensics/SKILL.md +284 -0
- package/skills/interview-cheatsheet/SKILL.md +245 -0
- package/skills/invention-structuring/SKILL.md +188 -0
- package/skills/jurisdiction-format/SKILL.md +192 -0
- package/skills/kill-argument/SKILL.md +437 -0
- package/skills/mermaid-diagram/SKILL.md +419 -0
- package/skills/meta-apply/SKILL.md +141 -0
- package/skills/meta-optimize/SKILL.md +437 -0
- package/skills/monitor-experiment/SKILL.md +140 -0
- package/skills/novelty-check/SKILL.md +101 -0
- package/skills/openalex/SKILL.md +237 -0
- package/skills/overleaf-sync/SKILL.md +220 -0
- package/skills/paper-claim-audit/SKILL.md +348 -0
- package/skills/paper-compile/SKILL.md +266 -0
- package/skills/paper-figure/SKILL.md +312 -0
- package/skills/paper-illustration/SKILL.md +736 -0
- package/skills/paper-illustration-image2/SKILL.md +391 -0
- package/skills/paper-illustration-image2/scripts/paper_illustration_image2.py +255 -0
- package/skills/paper-plan/SKILL.md +386 -0
- package/skills/paper-poster/SKILL.md +19 -0
- package/skills/paper-poster-html/DESIGN_FINAL.md +176 -0
- package/skills/paper-poster-html/IMPLEMENTATION_CONVENTIONS.md +161 -0
- package/skills/paper-poster-html/LICENSES/posterly-MIT.txt +21 -0
- package/skills/paper-poster-html/NOTICE.md +57 -0
- package/skills/paper-poster-html/SKILL.md +323 -0
- package/skills/paper-poster-html/scripts/_posterly/__init__.py +0 -0
- package/skills/paper-poster-html/scripts/_posterly/canvas.py +200 -0
- package/skills/paper-poster-html/scripts/_posterly/measure.py +588 -0
- package/skills/paper-poster-html/scripts/_posterly/polish.py +498 -0
- package/skills/paper-poster-html/scripts/_posterly/preflight.py +489 -0
- package/skills/paper-poster-html/scripts/_posterly/render.py +215 -0
- package/skills/paper-poster-html/scripts/_posterly/textutil.py +16 -0
- package/skills/paper-poster-html/scripts/_posterly/verify_final.py +171 -0
- package/skills/paper-poster-html/scripts/asset_check.py +897 -0
- package/skills/paper-poster-html/scripts/extract_pdf_figures.py +666 -0
- package/skills/paper-poster-html/scripts/poster_check.py +251 -0
- package/skills/paper-poster-html/scripts/preprocess_figures.py +238 -0
- package/skills/paper-poster-html/scripts/render_preview.py +217 -0
- package/skills/paper-poster-html/scripts/run_gates.py +556 -0
- package/skills/paper-poster-html/scripts/style_check.py +1324 -0
- package/skills/paper-poster-html/templates/COMPONENTS.md +462 -0
- package/skills/paper-poster-html/templates/README.md +170 -0
- package/skills/paper-poster-html/templates/landscape_4col.html +1032 -0
- package/skills/paper-poster-html/templates/landscape_hero.html +1046 -0
- package/skills/paper-poster-html/templates/portrait_2col.html +947 -0
- package/skills/paper-poster-html/templates/tokens/acl.json +9 -0
- package/skills/paper-poster-html/templates/tokens/cvpr.json +9 -0
- package/skills/paper-poster-html/templates/tokens/generic.json +9 -0
- package/skills/paper-poster-html/templates/tokens/iclr.json +9 -0
- package/skills/paper-poster-html/templates/tokens/icml.json +9 -0
- package/skills/paper-poster-html/templates/tokens/neurips.json +9 -0
- package/skills/paper-slides/SKILL.md +635 -0
- package/skills/paper-talk/SKILL.md +381 -0
- package/skills/paper-write/SKILL.md +604 -0
- package/skills/paper-write/templates/IEEEtran.bst +2409 -0
- package/skills/paper-write/templates/IEEEtran.cls +6347 -0
- package/skills/paper-write/templates/iclr2026.tex +84 -0
- package/skills/paper-write/templates/icml2025.tex +87 -0
- package/skills/paper-write/templates/ieee_conference.tex +89 -0
- package/skills/paper-write/templates/ieee_journal.tex +93 -0
- package/skills/paper-write/templates/math_commands.tex +48 -0
- package/skills/paper-write/templates/neurips2025.tex +80 -0
- package/skills/paper-writing/SKILL.md +916 -0
- package/skills/patent-novelty-check/SKILL.md +153 -0
- package/skills/patent-pipeline/SKILL.md +344 -0
- package/skills/patent-review/SKILL.md +203 -0
- package/skills/pixel-art/SKILL.md +137 -0
- package/skills/prior-art-search/SKILL.md +146 -0
- package/skills/proof-checker/SKILL.md +866 -0
- package/skills/proof-orchestrator/NOTICE.md +24 -0
- package/skills/proof-orchestrator/SKILL.md +254 -0
- package/skills/proof-orchestrator/references/audit-output-contract.md +126 -0
- package/skills/proof-orchestrator/references/deepseek-routing.md +74 -0
- package/skills/proof-orchestrator/references/dispatch-prompts.md +227 -0
- package/skills/proof-orchestrator/references/notation-audit.md +135 -0
- package/skills/proof-orchestrator/references/proof-audit-rubric.md +70 -0
- package/skills/proof-orchestrator/references/stress-tests.md +38 -0
- package/skills/proof-writer/SKILL.md +223 -0
- package/skills/qzcli/SKILL.md +324 -0
- package/skills/rebuttal/SKILL.md +376 -0
- package/skills/render-html/SKILL.md +316 -0
- package/skills/render-html/scripts/render_html.py +1006 -0
- package/skills/render-html/scripts/templates/academic.html +703 -0
- package/skills/render-html/scripts/templates/dashboard.html +333 -0
- package/skills/research-lit/SKILL.md +756 -0
- package/skills/research-pipeline/SKILL.md +384 -0
- package/skills/research-refine/SKILL.md +770 -0
- package/skills/research-refine-pipeline/SKILL.md +186 -0
- package/skills/research-review/SKILL.md +198 -0
- package/skills/research-wiki/SKILL.md +461 -0
- package/skills/resubmit-pipeline/SKILL.md +447 -0
- package/skills/result-to-claim/SKILL.md +311 -0
- package/skills/run-experiment/SKILL.md +313 -0
- package/skills/semantic-scholar/SKILL.md +236 -0
- package/skills/serverless-modal/SKILL.md +335 -0
- package/skills/shared-references/acceptance-gate.md +324 -0
- package/skills/shared-references/assurance-contract.md +248 -0
- package/skills/shared-references/capture-antipatterns.md +78 -0
- package/skills/shared-references/citation-discipline.md +583 -0
- package/skills/shared-references/compute-env-contract.md +163 -0
- package/skills/shared-references/effort-contract.md +183 -0
- package/skills/shared-references/evidence-precheck.md +65 -0
- package/skills/shared-references/experiment-integrity.md +49 -0
- package/skills/shared-references/external-cadence.md +326 -0
- package/skills/shared-references/fan-out-pattern.md +366 -0
- package/skills/shared-references/injection-hygiene.md +127 -0
- package/skills/shared-references/integration-contract.md +461 -0
- package/skills/shared-references/output-composition.md +93 -0
- package/skills/shared-references/output-language.md +45 -0
- package/skills/shared-references/output-manifest.md +49 -0
- package/skills/shared-references/output-versioning.md +111 -0
- package/skills/shared-references/patent-format-cn.md +199 -0
- package/skills/shared-references/patent-format-ep.md +173 -0
- package/skills/shared-references/patent-format-us.md +161 -0
- package/skills/shared-references/patent-writing-principles.md +197 -0
- package/skills/shared-references/prior-art-databases.md +141 -0
- package/skills/shared-references/resumable-runs.md +109 -0
- package/skills/shared-references/review-scope-limits.md +81 -0
- package/skills/shared-references/review-tracing.md +391 -0
- package/skills/shared-references/reviewer-independence.md +79 -0
- package/skills/shared-references/reviewer-routing.md +852 -0
- package/skills/shared-references/skill-governance.md +104 -0
- package/skills/shared-references/taste-calibration.md +85 -0
- package/skills/shared-references/venue-checklists.md +114 -0
- package/skills/shared-references/wiki-helper-resolution.md +134 -0
- package/skills/shared-references/writing-principles.md +525 -0
- package/skills/skills-codex/README.md +102 -0
- package/skills/skills-codex/README_CN.md +100 -0
- package/skills/skills-codex/ablation-planner/SKILL.md +126 -0
- package/skills/skills-codex/alphaxiv/SKILL.md +186 -0
- package/skills/skills-codex/analyze-results/SKILL.md +45 -0
- package/skills/skills-codex/arxiv/SKILL.md +210 -0
- package/skills/skills-codex/auto-paper-improvement-loop/SKILL.md +574 -0
- package/skills/skills-codex/auto-review-loop/SKILL.md +500 -0
- package/skills/skills-codex/auto-review-loop-llm/SKILL.md +247 -0
- package/skills/skills-codex/auto-review-loop-minimax/SKILL.md +290 -0
- package/skills/skills-codex/citation-audit/SKILL.md +504 -0
- package/skills/skills-codex/claims-drafting/SKILL.md +239 -0
- package/skills/skills-codex/comm-lit-review/SKILL.md +299 -0
- package/skills/skills-codex/comm-lit-review/references/domain-taxonomy.md +57 -0
- package/skills/skills-codex/comm-lit-review/references/output-template.md +37 -0
- package/skills/skills-codex/comm-lit-review/references/source-policy.md +99 -0
- package/skills/skills-codex/comm-lit-review/references/venue-tiering.md +112 -0
- package/skills/skills-codex/deepxiv/SKILL.md +142 -0
- package/skills/skills-codex/dse-loop/SKILL.md +285 -0
- package/skills/skills-codex/embodiment-description/SKILL.md +129 -0
- package/skills/skills-codex/exa-search/SKILL.md +192 -0
- package/skills/skills-codex/experiment-audit/SKILL.md +286 -0
- package/skills/skills-codex/experiment-bridge/SKILL.md +356 -0
- package/skills/skills-codex/experiment-plan/SKILL.md +249 -0
- package/skills/skills-codex/experiment-queue/SKILL.md +401 -0
- package/skills/skills-codex/feishu-notify/SKILL.md +155 -0
- package/skills/skills-codex/figure-description/SKILL.md +138 -0
- package/skills/skills-codex/figure-spec/SKILL.md +252 -0
- package/skills/skills-codex/formula-derivation/SKILL.md +280 -0
- package/skills/skills-codex/gemini-search/SKILL.md +205 -0
- package/skills/skills-codex/grant-proposal/SKILL.md +626 -0
- package/skills/skills-codex/idea-creator/SKILL.md +405 -0
- package/skills/skills-codex/idea-discovery/SKILL.md +475 -0
- package/skills/skills-codex/idea-discovery-robot/SKILL.md +362 -0
- package/skills/skills-codex/integrity-forensics/SKILL.md +106 -0
- package/skills/skills-codex/interview-cheatsheet/SKILL.md +245 -0
- package/skills/skills-codex/invention-structuring/SKILL.md +188 -0
- package/skills/skills-codex/jurisdiction-format/SKILL.md +192 -0
- package/skills/skills-codex/kill-argument/SKILL.md +403 -0
- package/skills/skills-codex/mermaid-diagram/SKILL.md +379 -0
- package/skills/skills-codex/meta-apply/SKILL.md +154 -0
- package/skills/skills-codex/meta-optimize/SKILL.md +348 -0
- package/skills/skills-codex/monitor-experiment/SKILL.md +98 -0
- package/skills/skills-codex/novelty-check/SKILL.md +89 -0
- package/skills/skills-codex/openalex/SKILL.md +228 -0
- package/skills/skills-codex/overleaf-sync/SKILL.md +220 -0
- package/skills/skills-codex/paper-claim-audit/SKILL.md +350 -0
- package/skills/skills-codex/paper-compile/SKILL.md +253 -0
- package/skills/skills-codex/paper-figure/SKILL.md +311 -0
- package/skills/skills-codex/paper-illustration/SKILL.md +690 -0
- package/skills/skills-codex/paper-illustration-image2/SKILL.md +383 -0
- package/skills/skills-codex/paper-illustration-image2/scripts/paper_illustration_image2.py +255 -0
- package/skills/skills-codex/paper-plan/SKILL.md +278 -0
- package/skills/skills-codex/paper-poster/SKILL.md +19 -0
- package/skills/skills-codex/paper-poster-html/SKILL.md +377 -0
- package/skills/skills-codex/paper-slides/SKILL.md +571 -0
- package/skills/skills-codex/paper-talk/SKILL.md +381 -0
- package/skills/skills-codex/paper-write/SKILL.md +411 -0
- package/skills/skills-codex/paper-write/templates/IEEEtran.bst +2409 -0
- package/skills/skills-codex/paper-write/templates/IEEEtran.cls +6347 -0
- package/skills/skills-codex/paper-write/templates/aaai2026.bst +1493 -0
- package/skills/skills-codex/paper-write/templates/aaai2026.sty +315 -0
- package/skills/skills-codex/paper-write/templates/aaai2026.tex +952 -0
- package/skills/skills-codex/paper-write/templates/acl.sty +312 -0
- package/skills/skills-codex/paper-write/templates/acl2026.tex +377 -0
- package/skills/skills-codex/paper-write/templates/acl_natbib.bst +1940 -0
- package/skills/skills-codex/paper-write/templates/acm.bst +3081 -0
- package/skills/skills-codex/paper-write/templates/acm_mm2026.tex +204 -0
- package/skills/skills-codex/paper-write/templates/acmart.cls +3520 -0
- package/skills/skills-codex/paper-write/templates/cvpr.bst +1448 -0
- package/skills/skills-codex/paper-write/templates/cvpr.sty +508 -0
- package/skills/skills-codex/paper-write/templates/cvpr2026.tex +63 -0
- package/skills/skills-codex/paper-write/templates/iclr2026.tex +84 -0
- package/skills/skills-codex/paper-write/templates/iclr2026_conference.bst +1440 -0
- package/skills/skills-codex/paper-write/templates/iclr2026_conference.sty +246 -0
- package/skills/skills-codex/paper-write/templates/icml2026.sty +767 -0
- package/skills/skills-codex/paper-write/templates/icml2026.tex +662 -0
- package/skills/skills-codex/paper-write/templates/ieee_conference.tex +89 -0
- package/skills/skills-codex/paper-write/templates/ieee_journal.tex +93 -0
- package/skills/skills-codex/paper-write/templates/math_commands.tex +48 -0
- package/skills/skills-codex/paper-write/templates/neurips2026.tex +493 -0
- package/skills/skills-codex/paper-write/templates/neurips_2026.sty +437 -0
- package/skills/skills-codex/paper-writing/SKILL.md +731 -0
- package/skills/skills-codex/patent-novelty-check/SKILL.md +153 -0
- package/skills/skills-codex/patent-pipeline/SKILL.md +344 -0
- package/skills/skills-codex/patent-review/SKILL.md +202 -0
- package/skills/skills-codex/pixel-art/SKILL.md +139 -0
- package/skills/skills-codex/prior-art-search/SKILL.md +146 -0
- package/skills/skills-codex/proof-checker/SKILL.md +554 -0
- package/skills/skills-codex/proof-orchestrator/SKILL.md +260 -0
- package/skills/skills-codex/proof-orchestrator/references/audit-output-contract.md +126 -0
- package/skills/skills-codex/proof-orchestrator/references/deepseek-routing.md +76 -0
- package/skills/skills-codex/proof-orchestrator/references/dispatch-prompts.md +227 -0
- package/skills/skills-codex/proof-orchestrator/references/notation-audit.md +135 -0
- package/skills/skills-codex/proof-orchestrator/references/proof-audit-rubric.md +70 -0
- package/skills/skills-codex/proof-orchestrator/references/stress-tests.md +38 -0
- package/skills/skills-codex/proof-writer/SKILL.md +222 -0
- package/skills/skills-codex/qzcli/SKILL.md +324 -0
- package/skills/skills-codex/rebuttal/SKILL.md +305 -0
- package/skills/skills-codex/render-html/SKILL.md +305 -0
- package/skills/skills-codex/render-html/scripts/__pycache__/render_html.cpython-314.pyc +0 -0
- package/skills/skills-codex/render-html/scripts/render_html.py +909 -0
- package/skills/skills-codex/render-html/scripts/templates/academic.html +342 -0
- package/skills/skills-codex/render-html/scripts/templates/dashboard.html +333 -0
- package/skills/skills-codex/research-lit/SKILL.md +464 -0
- package/skills/skills-codex/research-pipeline/SKILL.md +340 -0
- package/skills/skills-codex/research-refine/SKILL.md +721 -0
- package/skills/skills-codex/research-refine-pipeline/SKILL.md +186 -0
- package/skills/skills-codex/research-review/SKILL.md +135 -0
- package/skills/skills-codex/research-wiki/SKILL.md +421 -0
- package/skills/skills-codex/resubmit-pipeline/SKILL.md +444 -0
- package/skills/skills-codex/result-to-claim/SKILL.md +246 -0
- package/skills/skills-codex/run-experiment/SKILL.md +236 -0
- package/skills/skills-codex/semantic-scholar/SKILL.md +219 -0
- package/skills/skills-codex/serverless-modal/SKILL.md +335 -0
- package/skills/skills-codex/shared-references/acceptance-gate.md +336 -0
- package/skills/skills-codex/shared-references/assurance-contract.md +139 -0
- package/skills/skills-codex/shared-references/capture-antipatterns.md +84 -0
- package/skills/skills-codex/shared-references/citation-discipline.md +452 -0
- package/skills/skills-codex/shared-references/compute-env-contract.md +163 -0
- package/skills/skills-codex/shared-references/effort-contract.md +143 -0
- package/skills/skills-codex/shared-references/evidence-precheck.md +73 -0
- package/skills/skills-codex/shared-references/experiment-integrity.md +49 -0
- package/skills/skills-codex/shared-references/external-cadence.md +334 -0
- package/skills/skills-codex/shared-references/fan-out-pattern.md +375 -0
- package/skills/skills-codex/shared-references/injection-hygiene.md +132 -0
- package/skills/skills-codex/shared-references/integration-contract.md +372 -0
- package/skills/skills-codex/shared-references/output-composition.md +98 -0
- package/skills/skills-codex/shared-references/output-language.md +45 -0
- package/skills/skills-codex/shared-references/output-manifest.md +40 -0
- package/skills/skills-codex/shared-references/output-versioning.md +111 -0
- package/skills/skills-codex/shared-references/patent-format-cn.md +199 -0
- package/skills/skills-codex/shared-references/patent-format-ep.md +173 -0
- package/skills/skills-codex/shared-references/patent-format-us.md +161 -0
- package/skills/skills-codex/shared-references/patent-writing-principles.md +197 -0
- package/skills/skills-codex/shared-references/prior-art-databases.md +141 -0
- package/skills/skills-codex/shared-references/resumable-runs.md +125 -0
- package/skills/skills-codex/shared-references/review-scope-limits.md +81 -0
- package/skills/skills-codex/shared-references/review-tracing.md +144 -0
- package/skills/skills-codex/shared-references/reviewer-independence.md +66 -0
- package/skills/skills-codex/shared-references/reviewer-routing.md +128 -0
- package/skills/skills-codex/shared-references/skill-governance.md +119 -0
- package/skills/skills-codex/shared-references/taste-calibration.md +90 -0
- package/skills/skills-codex/shared-references/venue-checklists.md +73 -0
- package/skills/skills-codex/shared-references/wiki-helper-resolution.md +69 -0
- package/skills/skills-codex/shared-references/writing-principles.md +525 -0
- package/skills/skills-codex/slides-polish/SKILL.md +563 -0
- package/skills/skills-codex/specification-writing/SKILL.md +211 -0
- package/skills/skills-codex/system-profile/SKILL.md +103 -0
- package/skills/skills-codex/training-check/SKILL.md +83 -0
- package/skills/skills-codex/vast-gpu/SKILL.md +394 -0
- package/skills/skills-codex/web-debug-search/SKILL.md +334 -0
- package/skills/skills-codex/wiki-enrich/SKILL.md +255 -0
- package/skills/skills-codex/writing-systems-papers/SKILL.md +184 -0
- package/skills/skills-codex-claude-review/README.md +79 -0
- package/skills/skills-codex-claude-review/README_CN.md +78 -0
- package/skills/skills-codex-claude-review/auto-paper-improvement-loop/SKILL.md +581 -0
- package/skills/skills-codex-claude-review/auto-review-loop/SKILL.md +510 -0
- package/skills/skills-codex-claude-review/novelty-check/SKILL.md +102 -0
- package/skills/skills-codex-claude-review/paper-figure/SKILL.md +319 -0
- package/skills/skills-codex-claude-review/paper-plan/SKILL.md +287 -0
- package/skills/skills-codex-claude-review/paper-write/SKILL.md +420 -0
- package/skills/skills-codex-claude-review/research-refine/SKILL.md +732 -0
- package/skills/skills-codex-claude-review/research-review/SKILL.md +149 -0
- package/skills/skills-codex-gemini-review/README.md +176 -0
- package/skills/skills-codex-gemini-review/README_CN.md +175 -0
- package/skills/skills-codex-gemini-review/auto-paper-improvement-loop/SKILL.md +331 -0
- package/skills/skills-codex-gemini-review/auto-review-loop/SKILL.md +304 -0
- package/skills/skills-codex-gemini-review/grant-proposal/SKILL.md +630 -0
- package/skills/skills-codex-gemini-review/idea-creator/SKILL.md +263 -0
- package/skills/skills-codex-gemini-review/idea-discovery/SKILL.md +275 -0
- package/skills/skills-codex-gemini-review/idea-discovery-robot/SKILL.md +365 -0
- package/skills/skills-codex-gemini-review/novelty-check/SKILL.md +92 -0
- package/skills/skills-codex-gemini-review/paper-figure/SKILL.md +289 -0
- package/skills/skills-codex-gemini-review/paper-plan/SKILL.md +265 -0
- package/skills/skills-codex-gemini-review/paper-poster-html/SKILL.md +102 -0
- package/skills/skills-codex-gemini-review/paper-slides/SKILL.md +582 -0
- package/skills/skills-codex-gemini-review/paper-write/SKILL.md +346 -0
- package/skills/skills-codex-gemini-review/paper-writing/SKILL.md +312 -0
- package/skills/skills-codex-gemini-review/research-refine/SKILL.md +674 -0
- package/skills/skills-codex-gemini-review/research-review/SKILL.md +112 -0
- package/skills/slides-polish/SKILL.md +565 -0
- package/skills/specification-writing/SKILL.md +211 -0
- package/skills/system-profile/SKILL.md +103 -0
- package/skills/training-check/SKILL.md +132 -0
- package/skills/vast-gpu/SKILL.md +394 -0
- package/skills/web-debug-search/SKILL.md +334 -0
- package/skills/wiki-enrich/SKILL.md +257 -0
- package/skills/writing-systems-papers/SKILL.md +184 -0
- package/templates/CLAUDE_MD_TEMPLATE.md +29 -0
- package/templates/EXPERIMENT_LOG_TEMPLATE.md +47 -0
- package/templates/EXPERIMENT_PLAN_TEMPLATE.md +51 -0
- package/templates/EXPERIMENT_PLAN_TEMPLATE_CN.md +53 -0
- package/templates/FINDINGS_TEMPLATE.md +52 -0
- package/templates/IDEA_CANDIDATES_TEMPLATE.md +47 -0
- package/templates/IDEA_CANDIDATES_TEMPLATE_CN.md +47 -0
- package/templates/INVENTION_BRIEF_TEMPLATE.md +87 -0
- package/templates/MANIFEST_TEMPLATE.md +7 -0
- package/templates/NARRATIVE_REPORT_TEMPLATE.md +49 -0
- package/templates/PAPER_PLAN_TEMPLATE.md +47 -0
- package/templates/PATENT_CLAIMS_TEMPLATE.md +78 -0
- package/templates/PATENT_SPECIFICATION_TEMPLATE.md +68 -0
- package/templates/README.md +57 -0
- package/templates/RESEARCH_BRIEF_TEMPLATE.md +35 -0
- package/templates/RESEARCH_BRIEF_TEMPLATE_CN.md +41 -0
- package/templates/RESEARCH_CONTRACT_TEMPLATE.md +60 -0
- package/templates/claude-hooks/corpus_write_guard.json +16 -0
- package/templates/claude-hooks/corpus_write_guard.py +85 -0
- package/templates/claude-hooks/meta_logging.json +74 -0
- package/templates/gitignore-trace.txt +3 -0
- package/tools/__pycache__/check_skills_inventory.cpython-314.pyc +0 -0
- package/tools/arxiv_fetch.py +311 -0
- package/tools/capture_filter.py +126 -0
- package/tools/check_skills_inventory.py +273 -0
- package/tools/convert_skills_to_llm_chat.py +282 -0
- package/tools/copilot_native_evidence.py +818 -0
- package/tools/deepxiv_fetch.py +213 -0
- package/tools/evidence_check.py +212 -0
- package/tools/exa_search.py +425 -0
- package/tools/experiment_queue/README.md +118 -0
- package/tools/experiment_queue/build_manifest.py +44 -0
- package/tools/experiment_queue/queue_manager.py +44 -0
- package/tools/extract_paper_style.py +560 -0
- package/tools/figure_renderer.py +69 -0
- package/tools/forensics_gate.py +669 -0
- package/tools/generate_codex_claude_review_overrides.py +299 -0
- package/tools/idea_discovery_gate.py +256 -0
- package/tools/install_aris.ps1 +1372 -0
- package/tools/install_aris.sh +1370 -0
- package/tools/install_aris_codex.sh +1023 -0
- package/tools/install_aris_copilot.sh +1052 -0
- package/tools/iteration_log.py +143 -0
- package/tools/lint_skills_helpers.sh +84 -0
- package/tools/meta_opt/check_ready.sh +80 -0
- package/tools/meta_opt/log_event.sh +91 -0
- package/tools/meta_opt/trigger_eval.py +280 -0
- package/tools/meta_opt/trigger_evals.sample.json +28 -0
- package/tools/openalex_fetch.py +326 -0
- package/tools/overleaf_audit.sh +104 -0
- package/tools/overleaf_setup.sh +150 -0
- package/tools/paper_illustration_image2.py +62 -0
- package/tools/provenance.py +294 -0
- package/tools/research_wiki.py +1720 -0
- package/tools/review_gate.py +502 -0
- package/tools/run_state.py +399 -0
- package/tools/save_trace.sh +477 -0
- package/tools/semantic_scholar_fetch.py +438 -0
- package/tools/skill-groups.tsv +116 -0
- package/tools/skill_picker.py +238 -0
- package/tools/smart_update.ps1 +521 -0
- package/tools/smart_update.sh +591 -0
- package/tools/smart_update_codex.sh +419 -0
- package/tools/smart_update_copilot.sh +605 -0
- package/tools/threat_scan.py +222 -0
- package/tools/verify_paper_audits.sh +487 -0
- package/tools/verify_papers.py +613 -0
- package/tools/verify_wiki_coverage.sh +176 -0
- 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())
|