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,433 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""queue_manager.py — ARIS experiment-queue scheduler.
|
|
3
|
+
|
|
4
|
+
Runs on the SSH remote host (or locally for Modal/Vast.ai future support).
|
|
5
|
+
Reads a manifest, launches jobs across free GPUs via `screen`, retries on OOM,
|
|
6
|
+
cleans stale screens, and writes state continuously to disk.
|
|
7
|
+
|
|
8
|
+
Usage (on remote):
|
|
9
|
+
nohup python3 queue_manager.py \\
|
|
10
|
+
--manifest manifest.json \\
|
|
11
|
+
--state queue_state.json \\
|
|
12
|
+
--log-dir ./logs \\
|
|
13
|
+
> queue_mgr.log 2>&1 &
|
|
14
|
+
|
|
15
|
+
(Pass --log-dir, NOT --log: --log is declared but unused; per-job log
|
|
16
|
+
files in --log-dir drive OOM detection and stale-screen cleanup.)
|
|
17
|
+
|
|
18
|
+
The manifest.json is either produced manually or by `build_manifest.py`.
|
|
19
|
+
|
|
20
|
+
State file format (queue_state.json):
|
|
21
|
+
{
|
|
22
|
+
"meta": {"project": "...", "started": "ISO8601", "host": "..."},
|
|
23
|
+
"phases": [{"name": "...", "depends_on": [...], "status": "..."}],
|
|
24
|
+
"jobs": [
|
|
25
|
+
{
|
|
26
|
+
"id": "s200_N64_n50K",
|
|
27
|
+
"phase": "distill",
|
|
28
|
+
"status": "running", # pending|running|completed|failed_oom|failed_other|stuck
|
|
29
|
+
"gpu": 3,
|
|
30
|
+
"screen_name": "EQ_s200_N64_n50K",
|
|
31
|
+
"pid": 12345,
|
|
32
|
+
"attempts": 1,
|
|
33
|
+
"started": "...",
|
|
34
|
+
"completed": null,
|
|
35
|
+
"expected_output": "figures/distill_sw_N64_n50K_...json",
|
|
36
|
+
"error": null
|
|
37
|
+
}, ...
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
import argparse
|
|
43
|
+
import glob
|
|
44
|
+
import json
|
|
45
|
+
import os
|
|
46
|
+
import re
|
|
47
|
+
import shlex
|
|
48
|
+
import subprocess
|
|
49
|
+
import sys
|
|
50
|
+
import time
|
|
51
|
+
from datetime import datetime
|
|
52
|
+
from pathlib import Path
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
OOM_RE = re.compile(r"(CUDA out of memory|torch\.OutOfMemoryError)")
|
|
56
|
+
DEFAULT_GPU_FREE_THRESHOLD_MIB = 500
|
|
57
|
+
POLL_INTERVAL_SEC = 60
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def resolve_conda_hook(manifest_hook=None):
|
|
61
|
+
"""Resolve conda hook command via (1) manifest, (2) env var, (3) auto-detect, (4) PATH.
|
|
62
|
+
|
|
63
|
+
manifest_hook: value of `conda_hook` field in manifest (full hook command, e.g.
|
|
64
|
+
`eval "$(/custom/path/conda shell.bash hook)"`), or a bare conda binary path
|
|
65
|
+
which will be wrapped automatically.
|
|
66
|
+
"""
|
|
67
|
+
def wrap(path_or_cmd):
|
|
68
|
+
if path_or_cmd.startswith("eval"):
|
|
69
|
+
return path_or_cmd
|
|
70
|
+
return f'eval "$({path_or_cmd} shell.bash hook)"'
|
|
71
|
+
|
|
72
|
+
# 1. Manifest override
|
|
73
|
+
if manifest_hook:
|
|
74
|
+
return wrap(manifest_hook)
|
|
75
|
+
# 2. Env var override
|
|
76
|
+
env_hook = os.environ.get("ARIS_CONDA_HOOK")
|
|
77
|
+
if env_hook:
|
|
78
|
+
return wrap(env_hook)
|
|
79
|
+
# 3. Auto-detect common install paths
|
|
80
|
+
for p in (
|
|
81
|
+
os.path.expanduser("~/anaconda3/bin/conda"),
|
|
82
|
+
os.path.expanduser("~/miniconda3/bin/conda"),
|
|
83
|
+
os.path.expanduser("~/miniforge3/bin/conda"),
|
|
84
|
+
"/opt/anaconda3/bin/conda",
|
|
85
|
+
"/opt/miniconda3/bin/conda",
|
|
86
|
+
"/opt/miniforge3/bin/conda",
|
|
87
|
+
"/usr/local/anaconda3/bin/conda",
|
|
88
|
+
"/opt/homebrew/anaconda3/bin/conda",
|
|
89
|
+
):
|
|
90
|
+
if os.path.exists(p):
|
|
91
|
+
return wrap(p)
|
|
92
|
+
# 4. Fall back to PATH
|
|
93
|
+
out, rc = run("command -v conda 2>/dev/null")
|
|
94
|
+
if rc == 0 and out.strip():
|
|
95
|
+
return wrap(out.strip())
|
|
96
|
+
# 5. Last resort
|
|
97
|
+
return 'eval "$(conda shell.bash hook)"'
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def now():
|
|
101
|
+
return datetime.utcnow().isoformat() + "Z"
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def run(cmd, check=False, capture=True):
|
|
105
|
+
"""Run shell command, return (stdout, returncode)."""
|
|
106
|
+
r = subprocess.run(cmd, shell=True, capture_output=capture, text=True)
|
|
107
|
+
if check and r.returncode != 0:
|
|
108
|
+
raise RuntimeError(f"Command failed: {cmd}\n{r.stderr}")
|
|
109
|
+
return r.stdout, r.returncode
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def gpu_memory_used():
|
|
113
|
+
"""Return list of used MiB per GPU index."""
|
|
114
|
+
out, rc = run("nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits")
|
|
115
|
+
if rc != 0:
|
|
116
|
+
return []
|
|
117
|
+
return [int(x.strip()) for x in out.strip().split("\n") if x.strip()]
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def free_gpus(allowed, threshold_mib=DEFAULT_GPU_FREE_THRESHOLD_MIB):
|
|
121
|
+
"""Return list of GPU indices with memory.used < threshold."""
|
|
122
|
+
used = gpu_memory_used()
|
|
123
|
+
return [i for i in allowed if i < len(used) and used[i] < threshold_mib]
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def screen_exists(name):
|
|
127
|
+
out, _ = run("screen -ls")
|
|
128
|
+
return re.search(rf"^\s*\d+\.{re.escape(name)}\s", out, re.MULTILINE) is not None
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def kill_screen(name):
|
|
132
|
+
run(f"screen -S {name} -X quit", check=False)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def detect_oom_in_log(log_path):
|
|
136
|
+
if not log_path or not Path(log_path).exists():
|
|
137
|
+
return False
|
|
138
|
+
try:
|
|
139
|
+
# Check tail of log for OOM marker
|
|
140
|
+
out, _ = run(f"tail -c 10000 {shlex.quote(log_path)}")
|
|
141
|
+
return bool(OOM_RE.search(out))
|
|
142
|
+
except Exception:
|
|
143
|
+
return False
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def output_exists(path_pattern, cwd):
|
|
147
|
+
"""Check if output file exists (pattern supports shell glob)."""
|
|
148
|
+
if not path_pattern:
|
|
149
|
+
return False
|
|
150
|
+
full = os.path.join(cwd, path_pattern) if not os.path.isabs(path_pattern) else path_pattern
|
|
151
|
+
return bool(glob.glob(full))
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _normalize_depends_on(value):
|
|
155
|
+
"""A bare string was the shape our own docs showed until 2026-08; without this
|
|
156
|
+
it would be iterated character by character and the phase never becomes ready."""
|
|
157
|
+
return [value] if isinstance(value, str) else (value or [])
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def load_state(state_file, manifest):
|
|
161
|
+
"""Load state from disk or initialize from manifest."""
|
|
162
|
+
if Path(state_file).exists():
|
|
163
|
+
with open(state_file) as f:
|
|
164
|
+
state = json.load(f)
|
|
165
|
+
# a state file written before the fix carries the un-normalized shape
|
|
166
|
+
for phase in state.get("phases", []):
|
|
167
|
+
phase["depends_on"] = _normalize_depends_on(phase.get("depends_on"))
|
|
168
|
+
return state
|
|
169
|
+
# Initialize from manifest
|
|
170
|
+
state = {
|
|
171
|
+
"meta": {
|
|
172
|
+
"project": manifest.get("project", "unknown"),
|
|
173
|
+
"started": now(),
|
|
174
|
+
"manifest_path": str(manifest.get("_path", "")),
|
|
175
|
+
},
|
|
176
|
+
"phases": [
|
|
177
|
+
{"name": p.get("name", f"phase_{i}"),
|
|
178
|
+
"depends_on": _normalize_depends_on(p.get("depends_on")),
|
|
179
|
+
"status": "pending"}
|
|
180
|
+
for i, p in enumerate(manifest.get("phases", []))
|
|
181
|
+
],
|
|
182
|
+
"jobs": [],
|
|
183
|
+
}
|
|
184
|
+
return state
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def save_state(state, state_file):
|
|
188
|
+
tmp = state_file + ".tmp"
|
|
189
|
+
with open(tmp, "w") as f:
|
|
190
|
+
json.dump(state, f, indent=2)
|
|
191
|
+
os.rename(tmp, state_file)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def phase_ready(phase_name, state):
|
|
195
|
+
"""Check if all depends_on phases are completed."""
|
|
196
|
+
for p in state["phases"]:
|
|
197
|
+
if p["name"] == phase_name:
|
|
198
|
+
if not p["depends_on"]:
|
|
199
|
+
return True
|
|
200
|
+
for dep in p["depends_on"]:
|
|
201
|
+
dep_phase = next((x for x in state["phases"] if x["name"] == dep), None)
|
|
202
|
+
if not dep_phase or dep_phase["status"] != "completed":
|
|
203
|
+
return False
|
|
204
|
+
return True
|
|
205
|
+
return False
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def phase_complete(phase_name, state):
|
|
209
|
+
phase_jobs = [j for j in state["jobs"] if j.get("phase") == phase_name]
|
|
210
|
+
if not phase_jobs:
|
|
211
|
+
return False
|
|
212
|
+
return all(j["status"] in ("completed", "stuck") for j in phase_jobs)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def assign_jobs_to_phases(manifest, state):
|
|
216
|
+
"""Ensure state.jobs contains all manifest jobs; idempotent."""
|
|
217
|
+
for phase in manifest.get("phases", []):
|
|
218
|
+
phase_name = phase.get("name")
|
|
219
|
+
for job in phase.get("jobs", []):
|
|
220
|
+
existing = next((j for j in state["jobs"] if j["id"] == job["id"]), None)
|
|
221
|
+
if not existing:
|
|
222
|
+
state["jobs"].append({
|
|
223
|
+
"id": job["id"],
|
|
224
|
+
"phase": phase_name,
|
|
225
|
+
"cmd": job["cmd"],
|
|
226
|
+
"expected_output": job.get("expected_output"),
|
|
227
|
+
"status": "pending",
|
|
228
|
+
"gpu": None,
|
|
229
|
+
"screen_name": None,
|
|
230
|
+
"pid": None,
|
|
231
|
+
"attempts": 0,
|
|
232
|
+
"started": None,
|
|
233
|
+
"completed": None,
|
|
234
|
+
"error": None,
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def launch_job(job, gpu, conda_env, cwd, log_dir, conda_hook):
|
|
239
|
+
"""Launch job in a detached screen, return (screen_name, pid)."""
|
|
240
|
+
screen_name = f"EQ_{job['id']}"
|
|
241
|
+
if screen_exists(screen_name):
|
|
242
|
+
# Shouldn't happen; clean up
|
|
243
|
+
kill_screen(screen_name)
|
|
244
|
+
time.sleep(2)
|
|
245
|
+
log_file = os.path.join(log_dir, f"{job['id']}.log")
|
|
246
|
+
cmd = job["cmd"]
|
|
247
|
+
# Substitute GPU placeholder if present
|
|
248
|
+
cmd_with_gpu = cmd.replace("${GPU}", str(gpu))
|
|
249
|
+
full = (
|
|
250
|
+
f'cd {shlex.quote(cwd)} && '
|
|
251
|
+
f'{conda_hook} && '
|
|
252
|
+
f'conda activate {conda_env} && '
|
|
253
|
+
f'CUDA_VISIBLE_DEVICES={gpu} {cmd_with_gpu} 2>&1 | tee {shlex.quote(log_file)}'
|
|
254
|
+
)
|
|
255
|
+
screen_cmd = f'screen -dmS {screen_name} bash -c {shlex.quote(full)}'
|
|
256
|
+
run(screen_cmd)
|
|
257
|
+
time.sleep(2)
|
|
258
|
+
# Get pid (find python process for this CUDA_VISIBLE_DEVICES)
|
|
259
|
+
pid_out, _ = run(
|
|
260
|
+
f"ps -ef | grep 'CUDA_VISIBLE_DEVICES={gpu} ' | grep -v grep | "
|
|
261
|
+
f"grep python | awk '{{print $2}}' | head -1")
|
|
262
|
+
pid = pid_out.strip()
|
|
263
|
+
return screen_name, (int(pid) if pid.isdigit() else None)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def job_status_check(job, log_dir, cwd):
|
|
267
|
+
"""Return new status for a running job."""
|
|
268
|
+
screen_name = job["screen_name"]
|
|
269
|
+
log_file = os.path.join(log_dir, f"{job['id']}.log")
|
|
270
|
+
|
|
271
|
+
# 1. Output exists → completed
|
|
272
|
+
if job.get("expected_output") and output_exists(job["expected_output"], cwd):
|
|
273
|
+
return "completed", None
|
|
274
|
+
|
|
275
|
+
# 2. OOM detected → failed_oom
|
|
276
|
+
if detect_oom_in_log(log_file):
|
|
277
|
+
return "failed_oom", "CUDA OOM detected"
|
|
278
|
+
|
|
279
|
+
# 3. Screen alive + python alive → still running
|
|
280
|
+
if screen_name and screen_exists(screen_name):
|
|
281
|
+
if job.get("pid"):
|
|
282
|
+
_, rc = run(f"kill -0 {job['pid']} 2>/dev/null")
|
|
283
|
+
if rc == 0:
|
|
284
|
+
return "running", None
|
|
285
|
+
# Python died but the screen lingers → stale; step() kills the screen.
|
|
286
|
+
return "failed_other", "Process exited without expected output (stale screen)"
|
|
287
|
+
else:
|
|
288
|
+
# No pid known; trust screen for now
|
|
289
|
+
return "running", None
|
|
290
|
+
|
|
291
|
+
# 4. Screen gone (or never recorded), no output → failed_other
|
|
292
|
+
return "failed_other", "Screen exited without expected output"
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def pending_jobs_in_active_phases(state, manifest):
|
|
296
|
+
active_phases = []
|
|
297
|
+
for phase in manifest.get("phases", []):
|
|
298
|
+
phase_name = phase.get("name")
|
|
299
|
+
if phase_ready(phase_name, state) and not phase_complete(phase_name, state):
|
|
300
|
+
active_phases.append(phase_name)
|
|
301
|
+
return [
|
|
302
|
+
j for j in state["jobs"]
|
|
303
|
+
if j["status"] == "pending" and j["phase"] in active_phases
|
|
304
|
+
]
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def step(manifest, state, state_file, log_dir):
|
|
308
|
+
"""Run one scheduler step: poll, launch, update state."""
|
|
309
|
+
cwd = manifest.get("cwd", ".")
|
|
310
|
+
conda_env = manifest.get("conda", "base")
|
|
311
|
+
conda_hook = resolve_conda_hook(manifest.get("conda_hook"))
|
|
312
|
+
allowed_gpus = manifest.get("gpus", list(range(8)))
|
|
313
|
+
max_parallel = manifest.get("max_parallel", len(allowed_gpus))
|
|
314
|
+
gpu_free_threshold = manifest.get("gpu_free_threshold_mib",
|
|
315
|
+
DEFAULT_GPU_FREE_THRESHOLD_MIB)
|
|
316
|
+
oom_delay = manifest.get("oom_retry", {}).get("delay", 120)
|
|
317
|
+
max_oom_attempts = manifest.get("oom_retry", {}).get("max_attempts", 3)
|
|
318
|
+
|
|
319
|
+
# 1. Check running jobs
|
|
320
|
+
for job in state["jobs"]:
|
|
321
|
+
if job["status"] != "running":
|
|
322
|
+
continue
|
|
323
|
+
new_status, err = job_status_check(job, log_dir, cwd)
|
|
324
|
+
if new_status == "completed":
|
|
325
|
+
job["status"] = "completed"
|
|
326
|
+
job["completed"] = now()
|
|
327
|
+
# Clean up screen
|
|
328
|
+
if job["screen_name"]:
|
|
329
|
+
kill_screen(job["screen_name"])
|
|
330
|
+
elif new_status == "failed_oom":
|
|
331
|
+
job["status"] = "failed_oom"
|
|
332
|
+
job["error"] = err
|
|
333
|
+
job["completed"] = now()
|
|
334
|
+
if job["screen_name"]:
|
|
335
|
+
kill_screen(job["screen_name"])
|
|
336
|
+
elif new_status == "failed_other":
|
|
337
|
+
job["status"] = "failed_other"
|
|
338
|
+
job["error"] = err
|
|
339
|
+
job["completed"] = now()
|
|
340
|
+
if job["screen_name"]:
|
|
341
|
+
kill_screen(job["screen_name"])
|
|
342
|
+
|
|
343
|
+
# 2. Park non-OOM failures as terminal, retry OOM jobs that have waited long enough
|
|
344
|
+
current_time = time.time()
|
|
345
|
+
for job in state["jobs"]:
|
|
346
|
+
if job["status"] == "failed_other":
|
|
347
|
+
job["status"] = "stuck" # no retry path exists for non-OOM failures
|
|
348
|
+
continue
|
|
349
|
+
if job["status"] != "failed_oom":
|
|
350
|
+
continue
|
|
351
|
+
if job["attempts"] >= max_oom_attempts:
|
|
352
|
+
job["status"] = "stuck"
|
|
353
|
+
continue
|
|
354
|
+
# Wait oom_delay after failure before retry
|
|
355
|
+
if job["completed"]:
|
|
356
|
+
last = datetime.fromisoformat(job["completed"].rstrip("Z"))
|
|
357
|
+
elapsed = (datetime.utcnow() - last).total_seconds()
|
|
358
|
+
if elapsed >= oom_delay:
|
|
359
|
+
job["status"] = "pending" # Requeue
|
|
360
|
+
|
|
361
|
+
# 3. Launch new jobs up to max_parallel
|
|
362
|
+
running = [j for j in state["jobs"] if j["status"] == "running"]
|
|
363
|
+
pending = pending_jobs_in_active_phases(state, manifest)
|
|
364
|
+
free = free_gpus(allowed_gpus, gpu_free_threshold)
|
|
365
|
+
# Exclude GPUs already assigned to running jobs
|
|
366
|
+
taken = {j["gpu"] for j in running if j.get("gpu") is not None}
|
|
367
|
+
free = [g for g in free if g not in taken]
|
|
368
|
+
|
|
369
|
+
slots = min(max_parallel - len(running), len(free), len(pending))
|
|
370
|
+
for i in range(slots):
|
|
371
|
+
job = pending[i]
|
|
372
|
+
gpu = free[i]
|
|
373
|
+
screen_name, pid = launch_job(job, gpu, conda_env, cwd, log_dir, conda_hook)
|
|
374
|
+
job["status"] = "running"
|
|
375
|
+
job["gpu"] = gpu
|
|
376
|
+
job["screen_name"] = screen_name
|
|
377
|
+
job["pid"] = pid
|
|
378
|
+
job["attempts"] += 1
|
|
379
|
+
job["started"] = now()
|
|
380
|
+
job["error"] = None
|
|
381
|
+
|
|
382
|
+
# 4. Update phase status
|
|
383
|
+
for phase in state["phases"]:
|
|
384
|
+
if phase_complete(phase["name"], state):
|
|
385
|
+
phase["status"] = "completed"
|
|
386
|
+
elif any(j["status"] == "running"
|
|
387
|
+
for j in state["jobs"] if j.get("phase") == phase["name"]):
|
|
388
|
+
phase["status"] = "running"
|
|
389
|
+
|
|
390
|
+
save_state(state, state_file)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def all_done(state):
|
|
394
|
+
return all(j["status"] in ("completed", "stuck") for j in state["jobs"])
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def main():
|
|
398
|
+
ap = argparse.ArgumentParser()
|
|
399
|
+
ap.add_argument("--manifest", required=True)
|
|
400
|
+
ap.add_argument("--state", required=True)
|
|
401
|
+
ap.add_argument("--log", default=None, help="Human-readable log file")
|
|
402
|
+
ap.add_argument("--log-dir", default=None,
|
|
403
|
+
help="Per-job log directory (default: cwd)")
|
|
404
|
+
ap.add_argument("--poll", type=int, default=POLL_INTERVAL_SEC)
|
|
405
|
+
args = ap.parse_args()
|
|
406
|
+
|
|
407
|
+
with open(args.manifest) as f:
|
|
408
|
+
manifest = json.load(f)
|
|
409
|
+
manifest["_path"] = args.manifest
|
|
410
|
+
|
|
411
|
+
log_dir = args.log_dir or manifest.get("cwd", ".")
|
|
412
|
+
Path(log_dir).mkdir(parents=True, exist_ok=True)
|
|
413
|
+
|
|
414
|
+
state = load_state(args.state, manifest)
|
|
415
|
+
assign_jobs_to_phases(manifest, state)
|
|
416
|
+
save_state(state, args.state)
|
|
417
|
+
|
|
418
|
+
print(f"[{now()}] Queue manager started with {len(state['jobs'])} jobs")
|
|
419
|
+
sys.stdout.flush()
|
|
420
|
+
|
|
421
|
+
while not all_done(state):
|
|
422
|
+
try:
|
|
423
|
+
step(manifest, state, args.state, log_dir)
|
|
424
|
+
except Exception as e:
|
|
425
|
+
print(f"[{now()}] Step error: {e}")
|
|
426
|
+
sys.stdout.flush()
|
|
427
|
+
time.sleep(args.poll)
|
|
428
|
+
|
|
429
|
+
print(f"[{now()}] All jobs done")
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
if __name__ == "__main__":
|
|
433
|
+
main()
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: feishu-notify
|
|
3
|
+
description: "Send notifications to Feishu/Lark. Internal utility used by other skills, or manually via /feishu-notify. Use when user says \"发飞书\", \"notify feishu\", or other skills need to send status updates."
|
|
4
|
+
argument-hint: "[message-text]"
|
|
5
|
+
allowed-tools: Bash(curl *), Bash(cat *), Read, Glob
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Feishu/Lark Notification
|
|
9
|
+
|
|
10
|
+
Send a notification: **$ARGUMENTS**
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
This skill provides Feishu/Lark integration for ARIS. It is designed as an **internal utility** — other skills call it at key events (experiment done, review scored, checkpoint waiting). It can also be invoked manually.
|
|
15
|
+
|
|
16
|
+
**Zero-impact guarantee**: If no `feishu.json` config exists, this skill does nothing and returns silently. All existing workflows are completely unaffected.
|
|
17
|
+
|
|
18
|
+
## Configuration
|
|
19
|
+
|
|
20
|
+
The skill reads `~/.claude/feishu.json`. If this file does not exist, **all Feishu functionality is disabled** — skills behave exactly as before.
|
|
21
|
+
|
|
22
|
+
### Config Format
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"mode": "push",
|
|
27
|
+
"webhook_url": "https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_WEBHOOK_ID",
|
|
28
|
+
"interactive": {
|
|
29
|
+
"bridge_url": "http://localhost:5000",
|
|
30
|
+
"timeout_seconds": 300
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Modes
|
|
36
|
+
|
|
37
|
+
| Mode | `"mode"` value | What it does | Requires |
|
|
38
|
+
|------|----------------|--------------|----------|
|
|
39
|
+
| **Off** | `"off"` or file absent | Nothing. Pure CLI as-is | Nothing |
|
|
40
|
+
| **Push only** | `"push"` | Send webhook notifications at key events. Mobile push, no reply | Feishu bot webhook URL |
|
|
41
|
+
| **Interactive** | `"interactive"` | Full bidirectional. Approve/reject from Feishu, reply to checkpoints | [feishu-claude-code](https://github.com/joewongjc/feishu-claude-code) running |
|
|
42
|
+
|
|
43
|
+
## Workflow
|
|
44
|
+
|
|
45
|
+
### Step 1: Read Config
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
cat ~/.claude/feishu.json 2>/dev/null
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
- **File not found** → return silently, do nothing
|
|
52
|
+
- **`"mode": "off"`** → return silently, do nothing
|
|
53
|
+
- **`"mode": "push"`** → proceed to Step 2 (push)
|
|
54
|
+
- **`"mode": "interactive"`** → proceed to Step 3 (interactive)
|
|
55
|
+
|
|
56
|
+
### Step 2: Push Notification (webhook)
|
|
57
|
+
|
|
58
|
+
Send a rich card to the Feishu webhook:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
curl -s -X POST "$WEBHOOK_URL" \
|
|
62
|
+
-H "Content-Type: application/json" \
|
|
63
|
+
-d '{
|
|
64
|
+
"msg_type": "interactive",
|
|
65
|
+
"card": {
|
|
66
|
+
"header": {
|
|
67
|
+
"title": {"tag": "plain_text", "content": "TITLE"},
|
|
68
|
+
"template": "COLOR"
|
|
69
|
+
},
|
|
70
|
+
"elements": [
|
|
71
|
+
{"tag": "markdown", "content": "BODY"}
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
}'
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Card templates by event type:**
|
|
78
|
+
|
|
79
|
+
| Event | Title | Color | Body |
|
|
80
|
+
|-------|-------|-------|------|
|
|
81
|
+
| `experiment_done` | Experiment Complete | `green` | Results table, delta vs baseline |
|
|
82
|
+
| `review_scored` | Review Round N: X/10 | `blue` (≥6) / `orange` (<6) | Score, verdict, top 3 weaknesses |
|
|
83
|
+
| `checkpoint` | Checkpoint: Waiting for Input | `yellow` | Question, options, context |
|
|
84
|
+
| `error` | Error: [type] | `red` | Error message, what failed |
|
|
85
|
+
| `pipeline_done` | Pipeline Complete | `purple` | Final summary, deliverables |
|
|
86
|
+
| `custom` | Custom | `blue` | Free-form message from $ARGUMENTS |
|
|
87
|
+
|
|
88
|
+
**Return immediately after curl** — push mode never waits for a response.
|
|
89
|
+
|
|
90
|
+
### Step 3: Interactive Notification (bidirectional)
|
|
91
|
+
|
|
92
|
+
Interactive mode uses [feishu-claude-code](https://github.com/joewongjc/feishu-claude-code) as a bridge:
|
|
93
|
+
|
|
94
|
+
1. **Send message** to the bridge:
|
|
95
|
+
```bash
|
|
96
|
+
curl -s -X POST "$BRIDGE_URL/send" \
|
|
97
|
+
-H "Content-Type: application/json" \
|
|
98
|
+
-d '{"type": "EVENT_TYPE", "title": "TITLE", "body": "BODY", "options": ["approve", "reject", "custom"]}'
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
2. **Wait for reply** (with timeout):
|
|
102
|
+
```bash
|
|
103
|
+
curl -s "$BRIDGE_URL/poll?timeout=$TIMEOUT_SECONDS"
|
|
104
|
+
```
|
|
105
|
+
Returns: `{"reply": "approve"}` or `{"reply": "reject"}` or `{"reply": "user typed message"}` or `{"timeout": true}`
|
|
106
|
+
|
|
107
|
+
3. **On timeout**: Fall back to `AUTO_PROCEED` behavior (proceed with default option).
|
|
108
|
+
|
|
109
|
+
4. **Return the user's reply** to the calling skill so it can act on it.
|
|
110
|
+
|
|
111
|
+
### Step 4: Verify Delivery
|
|
112
|
+
|
|
113
|
+
- **Push mode**: Check curl exit code. If non-zero, log warning but do NOT block the workflow.
|
|
114
|
+
- **Interactive mode**: If bridge is unreachable, fall back to push mode (if webhook configured) or skip silently.
|
|
115
|
+
|
|
116
|
+
## Helper Function (for other skills)
|
|
117
|
+
|
|
118
|
+
Other skills should use this pattern to send notifications:
|
|
119
|
+
|
|
120
|
+
```markdown
|
|
121
|
+
### Feishu Notification (if configured)
|
|
122
|
+
|
|
123
|
+
Check if `~/.claude/feishu.json` exists and mode is not "off":
|
|
124
|
+
- If **push** mode: send webhook notification with event summary
|
|
125
|
+
- If **interactive** mode: send notification and wait for user reply
|
|
126
|
+
- If **off** or file absent: skip entirely (no-op)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**This check is always guarded.** If the config file doesn't exist, the skill skips the notification block entirely — zero overhead, zero side effects.
|
|
130
|
+
|
|
131
|
+
## Event Catalog
|
|
132
|
+
|
|
133
|
+
Skills send these events at these moments:
|
|
134
|
+
|
|
135
|
+
| Skill | Event | When |
|
|
136
|
+
|-------|-------|------|
|
|
137
|
+
| `/auto-review-loop` | `review_scored` | After each round's review score |
|
|
138
|
+
| `/auto-review-loop` | `pipeline_done` | Loop complete (positive or max rounds) |
|
|
139
|
+
| `/auto-paper-improvement-loop` | `review_scored` | After each round's review score |
|
|
140
|
+
| `/auto-paper-improvement-loop` | `pipeline_done` | All rounds complete |
|
|
141
|
+
| `/run-experiment` | `experiment_done` | Screen session finishes |
|
|
142
|
+
| `/idea-discovery` | `checkpoint` | Between phases (if interactive) |
|
|
143
|
+
| `/idea-discovery` | `pipeline_done` | Final report ready |
|
|
144
|
+
| `/monitor-experiment` | `experiment_done` | Results collected |
|
|
145
|
+
| `/research-pipeline` | `checkpoint` | Between workflow stages |
|
|
146
|
+
| `/research-pipeline` | `pipeline_done` | Full pipeline complete |
|
|
147
|
+
|
|
148
|
+
## Key Rules
|
|
149
|
+
|
|
150
|
+
- **NEVER block a workflow** because Feishu is unreachable. Always fail open.
|
|
151
|
+
- **NEVER require Feishu config** — all skills must work without it.
|
|
152
|
+
- **Config file absent = mode off.** No error, no warning, no log.
|
|
153
|
+
- **Push mode is fire-and-forget.** Send curl, check exit code, move on.
|
|
154
|
+
- **Interactive timeout = auto-proceed.** Don't hang forever waiting for a reply.
|
|
155
|
+
- **Respect `AUTO_PROCEED`**: In interactive mode, if the user doesn't reply within timeout, use the same auto-proceed logic as the calling skill.
|
|
156
|
+
- **No secrets in notifications.** Never include API keys, tokens, or passwords in Feishu messages.
|