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,560 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
extract_paper_style.py — extract a *skeleton-only* style profile from a
|
|
4
|
+
reference paper, for opt-in use by writer skills via the `--style-ref` flag.
|
|
5
|
+
|
|
6
|
+
================================================================
|
|
7
|
+
CONTRACT (read this before consuming the output in a writer skill)
|
|
8
|
+
================================================================
|
|
9
|
+
|
|
10
|
+
Purpose
|
|
11
|
+
-------
|
|
12
|
+
Some users want a generated paper / poster / slide / grant draft to *match
|
|
13
|
+
the structural style* of a reference paper they admire (section ordering,
|
|
14
|
+
section name conventions, sentence-length cadence, theorem density, figure
|
|
15
|
+
density, bibliography style, etc.) — *without* copying the reference's prose
|
|
16
|
+
or claims. This helper resolves the reference, derives a compact, neutral
|
|
17
|
+
"style profile", and writes it to a deterministic cache path.
|
|
18
|
+
|
|
19
|
+
Writer skills that accept `--style-ref <source>`:
|
|
20
|
+
- paper-write, paper-plan, paper-writing
|
|
21
|
+
- paper-illustration, paper-slides
|
|
22
|
+
- grant-proposal, auto-paper-improvement-loop
|
|
23
|
+
|
|
24
|
+
Strict rules for the calling skill
|
|
25
|
+
----------------------------------
|
|
26
|
+
1. **Opt-in only.** When the user does NOT pass `--style-ref`, behavior is
|
|
27
|
+
unchanged. Do not auto-discover reference papers from the working tree.
|
|
28
|
+
|
|
29
|
+
2. **Run this script first**, before drafting:
|
|
30
|
+
python3 tools/extract_paper_style.py --source <SRC> [--out <DIR>]
|
|
31
|
+
On exit code 0, read the printed cache directory and consume:
|
|
32
|
+
<cache>/source_manifest.json (provenance)
|
|
33
|
+
<cache>/style_profile.md (the style guidance)
|
|
34
|
+
On exit code 2 (missing optional dep), print a one-line warning and
|
|
35
|
+
continue without style guidance.
|
|
36
|
+
On exit code 3 (source failure), print the error and FAIL the writer
|
|
37
|
+
step — do NOT silently fall back, the user explicitly asked for a ref.
|
|
38
|
+
|
|
39
|
+
3. **Use the profile as STRUCTURAL guidance only.** Do not copy sentences,
|
|
40
|
+
phrases, claim bullets, or any concrete content from anything reachable
|
|
41
|
+
through the cache. The profile is intentionally aggregate / statistical;
|
|
42
|
+
if you find yourself reaching for copied prose, stop.
|
|
43
|
+
|
|
44
|
+
4. **Never pass `--style-ref` to reviewer / auditor sub-agents.**
|
|
45
|
+
Cross-model review independence (`shared-references/reviewer-independence.md`)
|
|
46
|
+
requires reviewers see only the artifact and the user's prompt, not the
|
|
47
|
+
author's stylistic context. Style ref is a *writer-side* affordance.
|
|
48
|
+
|
|
49
|
+
5. **Cache is deterministic.** Same source → same cache dir. The calling
|
|
50
|
+
skill should pass the resolved cache path explicitly when invoking
|
|
51
|
+
sub-tools that need it; it should NOT mutate the cache.
|
|
52
|
+
|
|
53
|
+
Source types accepted
|
|
54
|
+
---------------------
|
|
55
|
+
- Local directory: /path/to/paper/ (scans *.tex)
|
|
56
|
+
- Local TeX file: /path/to/paper.tex
|
|
57
|
+
- Local PDF file: /path/to/paper.pdf (uses pdftotext if installed)
|
|
58
|
+
- arXiv ID: arxiv:2501.12345 (fetches abstract HTML)
|
|
59
|
+
(also: 2501.12345 alone is auto-detected)
|
|
60
|
+
- HTTP/HTTPS URL: https://... (PDF or HTML)
|
|
61
|
+
- Overleaf URL/ID: https://www.overleaf.com/project/<id>
|
|
62
|
+
↑ rejected with guidance: clone via overleaf-sync
|
|
63
|
+
first, then pass the local clone path.
|
|
64
|
+
|
|
65
|
+
Output schema
|
|
66
|
+
-------------
|
|
67
|
+
<cache>/source_manifest.json:
|
|
68
|
+
{
|
|
69
|
+
"source_input": "<original argument>",
|
|
70
|
+
"source_type": "local_dir|local_tex|local_pdf|arxiv|http",
|
|
71
|
+
"resolved_path": "<absolute path or URL>",
|
|
72
|
+
"fetched_at": "<ISO 8601 UTC>",
|
|
73
|
+
"content_sha256": "<hex>",
|
|
74
|
+
"tool_version": "1"
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
<cache>/style_profile.md:
|
|
78
|
+
Compact markdown (≤ ~200 lines). Sections:
|
|
79
|
+
- Section structure (ordered list of sec names)
|
|
80
|
+
- Length distribution (per-section approx word counts)
|
|
81
|
+
- Theorem-environment density
|
|
82
|
+
- Figure / table density
|
|
83
|
+
- Citation density and style (numeric vs author-year, if detectable)
|
|
84
|
+
- Sentence cadence (mean/median/p90 word count)
|
|
85
|
+
- Math display ratio (inline vs display)
|
|
86
|
+
- Captioning conventions (caption length stats)
|
|
87
|
+
- Notable structural patterns (e.g., "Contributions" bullet block,
|
|
88
|
+
"Setup → Result → Interpretation" theorem rhythm)
|
|
89
|
+
Explicitly NOT included: any copied sentences, claim text, author names,
|
|
90
|
+
affiliations, acknowledgements, or specific numerical results.
|
|
91
|
+
|
|
92
|
+
Cache layout
|
|
93
|
+
------------
|
|
94
|
+
Default cache root: $ARIS_STYLE_REF_CACHE (env) or `~/.cache/aris-style-refs/`
|
|
95
|
+
(XDG-friendly; avoids polluting the user's project repo
|
|
96
|
+
when the user runs the writer skill from inside their
|
|
97
|
+
paper directory)
|
|
98
|
+
Per-source dir: <root>/<sha256(source_input)[:16]>/
|
|
99
|
+
source_manifest.json
|
|
100
|
+
style_profile.md
|
|
101
|
+
|
|
102
|
+
Exit codes
|
|
103
|
+
----------
|
|
104
|
+
0 — success (cache written; cache path printed to stdout, last line)
|
|
105
|
+
2 — missing optional Python dep; nothing written (caller may continue)
|
|
106
|
+
3 — source resolution / network / parse failure (caller should fail)
|
|
107
|
+
1 — generic runtime error
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
from __future__ import annotations
|
|
111
|
+
|
|
112
|
+
import argparse
|
|
113
|
+
import datetime as _dt
|
|
114
|
+
import hashlib
|
|
115
|
+
import io
|
|
116
|
+
import json
|
|
117
|
+
import os
|
|
118
|
+
import re
|
|
119
|
+
import shutil
|
|
120
|
+
import statistics
|
|
121
|
+
import subprocess
|
|
122
|
+
import sys
|
|
123
|
+
from pathlib import Path
|
|
124
|
+
from typing import Any
|
|
125
|
+
|
|
126
|
+
TOOL_VERSION = "1"
|
|
127
|
+
ARXIV_ID_RE = re.compile(r"^\d{4}\.\d{4,5}(v\d+)?$")
|
|
128
|
+
# Match any URL whose host is overleaf.com (or *.overleaf.com) AND whose path
|
|
129
|
+
# contains "/project/...". Rejects regardless of trailing slash, query string,
|
|
130
|
+
# fragment, or extra path segments like "/file/main.tex".
|
|
131
|
+
OVERLEAF_URL_RE = re.compile(
|
|
132
|
+
r"^https?://([A-Za-z0-9-]+\.)*overleaf\.com(:\d+)?/project(/|$)",
|
|
133
|
+
re.IGNORECASE,
|
|
134
|
+
)
|
|
135
|
+
# Bare hex blob that looks like an Overleaf project id (24+ hex chars, no path).
|
|
136
|
+
OVERLEAF_BARE_ID_RE = re.compile(r"^[A-Fa-f0-9]{24,}$")
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# ---------------------------------------------------------------------------
|
|
140
|
+
# Source resolution
|
|
141
|
+
# ---------------------------------------------------------------------------
|
|
142
|
+
|
|
143
|
+
def _classify_source(src: str) -> str:
|
|
144
|
+
if OVERLEAF_URL_RE.match(src) or OVERLEAF_BARE_ID_RE.match(src):
|
|
145
|
+
return "overleaf"
|
|
146
|
+
if src.startswith("arxiv:"):
|
|
147
|
+
return "arxiv"
|
|
148
|
+
if ARXIV_ID_RE.match(src):
|
|
149
|
+
return "arxiv"
|
|
150
|
+
if src.startswith("http://") or src.startswith("https://"):
|
|
151
|
+
return "http"
|
|
152
|
+
p = Path(src).expanduser()
|
|
153
|
+
if p.is_dir():
|
|
154
|
+
return "local_dir"
|
|
155
|
+
if p.is_file():
|
|
156
|
+
if p.suffix.lower() == ".pdf":
|
|
157
|
+
return "local_pdf"
|
|
158
|
+
return "local_tex"
|
|
159
|
+
return "unknown"
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _read_local_dir(p: Path) -> str:
|
|
163
|
+
parts: list[str] = []
|
|
164
|
+
tex_files = sorted(p.rglob("*.tex"))
|
|
165
|
+
if not tex_files:
|
|
166
|
+
raise SourceError(f"No .tex files under {p}")
|
|
167
|
+
for f in tex_files:
|
|
168
|
+
try:
|
|
169
|
+
parts.append(f.read_text(encoding="utf-8", errors="replace"))
|
|
170
|
+
except Exception:
|
|
171
|
+
continue
|
|
172
|
+
return "\n\n% --- file boundary ---\n\n".join(parts)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def _read_local_tex(p: Path) -> str:
|
|
176
|
+
return p.read_text(encoding="utf-8", errors="replace")
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _read_local_pdf(p: Path) -> str:
|
|
180
|
+
if not shutil.which("pdftotext"):
|
|
181
|
+
raise MissingDep("pdftotext (poppler) is required to read PDFs")
|
|
182
|
+
out = subprocess.run(
|
|
183
|
+
["pdftotext", "-layout", str(p), "-"],
|
|
184
|
+
capture_output=True,
|
|
185
|
+
timeout=120,
|
|
186
|
+
)
|
|
187
|
+
if out.returncode != 0:
|
|
188
|
+
raise SourceError(f"pdftotext failed: {out.stderr.decode(errors='replace')[:200]}")
|
|
189
|
+
return out.stdout.decode("utf-8", errors="replace")
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _read_arxiv(arxiv_id: str) -> str:
|
|
193
|
+
try:
|
|
194
|
+
import requests
|
|
195
|
+
except ImportError:
|
|
196
|
+
raise MissingDep("requests (pip install requests) needed for arXiv fetch")
|
|
197
|
+
arxiv_id = arxiv_id.removeprefix("arxiv:")
|
|
198
|
+
url = f"https://export.arxiv.org/abs/{arxiv_id}"
|
|
199
|
+
try:
|
|
200
|
+
r = requests.get(url, timeout=20, headers={"User-Agent": "aris-extract-paper-style/1"})
|
|
201
|
+
except Exception as e:
|
|
202
|
+
raise SourceError(f"arXiv fetch failed: {e}")
|
|
203
|
+
if r.status_code != 200:
|
|
204
|
+
raise SourceError(f"arXiv fetch returned HTTP {r.status_code}")
|
|
205
|
+
return r.text
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def _read_http(url: str) -> str:
|
|
209
|
+
try:
|
|
210
|
+
import requests
|
|
211
|
+
except ImportError:
|
|
212
|
+
raise MissingDep("requests (pip install requests) needed for HTTP fetch")
|
|
213
|
+
try:
|
|
214
|
+
r = requests.get(url, timeout=30, headers={"User-Agent": "aris-extract-paper-style/1"})
|
|
215
|
+
except Exception as e:
|
|
216
|
+
raise SourceError(f"HTTP fetch failed: {e}")
|
|
217
|
+
if r.status_code != 200:
|
|
218
|
+
raise SourceError(f"HTTP fetch returned HTTP {r.status_code}")
|
|
219
|
+
ctype = r.headers.get("content-type", "").lower()
|
|
220
|
+
if "pdf" in ctype or url.lower().endswith(".pdf"):
|
|
221
|
+
if not shutil.which("pdftotext"):
|
|
222
|
+
raise MissingDep("pdftotext (poppler) needed to parse downloaded PDF")
|
|
223
|
+
with subprocess.Popen(
|
|
224
|
+
["pdftotext", "-layout", "-", "-"],
|
|
225
|
+
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
226
|
+
) as proc:
|
|
227
|
+
stdout, _ = proc.communicate(input=r.content, timeout=120)
|
|
228
|
+
if proc.returncode != 0:
|
|
229
|
+
raise SourceError("pdftotext failed on downloaded PDF")
|
|
230
|
+
return stdout.decode("utf-8", errors="replace")
|
|
231
|
+
return r.text
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
# ---------------------------------------------------------------------------
|
|
235
|
+
# Style extraction
|
|
236
|
+
# ---------------------------------------------------------------------------
|
|
237
|
+
|
|
238
|
+
SECTION_RE = re.compile(r"\\section\*?\{([^}]*)\}")
|
|
239
|
+
SUBSECTION_RE = re.compile(r"\\subsection\*?\{([^}]*)\}")
|
|
240
|
+
THM_RE = re.compile(
|
|
241
|
+
r"\\begin\{(theorem|lemma|proposition|corollary|definition|assumption|remark)\}",
|
|
242
|
+
re.IGNORECASE,
|
|
243
|
+
)
|
|
244
|
+
FIG_RE = re.compile(r"\\begin\{figure\*?\}")
|
|
245
|
+
TAB_RE = re.compile(r"\\begin\{table\*?\}")
|
|
246
|
+
CAPTION_RE = re.compile(r"\\caption\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}")
|
|
247
|
+
CITE_RE = re.compile(r"\\cite[a-zA-Z]*\*?\{([^}]+)\}")
|
|
248
|
+
DISPLAY_MATH_RE = re.compile(r"\\begin\{(equation|align|gather|multline)\*?\}")
|
|
249
|
+
INLINE_MATH_RE = re.compile(r"(?<!\\)\$[^$]+?(?<!\\)\$")
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def _strip_tex(text: str) -> str:
|
|
253
|
+
"""Strip TeX commands to leave roughly natural-language prose for sentence stats."""
|
|
254
|
+
text = re.sub(r"\\begin\{[^}]+\}.*?\\end\{[^}]+\}", " ", text, flags=re.DOTALL)
|
|
255
|
+
text = re.sub(r"%.*", " ", text)
|
|
256
|
+
text = re.sub(r"\\[a-zA-Z]+\*?(\[[^\]]*\])?(\{[^}]*\})*", " ", text)
|
|
257
|
+
text = re.sub(r"[{}]", " ", text)
|
|
258
|
+
text = re.sub(r"\$[^$]*\$", " MATHEXPR ", text)
|
|
259
|
+
text = re.sub(r"\s+", " ", text)
|
|
260
|
+
return text
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def _sentence_stats(prose: str) -> dict[str, Any]:
|
|
264
|
+
sentences = re.split(r"(?<=[.!?])\s+", prose.strip())
|
|
265
|
+
sentences = [s for s in sentences if len(s) > 4]
|
|
266
|
+
if not sentences:
|
|
267
|
+
return {"count": 0, "mean_words": 0, "median_words": 0, "p90_words": 0}
|
|
268
|
+
word_counts = [len(s.split()) for s in sentences]
|
|
269
|
+
word_counts_sorted = sorted(word_counts)
|
|
270
|
+
p90_idx = max(0, int(0.9 * len(word_counts_sorted)) - 1)
|
|
271
|
+
return {
|
|
272
|
+
"count": len(sentences),
|
|
273
|
+
"mean_words": round(statistics.mean(word_counts), 1),
|
|
274
|
+
"median_words": int(statistics.median(word_counts)),
|
|
275
|
+
"p90_words": word_counts_sorted[p90_idx],
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def _build_profile(src_kind: str, raw: str) -> str:
|
|
280
|
+
"""Generate a markdown style profile. Skeleton-only; no copied prose."""
|
|
281
|
+
if src_kind in ("local_dir", "local_tex"):
|
|
282
|
+
return _profile_from_tex(raw)
|
|
283
|
+
return _profile_from_text(raw)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def _profile_from_tex(tex: str) -> str:
|
|
287
|
+
sections = SECTION_RE.findall(tex)
|
|
288
|
+
subsecs = SUBSECTION_RE.findall(tex)
|
|
289
|
+
thm_kinds = THM_RE.findall(tex)
|
|
290
|
+
n_fig = len(FIG_RE.findall(tex))
|
|
291
|
+
n_tab = len(TAB_RE.findall(tex))
|
|
292
|
+
captions = CAPTION_RE.findall(tex)
|
|
293
|
+
citations = CITE_RE.findall(tex)
|
|
294
|
+
n_display = len(DISPLAY_MATH_RE.findall(tex))
|
|
295
|
+
n_inline = len(INLINE_MATH_RE.findall(tex))
|
|
296
|
+
|
|
297
|
+
cite_keys: list[str] = []
|
|
298
|
+
for c in citations:
|
|
299
|
+
for k in c.split(","):
|
|
300
|
+
cite_keys.append(k.strip())
|
|
301
|
+
|
|
302
|
+
prose = _strip_tex(tex)
|
|
303
|
+
sstats = _sentence_stats(prose)
|
|
304
|
+
|
|
305
|
+
section_word_counts: list[tuple[str, int]] = []
|
|
306
|
+
parts = re.split(SECTION_RE, tex)
|
|
307
|
+
if len(parts) >= 3:
|
|
308
|
+
for i in range(1, len(parts) - 1, 2):
|
|
309
|
+
name = parts[i]
|
|
310
|
+
body = parts[i + 1] if i + 1 < len(parts) else ""
|
|
311
|
+
wc = len(_strip_tex(body).split())
|
|
312
|
+
section_word_counts.append((name, wc))
|
|
313
|
+
|
|
314
|
+
caption_lens = [len(c.split()) for c in captions] if captions else []
|
|
315
|
+
caption_summary = ""
|
|
316
|
+
if caption_lens:
|
|
317
|
+
caption_summary = (
|
|
318
|
+
f"- Captions: {len(caption_lens)} captions, "
|
|
319
|
+
f"mean {round(statistics.mean(caption_lens), 1)} words, "
|
|
320
|
+
f"median {int(statistics.median(caption_lens))} words"
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
thm_counter: dict[str, int] = {}
|
|
324
|
+
for k in thm_kinds:
|
|
325
|
+
thm_counter[k.lower()] = thm_counter.get(k.lower(), 0) + 1
|
|
326
|
+
|
|
327
|
+
md = ["# Style profile (skeleton-only)\n"]
|
|
328
|
+
md.append("**Use as structural guidance for the writer agent. Do NOT copy prose.**\n")
|
|
329
|
+
|
|
330
|
+
md.append("\n## Top-level section structure\n")
|
|
331
|
+
if sections:
|
|
332
|
+
for i, s in enumerate(sections, 1):
|
|
333
|
+
md.append(f"{i}. {s}")
|
|
334
|
+
else:
|
|
335
|
+
md.append("- (no `\\section{...}` markers detected — treat as freeform prose)")
|
|
336
|
+
|
|
337
|
+
if subsecs:
|
|
338
|
+
md.append(f"\n- Subsection density: {len(subsecs)} subsections / {max(1,len(sections))} sections "
|
|
339
|
+
f"= {round(len(subsecs)/max(1,len(sections)), 2)} per section")
|
|
340
|
+
|
|
341
|
+
md.append("\n## Approximate length per section (words after TeX strip)\n")
|
|
342
|
+
if section_word_counts:
|
|
343
|
+
for name, wc in section_word_counts:
|
|
344
|
+
md.append(f"- {name}: ~{wc} words")
|
|
345
|
+
else:
|
|
346
|
+
md.append("- (not measurable)")
|
|
347
|
+
|
|
348
|
+
md.append("\n## Theorem-environment density\n")
|
|
349
|
+
if thm_counter:
|
|
350
|
+
for k, v in sorted(thm_counter.items(), key=lambda kv: -kv[1]):
|
|
351
|
+
md.append(f"- {k}: {v}")
|
|
352
|
+
md.append(f"- Total proof-style env: {sum(thm_counter.values())}")
|
|
353
|
+
else:
|
|
354
|
+
md.append("- (no theorem-style environments)")
|
|
355
|
+
|
|
356
|
+
md.append("\n## Figures / tables\n")
|
|
357
|
+
md.append(f"- Figures: {n_fig}")
|
|
358
|
+
md.append(f"- Tables: {n_tab}")
|
|
359
|
+
if caption_summary:
|
|
360
|
+
md.append(caption_summary)
|
|
361
|
+
|
|
362
|
+
md.append("\n## Math density\n")
|
|
363
|
+
md.append(f"- Display equations (equation/align/gather/multline): {n_display}")
|
|
364
|
+
md.append(f"- Inline math `$...$`: {n_inline}")
|
|
365
|
+
if n_inline + n_display > 0:
|
|
366
|
+
ratio = n_display / (n_inline + n_display)
|
|
367
|
+
md.append(f"- Display-math share: {round(ratio*100, 1)}%")
|
|
368
|
+
|
|
369
|
+
md.append("\n## Citation usage\n")
|
|
370
|
+
md.append(f"- Total `\\cite*{{...}}` invocations: {len(citations)}")
|
|
371
|
+
md.append(f"- Distinct cite keys: {len(set(cite_keys))}")
|
|
372
|
+
bib_hint = "unknown"
|
|
373
|
+
if re.search(r"\\bibliographystyle\{(plainnat|abbrvnat|authoryear)", tex):
|
|
374
|
+
bib_hint = "author-year (natbib-style)"
|
|
375
|
+
elif re.search(r"\\bibliographystyle\{(plain|unsrt|ieee|alpha)", tex):
|
|
376
|
+
bib_hint = "numeric"
|
|
377
|
+
md.append(f"- Bibliography style hint: {bib_hint}")
|
|
378
|
+
|
|
379
|
+
md.append("\n## Sentence cadence (after TeX strip)\n")
|
|
380
|
+
md.append(f"- Sentence count: {sstats['count']}")
|
|
381
|
+
md.append(f"- Mean words/sentence: {sstats['mean_words']}")
|
|
382
|
+
md.append(f"- Median words/sentence: {sstats['median_words']}")
|
|
383
|
+
md.append(f"- p90 words/sentence: {sstats['p90_words']}")
|
|
384
|
+
|
|
385
|
+
md.append("\n## Notable structural cues\n")
|
|
386
|
+
cues: list[str] = []
|
|
387
|
+
if any(re.search(r"contribution", s, re.IGNORECASE) for s in sections + subsecs):
|
|
388
|
+
cues.append("- Has explicit \"Contributions\" subsection")
|
|
389
|
+
if any(re.search(r"related work|prior work", s, re.IGNORECASE) for s in sections):
|
|
390
|
+
cues.append("- Has dedicated \"Related Work\" section")
|
|
391
|
+
if any(re.search(r"limitation|broader impact", s, re.IGNORECASE) for s in sections + subsecs):
|
|
392
|
+
cues.append("- Has explicit Limitations / Broader Impact discussion")
|
|
393
|
+
if "\\paragraph{" in tex:
|
|
394
|
+
n_para = tex.count("\\paragraph{")
|
|
395
|
+
cues.append(f"- Uses `\\paragraph{{...}}` headings ({n_para} occurrences) — implies short titled paragraphs")
|
|
396
|
+
if cues:
|
|
397
|
+
md.extend(cues)
|
|
398
|
+
else:
|
|
399
|
+
md.append("- (no salient cues detected)")
|
|
400
|
+
|
|
401
|
+
md.append("\n## Reminder to the writer\n")
|
|
402
|
+
md.append("- Match *structural* tendencies above (section count, theorem density, ")
|
|
403
|
+
md.append(" caption length, sentence cadence, math display ratio).")
|
|
404
|
+
md.append("- Do **not** copy prose, claims, examples, or terminology unique to the reference.")
|
|
405
|
+
md.append("- This profile is intentionally aggregate; if you need substance, use the user's own outline.\n")
|
|
406
|
+
|
|
407
|
+
return "\n".join(md) + "\n"
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
def _profile_from_text(text: str) -> str:
|
|
411
|
+
"""Best-effort profile from non-TeX text (PDF text dump or HTML)."""
|
|
412
|
+
sentences = re.split(r"(?<=[.!?])\s+", text)
|
|
413
|
+
sentences = [s for s in sentences if 8 < len(s) < 1000]
|
|
414
|
+
word_counts = [len(s.split()) for s in sentences] if sentences else [0]
|
|
415
|
+
headings = re.findall(r"^([A-Z][A-Za-z ]{2,40})$", text, re.MULTILINE)
|
|
416
|
+
headings = [h.strip() for h in headings if 3 <= len(h.split()) <= 6][:30]
|
|
417
|
+
|
|
418
|
+
md = ["# Style profile (skeleton-only, from non-TeX source)\n"]
|
|
419
|
+
md.append("**Use as structural guidance for the writer agent. Do NOT copy prose.**\n")
|
|
420
|
+
md.append("\n## Heuristic section-name candidates (best effort)\n")
|
|
421
|
+
if headings:
|
|
422
|
+
for h in headings[:20]:
|
|
423
|
+
md.append(f"- {h}")
|
|
424
|
+
else:
|
|
425
|
+
md.append("- (no headings recovered)")
|
|
426
|
+
md.append("\n## Sentence cadence\n")
|
|
427
|
+
if word_counts:
|
|
428
|
+
md.append(f"- Sentence count (heuristic): {len(sentences)}")
|
|
429
|
+
md.append(f"- Mean words/sentence: {round(statistics.mean(word_counts), 1)}")
|
|
430
|
+
md.append(f"- Median words/sentence: {int(statistics.median(word_counts))}")
|
|
431
|
+
md.append("\n## Caveat\n")
|
|
432
|
+
md.append("- Source is not LaTeX, so theorem density, citation style, and figure")
|
|
433
|
+
md.append(" density cannot be measured. Treat the section list as a hint only.\n")
|
|
434
|
+
return "\n".join(md) + "\n"
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
# ---------------------------------------------------------------------------
|
|
438
|
+
# Errors
|
|
439
|
+
# ---------------------------------------------------------------------------
|
|
440
|
+
|
|
441
|
+
class MissingDep(RuntimeError):
|
|
442
|
+
"""Optional Python or system dependency is unavailable. Caller may skip."""
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
class SourceError(RuntimeError):
|
|
446
|
+
"""Source could not be resolved or parsed. Caller should fail."""
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
# ---------------------------------------------------------------------------
|
|
450
|
+
# Main
|
|
451
|
+
# ---------------------------------------------------------------------------
|
|
452
|
+
|
|
453
|
+
def _cache_root() -> Path:
|
|
454
|
+
env = os.environ.get("ARIS_STYLE_REF_CACHE")
|
|
455
|
+
if env:
|
|
456
|
+
return Path(env).expanduser().resolve()
|
|
457
|
+
xdg = os.environ.get("XDG_CACHE_HOME")
|
|
458
|
+
base = Path(xdg).expanduser() if xdg else Path.home() / ".cache"
|
|
459
|
+
return base / "aris-style-refs"
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
def main() -> int:
|
|
463
|
+
ap = argparse.ArgumentParser(
|
|
464
|
+
description="Extract a skeleton-only style profile from a reference paper "
|
|
465
|
+
"for opt-in use by ARIS writer skills via --style-ref.",
|
|
466
|
+
)
|
|
467
|
+
ap.add_argument("--source", required=True,
|
|
468
|
+
help="Local path, arXiv ID, http(s) URL, or 'arxiv:<id>'. "
|
|
469
|
+
"Overleaf URLs are rejected — clone via overleaf-sync first "
|
|
470
|
+
"and pass the local clone path instead.")
|
|
471
|
+
ap.add_argument("--out", default=None,
|
|
472
|
+
help="Override cache root (default: $ARIS_STYLE_REF_CACHE, "
|
|
473
|
+
"$XDG_CACHE_HOME/aris-style-refs/, or ~/.cache/aris-style-refs/)")
|
|
474
|
+
ap.add_argument("--force", action="store_true",
|
|
475
|
+
help="Refetch and overwrite even if cache hit exists.")
|
|
476
|
+
args = ap.parse_args()
|
|
477
|
+
|
|
478
|
+
src = args.source.strip()
|
|
479
|
+
if not src:
|
|
480
|
+
print("error: --source is required", file=sys.stderr)
|
|
481
|
+
return 1
|
|
482
|
+
|
|
483
|
+
kind = _classify_source(src)
|
|
484
|
+
if kind == "overleaf":
|
|
485
|
+
print(
|
|
486
|
+
"Overleaf URLs / project IDs are rejected by design (private content).\n"
|
|
487
|
+
"Workflow: clone the project locally first via `/overleaf-sync setup <id>`,\n"
|
|
488
|
+
"then re-run with --source <local-clone-path>.",
|
|
489
|
+
file=sys.stderr,
|
|
490
|
+
)
|
|
491
|
+
return 3
|
|
492
|
+
if kind == "unknown":
|
|
493
|
+
print(f"error: could not classify source '{src}'. "
|
|
494
|
+
f"Pass a local path, arXiv id, or http(s) URL.", file=sys.stderr)
|
|
495
|
+
return 3
|
|
496
|
+
|
|
497
|
+
digest = hashlib.sha256(src.encode("utf-8")).hexdigest()[:16]
|
|
498
|
+
cache_root = Path(args.out).expanduser().resolve() if args.out else _cache_root()
|
|
499
|
+
cache_dir = cache_root / digest
|
|
500
|
+
manifest_path = cache_dir / "source_manifest.json"
|
|
501
|
+
profile_path = cache_dir / "style_profile.md"
|
|
502
|
+
|
|
503
|
+
if manifest_path.exists() and profile_path.exists() and not args.force:
|
|
504
|
+
print(f"# cache hit: {cache_dir}", file=sys.stderr)
|
|
505
|
+
print(str(cache_dir))
|
|
506
|
+
return 0
|
|
507
|
+
|
|
508
|
+
try:
|
|
509
|
+
if kind == "local_dir":
|
|
510
|
+
raw = _read_local_dir(Path(src).expanduser())
|
|
511
|
+
resolved = str(Path(src).expanduser().resolve())
|
|
512
|
+
elif kind == "local_tex":
|
|
513
|
+
raw = _read_local_tex(Path(src).expanduser())
|
|
514
|
+
resolved = str(Path(src).expanduser().resolve())
|
|
515
|
+
elif kind == "local_pdf":
|
|
516
|
+
raw = _read_local_pdf(Path(src).expanduser())
|
|
517
|
+
resolved = str(Path(src).expanduser().resolve())
|
|
518
|
+
elif kind == "arxiv":
|
|
519
|
+
raw = _read_arxiv(src)
|
|
520
|
+
resolved = src
|
|
521
|
+
elif kind == "http":
|
|
522
|
+
raw = _read_http(src)
|
|
523
|
+
resolved = src
|
|
524
|
+
else:
|
|
525
|
+
print(f"error: unsupported source kind '{kind}'", file=sys.stderr)
|
|
526
|
+
return 3
|
|
527
|
+
except MissingDep as e:
|
|
528
|
+
print(f"warning: missing optional dependency: {e}", file=sys.stderr)
|
|
529
|
+
return 2
|
|
530
|
+
except SourceError as e:
|
|
531
|
+
print(f"error: source could not be resolved: {e}", file=sys.stderr)
|
|
532
|
+
return 3
|
|
533
|
+
except Exception as e:
|
|
534
|
+
print(f"error: unexpected failure: {type(e).__name__}: {e}", file=sys.stderr)
|
|
535
|
+
return 1
|
|
536
|
+
|
|
537
|
+
profile_md = _build_profile(kind, raw)
|
|
538
|
+
|
|
539
|
+
cache_dir.mkdir(parents=True, exist_ok=True)
|
|
540
|
+
content_sha = hashlib.sha256(raw.encode("utf-8", errors="replace")).hexdigest()
|
|
541
|
+
manifest = {
|
|
542
|
+
"source_input": src,
|
|
543
|
+
"source_type": kind,
|
|
544
|
+
"resolved_path": resolved,
|
|
545
|
+
"fetched_at": _dt.datetime.now(_dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z"),
|
|
546
|
+
"content_sha256": content_sha,
|
|
547
|
+
"tool_version": TOOL_VERSION,
|
|
548
|
+
}
|
|
549
|
+
manifest_path.write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
|
|
550
|
+
profile_path.write_text(profile_md, encoding="utf-8")
|
|
551
|
+
|
|
552
|
+
print(str(cache_dir))
|
|
553
|
+
return 0
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
if __name__ == "__main__":
|
|
557
|
+
try:
|
|
558
|
+
sys.exit(main())
|
|
559
|
+
except KeyboardInterrupt:
|
|
560
|
+
sys.exit(130)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Legacy entry point — forwards to the canonical figure_renderer.
|
|
3
|
+
|
|
4
|
+
The canonical implementation now lives at
|
|
5
|
+
skills/figure-spec/scripts/figure_renderer.py
|
|
6
|
+
(Phase 3.1 — Arch C — self-contained single-owner helper).
|
|
7
|
+
|
|
8
|
+
This shim exists so existing users keep working without re-running
|
|
9
|
+
install_aris.sh. The four legacy resolver layers all still hit a
|
|
10
|
+
valid Python module:
|
|
11
|
+
|
|
12
|
+
layer 1 <project>/.aris/tools/figure_renderer.py
|
|
13
|
+
→ symlink to $ARIS_REPO/tools/figure_renderer.py
|
|
14
|
+
→ this file (shim)
|
|
15
|
+
→ $ARIS_REPO/skills/figure-spec/scripts/figure_renderer.py
|
|
16
|
+
|
|
17
|
+
layer 2 <project>/tools/figure_renderer.py
|
|
18
|
+
→ this file (when running from inside the ARIS repo)
|
|
19
|
+
|
|
20
|
+
layer 3 $ARIS_REPO/tools/figure_renderer.py
|
|
21
|
+
→ this file (when ARIS_REPO env var or manifest sets it)
|
|
22
|
+
|
|
23
|
+
layer 4 $ARIS_REPO/tools/figure_renderer.py
|
|
24
|
+
→ this file (when ARIS_REPO is resolved from the global
|
|
25
|
+
pointer file ~/.aris/repo, #366 — no project manifest needed)
|
|
26
|
+
|
|
27
|
+
Shim semantics: `os.execv` replaces the current Python process with
|
|
28
|
+
the real helper, so the helper sees its own `__file__`, `sys.path[0]`,
|
|
29
|
+
and argv exactly as if it had been invoked directly. No extra
|
|
30
|
+
process layer, no environment pollution.
|
|
31
|
+
|
|
32
|
+
The shim itself is kept minimal so a Python 3.6+ interpreter on any
|
|
33
|
+
platform (including older macOS system python) can run it.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
from __future__ import annotations
|
|
37
|
+
|
|
38
|
+
import os
|
|
39
|
+
import sys
|
|
40
|
+
from pathlib import Path
|
|
41
|
+
|
|
42
|
+
HERE = Path(__file__).resolve().parent
|
|
43
|
+
REPO_ROOT = HERE.parent
|
|
44
|
+
REAL = REPO_ROOT / "skills" / "figure-spec" / "scripts" / "figure_renderer.py"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _fail(msg: str) -> int:
|
|
48
|
+
sys.stderr.write(msg + "\n")
|
|
49
|
+
return 1
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def main() -> int:
|
|
53
|
+
if not REAL.is_file():
|
|
54
|
+
return _fail(
|
|
55
|
+
f"ERROR: canonical figure_renderer.py not found at {REAL}.\n"
|
|
56
|
+
" The Phase 3.1 migration moved this helper into the\n"
|
|
57
|
+
" /figure-spec SKILL ('skills/figure-spec/scripts/'). Your\n"
|
|
58
|
+
" local checkout may be incomplete — try `git pull` from the\n"
|
|
59
|
+
" ARIS repo, or rerun `bash tools/install_aris.sh` to refresh\n"
|
|
60
|
+
" the project-local symlink chain."
|
|
61
|
+
)
|
|
62
|
+
# os.execv replaces this Python process; argv[0] is the real path so
|
|
63
|
+
# the helper sees its own __file__ and computes paths correctly.
|
|
64
|
+
os.execv(sys.executable, [sys.executable, str(REAL), *sys.argv[1:]])
|
|
65
|
+
return 0 # unreachable; os.execv does not return on success
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
if __name__ == "__main__":
|
|
69
|
+
sys.exit(main())
|