runops 2.5.0__tar.gz → 2.7.0__tar.gz
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.
- {runops-2.5.0 → runops-2.7.0}/PKG-INFO +6 -1
- {runops-2.5.0 → runops-2.7.0}/README.md +5 -0
- {runops-2.5.0 → runops-2.7.0}/SPEC.md +59 -14
- {runops-2.5.0 → runops-2.7.0}/docs/guide.md +46 -4
- {runops-2.5.0 → runops-2.7.0}/docs/reference.md +19 -6
- {runops-2.5.0 → runops-2.7.0}/pyproject.toml +1 -1
- {runops-2.5.0 → runops-2.7.0}/src/runops/__init__.py +1 -1
- {runops-2.5.0 → runops-2.7.0}/src/runops/cli.py +51 -30
- {runops-2.5.0 → runops-2.7.0}/src/runops/harness.py +16 -4
- {runops-2.5.0 → runops-2.7.0}/src/runops/manifest.py +11 -3
- runops-2.7.0/src/runops/ops/analysis.py +113 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/ops/common.py +2 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/ops/create.py +1 -3
- {runops-2.5.0 → runops-2.7.0}/src/runops/ops/notes.py +8 -6
- {runops-2.5.0 → runops-2.7.0}/src/runops/ops/progress.py +16 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/ops/setup.py +3 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/ops/tidy.py +80 -3
- {runops-2.5.0 → runops-2.7.0}/src/runops/project.py +9 -3
- runops-2.7.0/src/runops/skills/runops-analyze/SKILL.md +40 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/skills/runops-check-status/SKILL.md +4 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/skills/runops-reference/SKILL.md +6 -4
- {runops-2.5.0 → runops-2.7.0}/src/runops/skills/runops-tidy/SKILL.md +4 -0
- runops-2.7.0/tests/test_analysis_layout.py +311 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_progress.py +50 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_skills.py +1 -0
- {runops-2.5.0 → runops-2.7.0}/uv.lock +1 -1
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/check/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/improve-harness/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/python-package-refactor/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/python-package-refactor/agents/openai.yaml +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/python-package-refactor/examples/refactor-request.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/python-package-refactor/references/anti-patterns.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/python-package-refactor/references/api-compatibility.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/python-package-refactor/references/packaging-modernization.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/python-package-refactor/references/refactor-playbook.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/python-package-refactor/references/verification.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/python-package-refactor/scripts/api_surface_snapshot.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/python-package-refactor/scripts/import_smoke.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/python-package-refactor/scripts/inspect_python_package.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/python-package-refactor/scripts/refactor_quality_gate.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/release/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/simulator-adapter/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/spec-reviewer/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.agents/skills/sync-docs/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.claude/agents/spec-reviewer.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.claude/rules/architecture.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.claude/rules/dev-workflow.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.claude/rules/gotchas.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.claude/settings.json +0 -0
- {runops-2.5.0 → runops-2.7.0}/.claude/skills/check/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.claude/skills/improve-harness/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.claude/skills/python-package-refactor/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.claude/skills/release/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.claude/skills/simulator-adapter/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.claude/skills/spec-reviewer/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.claude/skills/sync-docs/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.codex/README.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/.codex/agents/spec-reviewer.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/.codex/config.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/.codex/rules/runops.rules +0 -0
- {runops-2.5.0 → runops-2.7.0}/.dockerignore +0 -0
- {runops-2.5.0 → runops-2.7.0}/.gitattributes +0 -0
- {runops-2.5.0 → runops-2.7.0}/.github/assets/conversation-dark.svg +0 -0
- {runops-2.5.0 → runops-2.7.0}/.github/assets/conversation-light.svg +0 -0
- {runops-2.5.0 → runops-2.7.0}/.github/assets/hero-dark.svg +0 -0
- {runops-2.5.0 → runops-2.7.0}/.github/assets/hero-light.svg +0 -0
- {runops-2.5.0 → runops-2.7.0}/.github/assets/make_readme_art.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/.github/workflows/ci.yml +0 -0
- {runops-2.5.0 → runops-2.7.0}/.github/workflows/publish.yml +0 -0
- {runops-2.5.0 → runops-2.7.0}/.gitignore +0 -0
- {runops-2.5.0 → runops-2.7.0}/.harness/manifest.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/.pre-commit-config.yaml +0 -0
- {runops-2.5.0 → runops-2.7.0}/.vscode/settings.json +0 -0
- {runops-2.5.0 → runops-2.7.0}/AGENTS.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/CLAUDE.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/LICENSE +0 -0
- {runops-2.5.0 → runops-2.7.0}/docs/adapter.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/adapters/__init__.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/adapters/base.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/adapters/generic.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/adapters/registry.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/case.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/config.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/errors.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/jobgen.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/launchers.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/legacy_adapters/__init__.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/legacy_adapters/beach.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/legacy_adapters/emses.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/ops/__init__.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/ops/listing.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/ops/migrate.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/ops/skills.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/ops/submit.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/ops/sync.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/runtime.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/skills/runops-create-run/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/skills/runops-maintain/SKILL.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/slurm.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/src/runops/util.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/__init__.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/conftest.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/.codex/rules/a.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/.runops/test-runs/T20260701-0001/receipt.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/.runops/work/beach-x-abc/bin/beach +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/AGENTS.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/CLAUDE.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/cases/beach/plane/beach.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/cases/beach/plane/case.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/cases/old/beach.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/cases/old/case.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/launchers.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/research/CURRENT.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/runops.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/runs/AGENTS.md +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/runs/_archive/plane/R20260601-0001/manifest.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/runs/plane/R20260701-0001--a/input/beach.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/runs/plane/R20260701-0001--a/manifest.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/runs/plane/R20260702-0001/manifest.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/runs/scan/R20260701-0002/manifest.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/runs/scan/survey.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/simulators.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/fixtures/v1-project/site.toml +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/golden/mpi_standard.sh +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/golden/openmp_rsc.sh +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_adapters.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_archive_series.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_build.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_dev_harness.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_jobgen.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_legacy_adapters.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_lifecycle.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_manifest_config.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_migrate.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_mv_naming.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_project_scope.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_run_job.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_safety.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_scratch_tidy.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_setup_misc.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_sweep.py +0 -0
- {runops-2.5.0 → runops-2.7.0}/tests/test_sync_evidence.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: runops
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.0
|
|
4
4
|
Summary: Run ledger and Slurm job submission for HPC simulation projects
|
|
5
5
|
Project-URL: Homepage, https://github.com/Nkzono99/runops
|
|
6
6
|
Project-URL: Documentation, https://github.com/Nkzono99/runops/blob/main/docs/reference.md
|
|
@@ -76,6 +76,7 @@ runo init
|
|
|
76
76
|
| 資源を変えて作り直す | R20261015-0003 を 256 並列・72 時間で作り直して(case はそのまま) |
|
|
77
77
|
| 片付ける | 古い run を整理して。消すものと archive するものを先に見せて |
|
|
78
78
|
| 作り直した旧系列を片付ける | 旧系列は新系列で置き換えたので、対応を記録して archive して |
|
|
79
|
+
| 解析する | この系列の速度を比較して。図とスクリプト、調査メモを系列の `_analysis/` にまとめて |
|
|
79
80
|
| simulator を足す | パッチを当てた ~/BEACH-dev をビルドして、別の simulator として登録して |
|
|
80
81
|
| 更新する | runops と simulator を最新にして |
|
|
81
82
|
| v1 から移る | この project を runops v2 に移行して(`runo migrate-v1` を dry-run で確認してから) |
|
|
@@ -100,15 +101,19 @@ lunar-sheath/
|
|
|
100
101
|
│ │ │ ├── work/ Slurm のログと出力
|
|
101
102
|
│ │ │ └── analysis/
|
|
102
103
|
│ │ └── wc-phiz-scan/ sweep はまとめて 1 階層
|
|
104
|
+
│ │ └── _analysis/ 系列・sweep の比較調査(topic ごと)
|
|
103
105
|
│ ├── _scratch/ smoke / debug(期限付き)
|
|
104
106
|
│ └── _archive/ archive した run
|
|
105
107
|
├── LOG.md run をまたぐ結論と次の判断
|
|
106
108
|
├── notes/ 再利用する知見
|
|
109
|
+
├── analysis/ 複数系列にまたがる調査。共通コードは lib/
|
|
107
110
|
└── AGENTS.md, .agents/skills/, .claude/skills/
|
|
108
111
|
```
|
|
109
112
|
|
|
110
113
|
run は ID が変わらないので、directory を移動してもエージェントは見つけられます。
|
|
111
114
|
`work/` は Git の対象外で、`manifest.toml`、`input/`、`job.sh` は Git で追えます。
|
|
115
|
+
解析は依存する run の範囲で置き場所を選び、調査ごとに `README.md`、`scripts/`、`out/`、
|
|
116
|
+
`logs/` をまとめます。判断は `LOG.md` からリンクし、古い解析 job の log は整理候補になります。
|
|
112
117
|
|
|
113
118
|
## 対応 simulator
|
|
114
119
|
|
|
@@ -45,6 +45,7 @@ runo init
|
|
|
45
45
|
| 資源を変えて作り直す | R20261015-0003 を 256 並列・72 時間で作り直して(case はそのまま) |
|
|
46
46
|
| 片付ける | 古い run を整理して。消すものと archive するものを先に見せて |
|
|
47
47
|
| 作り直した旧系列を片付ける | 旧系列は新系列で置き換えたので、対応を記録して archive して |
|
|
48
|
+
| 解析する | この系列の速度を比較して。図とスクリプト、調査メモを系列の `_analysis/` にまとめて |
|
|
48
49
|
| simulator を足す | パッチを当てた ~/BEACH-dev をビルドして、別の simulator として登録して |
|
|
49
50
|
| 更新する | runops と simulator を最新にして |
|
|
50
51
|
| v1 から移る | この project を runops v2 に移行して(`runo migrate-v1` を dry-run で確認してから) |
|
|
@@ -69,15 +70,19 @@ lunar-sheath/
|
|
|
69
70
|
│ │ │ ├── work/ Slurm のログと出力
|
|
70
71
|
│ │ │ └── analysis/
|
|
71
72
|
│ │ └── wc-phiz-scan/ sweep はまとめて 1 階層
|
|
73
|
+
│ │ └── _analysis/ 系列・sweep の比較調査(topic ごと)
|
|
72
74
|
│ ├── _scratch/ smoke / debug(期限付き)
|
|
73
75
|
│ └── _archive/ archive した run
|
|
74
76
|
├── LOG.md run をまたぐ結論と次の判断
|
|
75
77
|
├── notes/ 再利用する知見
|
|
78
|
+
├── analysis/ 複数系列にまたがる調査。共通コードは lib/
|
|
76
79
|
└── AGENTS.md, .agents/skills/, .claude/skills/
|
|
77
80
|
```
|
|
78
81
|
|
|
79
82
|
run は ID が変わらないので、directory を移動してもエージェントは見つけられます。
|
|
80
83
|
`work/` は Git の対象外で、`manifest.toml`、`input/`、`job.sh` は Git で追えます。
|
|
84
|
+
解析は依存する run の範囲で置き場所を選び、調査ごとに `README.md`、`scripts/`、`out/`、
|
|
85
|
+
`logs/` をまとめます。判断は `LOG.md` からリンクし、古い解析 job の log は整理候補になります。
|
|
81
86
|
|
|
82
87
|
## 対応 simulator
|
|
83
88
|
|
|
@@ -119,12 +119,14 @@ v1 で運用した 2 つの project(`project_dust_release`: BEACH、run 120、
|
|
|
119
119
|
<run_id>--<label>/ # 単発 run
|
|
120
120
|
<sweep_label>/
|
|
121
121
|
<run_id>--<label>/ # sweep で生成された run
|
|
122
|
+
_analysis/<topic>/ # この group に依存する調査(§9.1)
|
|
122
123
|
_scratch/
|
|
123
124
|
<run_id>--<label>/ # scratch run
|
|
124
125
|
_archive/
|
|
125
126
|
<case_name>/... # archive された run(元の相対 path を保つ)
|
|
126
127
|
adapters/ # 任意。project ローカル adapter `<name>.py`(§8.1)
|
|
127
128
|
notes/ # 永続的な知見。1 topic 1 file。runops は管理しない(§9)
|
|
129
|
+
analysis/<topic>/ # 複数 group にまたがる調査。共通コードは analysis/lib/(§9.1)
|
|
128
130
|
LOG.md # project 全体の追記専用ログ(§9)
|
|
129
131
|
AGENTS.md # agent 向け入口(§10)
|
|
130
132
|
CLAUDE.md # `@AGENTS.md` のみ
|
|
@@ -147,7 +149,8 @@ v1 で運用した 2 つの project(`project_dust_release`: BEACH、run 120、
|
|
|
147
149
|
`runs/` 配下の任意の場所に移動してよい。runops は manifest の `run.id` で run を
|
|
148
150
|
見つける(§7.2)。
|
|
149
151
|
- 既定の配置先は `runs/<case_name>/`。`--dest` で上書きできる。`_` で始まる
|
|
150
|
-
directory(`_scratch`、`_archive`)は runops が予約する。
|
|
152
|
+
directory(`_scratch`、`_archive`、`_analysis`)は runops が予約する。
|
|
153
|
+
`_analysis` は group の調査用で、run の発見・作成先から除く。
|
|
151
154
|
- run directory の中(自身と子孫)には run を置けない。`--dest` が既存 run の中なら拒否し、
|
|
152
155
|
`delete` は中に別の run があれば拒否する(§7.2 の走査は manifest のある directory で止まる)。
|
|
153
156
|
- run id は `R<YYYYMMDD>-<NNNN>`。その日の既存 run と `.runops/last_run_id` の大きい方に 1 を足す。
|
|
@@ -160,7 +163,8 @@ v1 で運用した 2 つの project(`project_dust_release`: BEACH、run 120、
|
|
|
160
163
|
- `materials/`、`refs/`、`scripts/` などユーザーが置く directory は runops の関知外。
|
|
161
164
|
runops は `runs/`、`cases/`、`.runops/`、`.agents/skills/`、`.claude/skills/`、
|
|
162
165
|
`AGENTS.md`、`CLAUDE.md`、`runops.toml` 以外を作成・変更しない(`LOG.md`、`notes/`
|
|
163
|
-
は `init`
|
|
166
|
+
は `init` の雛形生成のみ)。例外として `tidy --apply --only analysis-logs` は
|
|
167
|
+
§7.5 の解析 log を削除できる。解析のスクリプト・結果・README は agent が書く。
|
|
164
168
|
|
|
165
169
|
---
|
|
166
170
|
|
|
@@ -471,8 +475,12 @@ adapter が `progress(run_dir)` を持つとき、`sync` は running の run と
|
|
|
471
475
|
上限 1000 件程度)。queue を離れたときの観測は終了時刻で記録し、終了後の待ち時間を速度に含めない。
|
|
472
476
|
- 要約を `[[job.attempts]].progress` に置く: `done`、`total`、`unit`、`start`、`fraction`、
|
|
473
477
|
`rate_recent_per_hour`(直近 10 分)、`rate_attempt_per_hour`(program 開始から。起点は
|
|
474
|
-
`start`)、`eta_hours`(running
|
|
478
|
+
`start`)、`eta_hours`(running のみ)、`last_change_at`(`done` が最後に増えた観測時刻)、
|
|
479
|
+
`stalled_hours`(最新観測が `last_change_at` から 1 時間以上進んでいないとき、その長さ。
|
|
480
|
+
終了後の観測には付けない)。program 開始時刻は job.sh が stdout に出す
|
|
475
481
|
`runops: start` 行から取り、`started_at` に入れる。
|
|
482
|
+
- `status` / `list` は `stalled_hours` があれば `stalled 6.7h` と表示する。観測は `sync` のときだけ
|
|
483
|
+
なので、停止の検出は `sync` の間隔より細かくならない。
|
|
476
484
|
- `status` / `list` は要約だけを読む(file を開かない)。read-only command は観測を足さない。
|
|
477
485
|
- 解析は adapter が行い、runops は保存と表示だけを持つ(§1.2 #4)。
|
|
478
486
|
|
|
@@ -493,7 +501,8 @@ adapter が `progress(run_dir)` を持つとき、`sync` は running の run と
|
|
|
493
501
|
`--json` は作成した run の同じ summary を返す。summary には `params`、`changed_keys`、
|
|
494
502
|
`parent_run`、`exe_hash`、`input_hash` を含め、run 同士の比較に別 command を要らなくする。
|
|
495
503
|
walltime の根拠として `walltime`、最新 attempt の `elapsed`、`walltime_used`(elapsed / walltime)、
|
|
496
|
-
`slurm_state`(`TIMEOUT`
|
|
504
|
+
`slurm_state`(`TIMEOUT` など)も含める。`list` / `status` の `--brief` は summary から
|
|
505
|
+
`params`、`why`、`last_note` を外す(多数の run を横断して渡すとき用。表では note / why 列を省く)。
|
|
497
506
|
- 破壊的 command(`cancel`、`delete`、`tidy --apply`、`archive`)は対象を表示して
|
|
498
507
|
確認を取る。`-y/--yes` で省略。
|
|
499
508
|
- exit code: 0 成功、1 対象 run の実行時エラー(例: sbatch 失敗)、2 使用方法・設定エラー。
|
|
@@ -503,7 +512,7 @@ adapter が `progress(run_dir)` を持つとき、`sync` は running の run と
|
|
|
503
512
|
- `runs/` 配下(`_archive/` を含む)を再帰的に走査し `manifest.toml` を集める。
|
|
504
513
|
`.runops/index.toml` に `run_id -> run_dir` の cache を持ち、manifest が cache の
|
|
505
514
|
path に無ければ再走査して cache を更新する。cache は常に再生成可能で、
|
|
506
|
-
|
|
515
|
+
壊れていても動作に影響しない。`_analysis/` は走査せず、そこにある manifest は run と扱わない。
|
|
507
516
|
- 走査対象は `runs/` のみ。project 外や `runs/` 外の run は扱わない。
|
|
508
517
|
|
|
509
518
|
### 7.3 command 一覧
|
|
@@ -514,7 +523,7 @@ adapter が `progress(run_dir)` を持つとき、`sync` は running の run と
|
|
|
514
523
|
| `runo doctor [--json]` | `runops.toml` の妥当性、adapter の import 可否、executable の存在、`sbatch` の有無、skill の鮮度を検査 |
|
|
515
524
|
| `runo update [--skills-only] [-y]` | adapter package を upgrade し、skill を再展開する |
|
|
516
525
|
| `runo build SIM [--force]` | `local_source` simulator を `.runops/build/` に build する(§4.1) |
|
|
517
|
-
| `runo context [--json]` | agent 向け現在地。project 名、simulator、active run
|
|
526
|
+
| `runo context [--json]` | agent 向け現在地。project 名、simulator、active run 数と全 active run(`--brief` と同じ summary、`active`)、直近 run 5 件、scratch 期限切れ数、`LOG.md` 末尾 20 行、現用 group の解析 topic 名(§9.1)。配置した runops skill が install 済みの runops より古ければ `runo update --skills-only` を促す warning |
|
|
518
527
|
| `runo case new NAME --simulator SIM [--from CASE]` | case をスキャフォールド。adapter の `case_template()` を展開 |
|
|
519
528
|
| `runo case list` | case 一覧 |
|
|
520
529
|
| `runo new CASE [--why TEXT] [--label L] [--set k=v]... [--job k=v]... [--tag T]... [--scratch] [--dest DIR] [--submit] [--created-by WHO] [--json]` | 単発 run を作る |
|
|
@@ -524,10 +533,10 @@ adapter が `progress(run_dir)` を持つとき、`sync` は running の run と
|
|
|
524
533
|
| `runo submit --all [DIR] [-y]` | DIR 配下の `created` run をすべて投入。件数と概算 core-hours を表示して確認 |
|
|
525
534
|
| `runo cancel RUN... [--why TEXT] [-y]` | scancel して sync。`--why` は `cancelled: ...` の note として残す |
|
|
526
535
|
| `runo retry RUN [--submit] [-y]` | `failed`/`cancelled` を `created` に戻す。直近の cancel に `--why` があれば理由を示して確認を取る |
|
|
527
|
-
| `runo status [RUN...] [--json]` | manifest の状態を表示。Slurm
|
|
536
|
+
| `runo status [RUN...] [--brief] [--json]` | manifest の状態を表示。Slurm を呼ばない。`--brief` は §7.1 |
|
|
528
537
|
| `runo sync [RUN...] [--json]` | squeue/sacct で状態を更新。引数なしは `submitted`/`running` 全件 |
|
|
529
538
|
| `runo log RUN [--err] [-n N] [-f]` | 最新 job の stdout/stderr を表示。`-f` は tail -f |
|
|
530
|
-
| `runo list [PATH] [--all] [--since 30d] [--case C] [--sweep L] [--status S]... [--tag T]... [--scratch] [--archived] [--json]` | run 一覧(§7.4) |
|
|
539
|
+
| `runo list [PATH] [--all] [--since 30d] [--case C] [--sweep L] [--status S]... [--tag T]... [--scratch] [--archived] [--brief] [--json]` | run 一覧(§7.4) |
|
|
531
540
|
| `runo note RUN [TEXT] [--by WHO]` | TEXT があれば `[[notes]]` に追記、なければ notes と `notes.md` を表示 |
|
|
532
541
|
| `runo pin RUN [--off] [--reason TEXT]` | `run.pinned` を切り替える。pinned は `list` に常に出て、`tidy` / `delete` の対象外 |
|
|
533
542
|
| `runo summarize RUN... [--force]` | adapter の `summarize()` を呼び `analysis/summary.json` を書く。既存があれば `--force` なしではスキップ |
|
|
@@ -546,13 +555,14 @@ adapter が `progress(run_dir)` を持つとき、`sync` は running の run と
|
|
|
546
555
|
- 既定で表示しない: scratch run、archived run、上記以外の古い terminal run。
|
|
547
556
|
- `--all` は scratch と archived 以外をすべて表示。`--scratch`、`--archived` は
|
|
548
557
|
それぞれを **追加** する。
|
|
549
|
-
- 表示列: id、status、label、case、sweep、created
|
|
558
|
+
- 表示列: id、status、label、case、sweep、created(相対時刻)、elapsed、progress、最新 note の先頭 60 文字、`why`。
|
|
559
|
+
`--brief` は note と `why` の列を省く。
|
|
550
560
|
- sort は `created_at` 降順。
|
|
551
561
|
- `PATH` を与えた場合はその directory 配下に限定する。
|
|
552
562
|
|
|
553
563
|
### 7.5 `tidy` の規則
|
|
554
564
|
|
|
555
|
-
`tidy` は候補を
|
|
565
|
+
`tidy` は候補を 6 種に分けて表示する。`--apply` はすべてを実行し、
|
|
556
566
|
`--apply --only KIND` で絞れる。
|
|
557
567
|
|
|
558
568
|
| kind | 条件 | 動作 |
|
|
@@ -562,8 +572,14 @@ adapter が `progress(run_dir)` を持つとき、`sync` は running の run と
|
|
|
562
572
|
| `old-completed` | `completed` で `defaults.tidy_archive_days`(既定 90)日より古く、`pinned = false` | archive |
|
|
563
573
|
| `orphan-job` | `submitted`/`running` だが squeue/sacct に job が無い | sync(state 確定) |
|
|
564
574
|
| `unused-build` | `.runops/build/*` のうち、非 archived run の manifest から参照されないもの | delete |
|
|
575
|
+
| `analysis-logs` | §9.1 の解析 directory 配下の `logs/` にある `*.<jobid>.out/err`。組の最終更新が `tidy_failed_days` より古く、同じ log directory・job 名の最新の組ではない | log file のみ delete |
|
|
565
576
|
|
|
566
577
|
- `--older-than AGE`(例 `14d`)はその回だけ、上の 2 つの日数をどちらもこの値で置き換える。
|
|
578
|
+
- `analysis-logs` は project の `analysis/`、group の `_analysis/`、run の `analysis/`
|
|
579
|
+
(topic の下も含む)を対象にする。stdout/stderr は同じ job id の組として更新時刻を比較し、
|
|
580
|
+
最新の組は常に残す。同時刻なら job id が大きい組を最新とする。片方だけの log も同じ扱い。
|
|
581
|
+
archived / pinned / submitted / running run の解析と、symlink は対象外。
|
|
582
|
+
適用直前にも対象範囲・更新時刻・最新組を再確認し、条件が変われば削除せず止まる。
|
|
567
583
|
- `--purge-work RUN...` は指定 run の `work/` の中身を削除し `work_purged_at` を記録する。
|
|
568
584
|
adapter が `keep_patterns()` を返す場合、一致するファイルは残す。`completed` 以外は拒否。
|
|
569
585
|
adapter を読み込めない(残すファイルを判定できない)ときは何も消さずにエラーにする。
|
|
@@ -710,7 +726,7 @@ runops は `init` と `update` で次を行う。
|
|
|
710
726
|
|
|
711
727
|
### 8.3 runops 自身の skill
|
|
712
728
|
|
|
713
|
-
runops は次の
|
|
729
|
+
runops は次の 6 skill だけを同梱し、simulator skill と同じ仕組みで展開する。
|
|
714
730
|
利用者が覚えるコマンドは `runo init` だけとし、それ以外(simulator の追加、更新、v1 移行を含む)は
|
|
715
731
|
エージェントへの依頼で行う。
|
|
716
732
|
各 SKILL.md は 60 行以内に収める。
|
|
@@ -720,6 +736,7 @@ runops は次の 5 skill だけを同梱し、simulator skill と同じ仕組み
|
|
|
720
736
|
| `runops-create-run` | `new` / `sweep` の使い方。`--why` を必ず書く、scratch の使い分け |
|
|
721
737
|
| `runops-check-status` | `sync` → `list` → `log` の順。失敗時の `retry` と `tidy --purge-work` |
|
|
722
738
|
| `runops-tidy` | `tidy` を定期的に実行する判断基準。pin の使い方 |
|
|
739
|
+
| `runops-analyze` | 依存する run の範囲で調査の置き場所を決め、script・結果・log・README をまとめる |
|
|
723
740
|
| `runops-reference` | command 一覧(§7.3 の表をそのまま載せる) |
|
|
724
741
|
| `runops-maintain` | simulator の追加、runops と simulator package の更新、`migrate-v1`、`doctor` の読み方 |
|
|
725
742
|
|
|
@@ -748,7 +765,7 @@ v1 の `emses` / `beach` adapter は次の順で runops 本体から出す。
|
|
|
748
765
|
見つかると使われなくなる(解決順 1 が優先)ので、ユーザーが消せばよい。
|
|
749
766
|
---
|
|
750
767
|
|
|
751
|
-
## 9.
|
|
768
|
+
## 9. ノートと解析
|
|
752
769
|
|
|
753
770
|
置き場所は 3 つに固定し、runops はどれも「管理」しない(schema、budget、rotation、
|
|
754
771
|
seal、index を持たない)。
|
|
@@ -766,10 +783,33 @@ seal、index を持たない)。
|
|
|
766
783
|
- 複数 run にまたがる結論と次の判断は `LOG.md` に日付付きで追記する
|
|
767
784
|
- 再利用する式・手法・環境の落とし穴は `notes/<topic>.md` に書く。既存 file があれば追記し、
|
|
768
785
|
似た topic の file を増やさない
|
|
769
|
-
-
|
|
786
|
+
- 調査の詳細は §9.1 の README にまとめ、LOG.md からリンクする
|
|
770
787
|
- v1 の `research/results/`、`.runops/insights/`、`research/archive/legacy/` は移行時に
|
|
771
788
|
`notes/legacy/` 配下へ **移動せず** そのまま残し、`notes/README.md` から path を案内する(§11)。
|
|
772
789
|
|
|
790
|
+
### 9.1 解析の置き場所
|
|
791
|
+
|
|
792
|
+
| 結果が依存する範囲 | 置き場所 |
|
|
793
|
+
|---|---|
|
|
794
|
+
| 1 run | `runs/.../<RUN>/analysis/`(必要なら `<topic>/`) |
|
|
795
|
+
| 1 group(同じ directory に並ぶ系列・sweep) | `runs/<group>/_analysis/<topic>/` |
|
|
796
|
+
| 複数 group・case または project 全体 | `analysis/<topic>/` |
|
|
797
|
+
| 共通コード | `analysis/lib/` |
|
|
798
|
+
|
|
799
|
+
- group は directory であり、新しい entity / ID / ledger を持たない。
|
|
800
|
+
- 調査 directory は `README.md`(問い・対象 run id・方法・結果・制約)、`scripts/`
|
|
801
|
+
(Python、sbatch)、`out/`(図・JSON・CSV)、`logs/`(job の stdout/stderr)からなる。
|
|
802
|
+
topic は内容で名付け、同じ問いは README に日付付きで追記する。
|
|
803
|
+
- `init` の `.gitignore` は `**/logs/`、`__pycache__/`、`.runops/analysis-env/` を含む。
|
|
804
|
+
既存 project のファイルは自動で再配置しない。
|
|
805
|
+
- `context` は現用 group の `_analysis/*/README.md` がある topic 名を表示し、
|
|
806
|
+
`--json` では `group_analysis` に project 相対の group path → topic 名一覧を返す。
|
|
807
|
+
README 本文や `out/`、simulator の `work/` は読まない。
|
|
808
|
+
- `archive DIR` が group 配下の全 run を移す場合、その group と配下の group の
|
|
809
|
+
`_analysis/` も同じ相対 path の `runs/_archive/` に移す。run が残る group の解析は残す。
|
|
810
|
+
確認表示に解析の移動先を含め、移動前に run と解析の全移動先を検査し、既存なら上書きしない。
|
|
811
|
+
`archive RUN...` / `--older-than` は group の解析を動かさず、`restore RUN` は run のみを戻す。
|
|
812
|
+
|
|
773
813
|
---
|
|
774
814
|
|
|
775
815
|
## 10. harness 生成
|
|
@@ -916,7 +956,7 @@ src/runops/
|
|
|
916
956
|
| 項目 | 目標 |
|
|
917
957
|
|---|---|
|
|
918
958
|
| `src/runops/` の行数(skill の md を除く) | 8,000 行以下 |
|
|
919
|
-
| CLI command 数(`case new` / `case list` を含む。同じ command の option 違いは数えない) | 25 以下。§7.3 の表の distinct command は
|
|
959
|
+
| CLI command 数(`case new` / `case list` を含む。同じ command の option 違いは数えない) | 25 以下。§7.3 の表の distinct command は 25 |
|
|
920
960
|
| ユーザーが編集する TOML | `runops.toml`、`case.toml` の 2 種 |
|
|
921
961
|
| runops が書く TOML | `manifest.toml`、`.runops/skills.lock`、`.runops/index.toml` の 3 種 |
|
|
922
962
|
| 依存 | `typer`、`rich`、`tomli-w`、`tomlkit`、`jinja2`、`packaging`(`mcp` を外す) |
|
|
@@ -954,6 +994,9 @@ src/runops/
|
|
|
954
994
|
9b. 同名 adapter が entry point と `adapters/X.py` の両方にあるとき entry point が優先される。
|
|
955
995
|
どちらも無く `generic` でもなければ exit code 2 で案内が出る。
|
|
956
996
|
10. `manifest.toml` の書き込み途中で例外が起きても元のファイルが壊れない。
|
|
997
|
+
11. 解析 log の tidy は最新組・新しい組・対象外ファイルを残し、確認後の更新も削除しない。
|
|
998
|
+
group の archive は全 run が対象のときだけ解析も移し、衝突時は何も動かさない。
|
|
999
|
+
context は調査の名前だけを読み、解析内の manifest を run と誤認しない。
|
|
957
1000
|
|
|
958
1001
|
### 13.3 ドキュメント
|
|
959
1002
|
|
|
@@ -974,6 +1017,7 @@ v2 の文書は次の 4 ファイルだけにする。
|
|
|
974
1017
|
|
|
975
1018
|
| 項目 | 決定 | 理由 |
|
|
976
1019
|
|---|---|---|
|
|
1020
|
+
| 解析の配置 2.6.0(2026-10-23) | 依存する run の範囲に応じて run 内 `analysis/`、group の `_analysis/<topic>/`、project の `analysis/<topic>/` にまとめる。skill、log の tidy、group archive、context を対応させる(§9.1) | 報告・図・script・job log が分散・混在していた。group は既存の directory として扱い、新しい entity や command は足さない。既存ファイルの整理は移動一覧を提示してから行う |
|
|
977
1021
|
| job の cwd | run_dir(v1 と同じ)。Slurm log は `work/` | v1 adapter の path 規約と実 project の job.sh をそのまま使える |
|
|
978
1022
|
| adapter の追加 hook | `configure(sim_config)`、`job_prelude(run_dir)` | generic の `command` 取得と、EMSES の `rm -f *_0000.h5` など v1 の setup command を表す |
|
|
979
1023
|
| launcher `kind = "none"` | MPI launcher を使わず program を直接実行 | OpenMP のみの BEACH run 用 |
|
|
@@ -1000,5 +1044,6 @@ v2 の文書は次の 4 ファイルだけにする。
|
|
|
1000
1044
|
| 生成ハーネスの書き方(2026-10-21) | AGENTS.md の Rules を「作業の進め方」5 項目に絞り、各項目を「何をするか」と短い理由で書く。skill は手順に専念し、AGENTS.md の方針(manifest を手で編集しない等)を繰り返さない | #112・#113 で規則が増え、禁止形(never / do not)が並んでいた。現行の Claude の prompting 指針は、しないことより何をするかを、理由と共に書くことを勧め、強い禁止語は過剰反応を招くとしている |
|
|
1001
1045
|
| 複数 run の mv / archive(2026-10-22) | 1 回の `run.lock` の下で全対象を読み直して検査し、通ってから移す。途中の filesystem error では移し終えた run id を示して止まる | `mv A B C --dest X` は 1 件ずつ検査して移していたので、途中の submitted run で一部だけ移動していた。archive は表示の後で lock を取り直していて、その間に再投入された run で同じことが起き得た |
|
|
1002
1046
|
| 進捗と系列配置 2.5.0(2026-10-23) | adapter に任意の `progress()`、`sync` が時刻付き観測を保存し速度・残り時間を要約(§6.4)。`new --from` の既定置き場所を元 run と同じ directory に。agent context の `docs/` も展開 | 速度比較のために agent が時刻付き batch 観測を手で保存し、再開点や終了後の待ちを毎回補正していた(4 回)。継続世代が case 直下に並び、同じ計算の系列を見分けにくかった。skill が package の `docs/` を参照していたが展開されていなかった。進捗の解析は simulator 固有なので adapter が持ち、runops は保存と表示だけにする |
|
|
1047
|
+
| 横断の状態確認 2.7.0(2026-10-30) | `list` / `status` に `--brief`、`context` に全 active run の `active`、progress 要約に `last_change_at` と `stalled_hours`(§6.4、§7.1、§7.3) | hub で 4 project の active run を集めるのに `recent_runs` 5 件では足りず、全 `params` 付きの `list --json` は shell 引数長を超えた(3 回)。進捗が 6 時間止まった run を 49% と報告した。新しい command は足さず、既存の summary を小さくし、観測から止まりを出す |
|
|
1003
1048
|
| FEEDBACK 棚卸し 2.4.0(2026-10-23) | `--job k=v` と `new --from` の `[job]` 継承、created の archive / restore、archived scratch を期限削除しない、展開 skill の references 参照の書き換えと `doctor` のリンク検査、adapter warning への版の併記、生成 AGENTS.md に解析環境の置き場所 | hub の FEEDBACK で、資源変更のための case 編集(3 回)、置換済み draft を archive できず helper で迂回(2 回)、保管目的の archive が期限削除される、skill から reference に辿れない、新版の正規キーが誤記に見える、解析依存の置き場所が project ごとに違う、が記録された。いずれも既存 command の拡張で、command 数は増やさない |
|
|
1004
1049
|
| 使い方ガイド | `docs/guide.md` を追加し、文書を 4 ファイルにする(§13.3) | README の依頼例の表と command 一覧の間を埋める、場面ごとの流れ(case と run の分け方、smoke から本計算、状態の決まり方、整理)の置き場所が無かった |
|
|
@@ -134,7 +134,10 @@ walltime は、同じ case・同じ資源で終わった run の実時間を元
|
|
|
134
134
|
adapter が進捗に対応していれば(BEACH の batch、MPIEMSES3D の step)、`sync` のたびに時刻付きの
|
|
135
135
|
観測を残し、`runo list` / `status` に `62% 0.198 s/batch eta 3.1h` のように進み具合、直近 10 分の
|
|
136
136
|
速度、残り時間を出します。resume した run は再開点から数え、終わった run は終了時刻までで速度を出すので、
|
|
137
|
-
版を切り替えた前後の比較にそのまま使えます(`--json` の `progress
|
|
137
|
+
版を切り替えた前後の比較にそのまま使えます(`--json` の `progress`)。`sync` を重ねても進みが 1 時間以上
|
|
138
|
+
変わらない run には `stalled 6.7h` が付くので、Slurm では RUNNING でも止まっている run を見分けられます。
|
|
139
|
+
全 project を横断して見るときは `runo context --json` の `active`(全 active run)か `runo list --brief --json`
|
|
140
|
+
(`params` や note を省いた小さい JSON)を使います。
|
|
138
141
|
|
|
139
142
|
### 状態の決まり方
|
|
140
143
|
|
|
@@ -192,7 +195,7 @@ project の run だけが対象です。同じアカウントの別 project の
|
|
|
192
195
|
前の job が終わるのを待って投入したいときは、「R20261016-0005 が成功したら投げて」と頼めば
|
|
193
196
|
`runo submit RUN --afterok <job_id>` になります。
|
|
194
197
|
|
|
195
|
-
## 6.
|
|
198
|
+
## 6. 解析して記録を残す
|
|
196
199
|
|
|
197
200
|
記録の置き場所は 3 つに決まっています。
|
|
198
201
|
|
|
@@ -202,10 +205,40 @@ project の run だけが対象です。同じアカウントの別 project の
|
|
|
202
205
|
| 複数の run をまたぐ結論と次の判断 | `LOG.md` に日付見出しで追記 | 今日の scan の結論を LOG にまとめて |
|
|
203
206
|
| 再利用する式、手法、落とし穴 | `notes/<topic>.md`(1 topic 1 file) | Debye 長の見積もり方を notes に残して |
|
|
204
207
|
|
|
205
|
-
エージェントはこれ以外の場所(`research/`、`analysis/*.md`、`runs/` の下など)にノートを作りません。
|
|
206
208
|
`notes/` に似た topic の file があれば、新しく作らずに追記します。
|
|
207
209
|
|
|
208
|
-
|
|
210
|
+
調査の詳細と図・スクリプトは、結果が依存する run の範囲に合わせてまとめます。
|
|
211
|
+
|
|
212
|
+
> この系列の速度を比較して。図とスクリプト、調査メモを系列の `_analysis/` にまとめて。
|
|
213
|
+
|
|
214
|
+
| 依存する範囲 | 置き場所 |
|
|
215
|
+
|---|---|
|
|
216
|
+
| 1 run | `<run_dir>/analysis/`(必要なら topic を切る) |
|
|
217
|
+
| 1 系列・sweep | `runs/<group>/_analysis/<topic>/` |
|
|
218
|
+
| 複数系列・case、project 全体 | `analysis/<topic>/` |
|
|
219
|
+
| 共通コードとそのテスト | `analysis/lib/` |
|
|
220
|
+
|
|
221
|
+
group は run が並ぶ directory です。登録や新しい ID は要りません。
|
|
222
|
+
topic は `speed-by-version` のように問いの内容で名付け、同じ問いをやり直すときは
|
|
223
|
+
同じ directory の結果を更新し、README に日付付きで追記します。
|
|
224
|
+
|
|
225
|
+
```text
|
|
226
|
+
<topic>/
|
|
227
|
+
README.md 問い・対象 run id と path・方法・結果・制約
|
|
228
|
+
scripts/ Python と sbatch
|
|
229
|
+
out/ 図、JSON、CSV、HTML
|
|
230
|
+
logs/ 解析 job の stdout/stderr(Git 管理外)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
エージェントは `runops-analyze` skill を使い、調査の README と、そこへのリンクを含む
|
|
234
|
+
`LOG.md` の判断を更新します。`notes/` は run に依存しない知見に使います。
|
|
235
|
+
解析の追加依存は `.runops/analysis-env/` に置き、重い読み込みや作図はサイトの規則に従って
|
|
236
|
+
計算ノードで実行します。sbatch は調査 directory から投入し、事前に `logs/` を作って
|
|
237
|
+
`#SBATCH -o logs/%x.%j.out` と `#SBATCH -e logs/%x.%j.err` を指定します。
|
|
238
|
+
既存 project のファイルは自動で移動しません。整理を頼むと、移動前に一覧を提示します。
|
|
239
|
+
|
|
240
|
+
`runo context` は `LOG.md` の末尾、`notes/` の file 名、現用 group の
|
|
241
|
+
`_analysis/*/README.md` がある topic 名を表示します。エージェントは作業の始めに
|
|
209
242
|
これを読むので、前回の続きから話を始められます。
|
|
210
243
|
|
|
211
244
|
## 7. 整理する
|
|
@@ -221,6 +254,7 @@ run は消さなくても `runo list` が古いものを隠しますが、direct
|
|
|
221
254
|
| `expired-scratch` | 期限切れの scratch run(archive したものは除く) | 削除 |
|
|
222
255
|
| `stale-failed` | 30 日より古い failed / cancelled で、`why` もノートも無い | 削除 |
|
|
223
256
|
| `old-completed` | 90 日より古い completed | archive |
|
|
257
|
+
| `analysis-logs` | 30 日より古い解析 job の log(各 job 名の最新組は保持) | log のみ削除 |
|
|
224
258
|
| `orphan-job` | 投入済みなのに Slurm が知らない | `sync` で状態を確定 |
|
|
225
259
|
| `unused-build` | どの run も使っていない build cache | 削除 |
|
|
226
260
|
|
|
@@ -239,6 +273,14 @@ run id で引き続き見つかり、`runo restore` で戻せます。
|
|
|
239
273
|
記録され、理由はノートに残ります。比較用に派生しただけの run は置き換えとは扱わないので、
|
|
240
274
|
旧系列が不要かどうかは毎回確かめます。
|
|
241
275
|
|
|
276
|
+
directory 指定で group の全 run を archive すると、その `_analysis/` も同じ相対 path で
|
|
277
|
+
移動します。run が残る group の解析は元の場所に残り、移動先に既存の解析があれば、run を
|
|
278
|
+
動かす前に停止します。`archive RUN...` と `restore RUN` は run だけを移動します。
|
|
279
|
+
|
|
280
|
+
解析 log だけの整理は「古い解析 log を整理して」で `runo tidy --only analysis-logs` に
|
|
281
|
+
なります。各 `logs/` の `*.<jobid>.out/err` を組で比較し、job 名ごとに最新の組を残します。
|
|
282
|
+
片方が新しければ両方とも残し、README、script、結果は削除しません。
|
|
283
|
+
|
|
242
284
|
論文の図に使う run や基準にする run は pin しておくと、`list` に常に表示され、`tidy` や `delete`
|
|
243
285
|
の対象になりません。
|
|
244
286
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
## runops.toml
|
|
7
7
|
|
|
8
8
|
project root にあり、`runo` はここを上方向に探して project を特定します。
|
|
9
|
-
command はこの project の `runs/` 配下だけを扱い、別 project の run directory や
|
|
9
|
+
run を対象にする command はこの project の `runs/` 配下だけを扱い、別 project の run directory や
|
|
10
10
|
directory を path で渡すとエラーになります。run id は project ごとなので、同じ id が
|
|
11
11
|
別 project にあっても cwd の project の run を指します。
|
|
12
12
|
|
|
@@ -141,7 +141,8 @@ run id は削除後も再利用しません。`--dest` に既存 run の中は
|
|
|
141
141
|
`list --json` と `status --json` は、walltime の根拠として `walltime`、最新 attempt の `elapsed`、
|
|
142
142
|
`walltime_used`(elapsed / walltime)、`slurm_state` も返します。adapter が `progress()` を持てば
|
|
143
143
|
`progress`(`done`、`total`、`unit`、`fraction`、`rate_recent_per_hour`、`rate_attempt_per_hour`、
|
|
144
|
-
`eta_hours`)も返し、表の `progress` 列に `62% 0.198 s/batch eta 3.1h`
|
|
144
|
+
`eta_hours`、`last_change_at`、`stalled_hours`)も返し、表の `progress` 列に `62% 0.198 s/batch eta 3.1h` と出します。
|
|
145
|
+
`sync` の観測で `done` が 1 時間以上増えていなければ `stalled 6.7h` が付きます(観測は `sync` のときだけ)。表では `TIMEOUT` などを
|
|
145
146
|
`failed (TIMEOUT)` と示します。
|
|
146
147
|
|
|
147
148
|
全 command は `--help` で option を確認できます。`RUN` には run id、run directory、
|
|
@@ -153,15 +154,15 @@ run id は削除後も再利用しません。`--dest` に既存 run の中は
|
|
|
153
154
|
| `runo doctor [--json]` | 設定、adapter の解決経路、executable、sbatch、skill の鮮度とリンク切れを点検 |
|
|
154
155
|
| `runo update [--skills-only] [-y]` | simulator package を更新し skill と AGENTS.md の管理 block を再生成 |
|
|
155
156
|
| `runo build SIM [--force]` | `local_source` の simulator を build |
|
|
156
|
-
| `runo context [--json]` | agent
|
|
157
|
+
| `runo context [--json]` | agent 向けの現在地。全 active run(`active`、`--brief` と同じ形)、直近 5 run、現用 group の解析 topic 名(JSON の `group_analysis` は group path → topic 名一覧) |
|
|
157
158
|
| `runo case new NAME [-s SIM] [--from CASE]` / `runo case list` | case の作成と一覧 |
|
|
158
159
|
| `runo new CASE [--why] [--label] [--set k=v]... [--job k=v]... [--tag] [--scratch] [--dest DIR] [--submit] [--json]` | run を 1 つ作る。`--job` はこの run の `[job]` の値 |
|
|
159
160
|
| `runo new --from RUN [--set k=v]... [--job k=v]... [--job-from-case] [--continue]` | 既存 run の params と `[job]` から派生(`--job-from-case` で `[job]` は case から)。置き場所の既定は元 run と同じ directory。`--continue` は adapter の restart 対応が必要 |
|
|
160
161
|
| `runo sweep CASE --set k=v1,v2 ... [--names k=n1,n2...] [--job k=v]... [--label] [--dest DIR] [--limit N] [--apply] [--submit] [--json]` | 直積の候補表示。`--apply` で作成。`--names` は各値の短い label、`--dest` は sweep directory の親 |
|
|
161
162
|
| `runo submit RUN... [-p P] [--qos Q] [--afterok JOB]` / `runo submit --all [DIR] [-y]` | job.sh を生成して sbatch |
|
|
162
163
|
| `runo cancel RUN... [--why TEXT] [-y]` / `runo retry RUN [--submit] [-y]` | scancel(`--why` は note に残る)/ failed・cancelled を created に戻す(理由付きで cancel された run は確認を取る) |
|
|
163
|
-
| `runo status [RUN...]` / `runo sync [RUN...]` / `runo log RUN [--err] [-n N] [-f]` | 状態表示 / Slurm から更新 / log 表示 |
|
|
164
|
-
| `runo list [PATH] [--all] [--since 30d] [--case] [--sweep] [--status] [--tag] [--scratch] [--archived] [--json]` | run
|
|
164
|
+
| `runo status [RUN...] [--brief]` / `runo sync [RUN...]` / `runo log RUN [--err] [-n N] [-f]` | 状態表示 / Slurm から更新 / log 表示 |
|
|
165
|
+
| `runo list [PATH] [--all] [--since 30d] [--case] [--sweep] [--status] [--tag] [--scratch] [--archived] [--brief] [--json]` | run 一覧。`--brief` は `params`、`why`、note を省く(表では note / why 列) |
|
|
165
166
|
| `runo note RUN [TEXT]` / `runo pin RUN [--off] [--reason]` | ノート追記・表示 / pin |
|
|
166
167
|
| `runo summarize RUN... [--force]` | adapter の要約を `analysis/summary.json` に書く |
|
|
167
168
|
| `runo mv RUN... [--dest DIR] [--label L] [--why TEXT]` | `runs/` 配下で改名・移動。id、入力、sweep、ノートは保つ。submitted / running と archived は不可。全対象を検査してから移し、1 件でも不可なら何も動かさない |
|
|
@@ -173,7 +174,11 @@ run id は削除後も再利用しません。`--dest` に既存 run の中は
|
|
|
173
174
|
`list` は既定で active、created、直近 `list_since_days` 日、pinned の run を表示し、
|
|
174
175
|
scratch と archived は表示しません。
|
|
175
176
|
|
|
176
|
-
`
|
|
177
|
+
`archive DIR` が group 配下の全 run を移すときは、group の `_analysis/` も同じ相対 path で
|
|
178
|
+
移動します。run が残る group の解析は残し、移動先が存在すれば全 run の移動前に拒否します。
|
|
179
|
+
`archive RUN...` / `--older-than` と `restore RUN` は group の解析を移動しません。
|
|
180
|
+
|
|
181
|
+
`tidy` の候補は次の 6 種類です。
|
|
177
182
|
|
|
178
183
|
| kind | 条件 | 動作 |
|
|
179
184
|
|---|---|---|
|
|
@@ -182,9 +187,17 @@ scratch と archived は表示しません。
|
|
|
182
187
|
| `old-completed` | `tidy_archive_days`(既定 90)日より古い completed | archive |
|
|
183
188
|
| `orphan-job` | Slurm が知らない submitted / running | sync |
|
|
184
189
|
| `unused-build` | 非 archived run が参照しない `.runops/build/*` | delete |
|
|
190
|
+
| `analysis-logs` | `tidy_failed_days` より古い解析 log。各 log directory・job 名の最新組は保持 | log のみ delete |
|
|
185
191
|
|
|
186
192
|
日数は `runops.toml` の `[defaults]` で変えられます。`--older-than 14d` のように指定すると、
|
|
187
193
|
その回だけ両方の日数をその値で置き換えます。pinned の run は `tidy` と `delete` の対象になりません。
|
|
188
194
|
`--purge-work` は adapter を読み込めないと何も消さずにエラーにします。
|
|
189
195
|
|
|
196
|
+
`analysis-logs` は project の `analysis/`、group の `_analysis/`、run の `analysis/` 配下の
|
|
197
|
+
`logs/*.<jobid>.out/err`(topic の下も含む)に限定します。組の新しい方の更新時刻で年齢を判定し、
|
|
198
|
+
最新組を残します。同時刻なら job id が大きい組を最新とします。片方だけの log も同じ扱いです。
|
|
199
|
+
archived / pinned / submitted / running run の解析と symlink は対象外で、適用直前にも条件を
|
|
200
|
+
確認します。`--json` の解析 log 候補は `files`(削除する project 相対 path)と `cutoff`
|
|
201
|
+
(ISO 日時)も持ちます。確認後に条件が変われば削除せず、再度 tidy を実行するよう案内します。
|
|
202
|
+
|
|
190
203
|
exit code は 0 が成功、1 が実行時エラー(sbatch 失敗など)、2 が使い方や設定のエラーです。
|
|
@@ -257,12 +257,24 @@ def context(as_json: bool = typer.Option(False, "--json")) -> None:
|
|
|
257
257
|
f"runs: {counts or 'none'}; active: {data['active_runs']}; "
|
|
258
258
|
f"expired scratch: {data['expired_scratch']}"
|
|
259
259
|
)
|
|
260
|
+
if data["active"]:
|
|
261
|
+
from runops.ops.progress import format_progress
|
|
262
|
+
|
|
263
|
+
out.print("active:")
|
|
264
|
+
for run in data["active"]:
|
|
265
|
+
out.print(
|
|
266
|
+
f" {run['id']} {run['status']:9} {run['case']} {run['label']} "
|
|
267
|
+
f"{format_progress(run['progress'])}"
|
|
268
|
+
)
|
|
269
|
+
out.print("recent:")
|
|
260
270
|
for run in data["recent_runs"]:
|
|
261
271
|
out.print(
|
|
262
272
|
f" {run['id']} {run['status']:9} {run['case']} {run['label']} {run['why'][:60]}"
|
|
263
273
|
)
|
|
264
274
|
if data["notes_files"]:
|
|
265
275
|
out.print("notes/: " + ", ".join(data["notes_files"]))
|
|
276
|
+
for group, topics in data["group_analysis"].items():
|
|
277
|
+
out.print(f"{group}/_analysis/: {', '.join(topics)}", markup=False)
|
|
266
278
|
if data["log_tail"]:
|
|
267
279
|
out.print("--- LOG.md (tail) ---")
|
|
268
280
|
out.print(data["log_tail"], markup=False)
|
|
@@ -590,23 +602,14 @@ def retry(
|
|
|
590
602
|
_submit_each(project, [m])
|
|
591
603
|
|
|
592
604
|
|
|
593
|
-
def _status_table(project: Project, manifests: list[Manifest]) -> Table:
|
|
605
|
+
def _status_table(project: Project, manifests: list[Manifest], *, brief: bool = False) -> Table:
|
|
594
606
|
from runops.ops.listing import relative_age
|
|
595
607
|
from runops.ops.progress import format_progress
|
|
596
608
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
"
|
|
600
|
-
|
|
601
|
-
"case",
|
|
602
|
-
"sweep",
|
|
603
|
-
"created",
|
|
604
|
-
"elapsed",
|
|
605
|
-
"progress",
|
|
606
|
-
"note",
|
|
607
|
-
"why",
|
|
608
|
-
box=None,
|
|
609
|
-
)
|
|
609
|
+
columns = ["id", "status", "label", "case", "sweep", "created", "elapsed", "progress"]
|
|
610
|
+
if not brief:
|
|
611
|
+
columns += ["note", "why"]
|
|
612
|
+
table = Table(*columns, box=None)
|
|
610
613
|
for m in manifests:
|
|
611
614
|
s = m.to_summary(project.root)
|
|
612
615
|
color = {
|
|
@@ -628,7 +631,7 @@ def _status_table(project: Project, manifests: list[Manifest]) -> Table:
|
|
|
628
631
|
status += " [dim](pinned)[/]"
|
|
629
632
|
if s["superseded_by"]:
|
|
630
633
|
status += f" [dim](-> {', '.join(s['superseded_by'])})[/]"
|
|
631
|
-
|
|
634
|
+
row = [
|
|
632
635
|
s["id"],
|
|
633
636
|
status,
|
|
634
637
|
s["label"],
|
|
@@ -637,15 +640,19 @@ def _status_table(project: Project, manifests: list[Manifest]) -> Table:
|
|
|
637
640
|
relative_age(s["created_at"]),
|
|
638
641
|
elapsed,
|
|
639
642
|
format_progress(s["progress"]),
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
+
]
|
|
644
|
+
if not brief:
|
|
645
|
+
row += [s["last_note"][:60], s["why"][:60]]
|
|
646
|
+
table.add_row(*row)
|
|
643
647
|
return table
|
|
644
648
|
|
|
645
649
|
|
|
646
650
|
@app.command()
|
|
647
651
|
def status(
|
|
648
652
|
runs: Optional[list[str]] = typer.Argument(None),
|
|
653
|
+
brief: bool = typer.Option(
|
|
654
|
+
False, "--brief", help="Leave out params, why, notes and the note/why columns."
|
|
655
|
+
),
|
|
649
656
|
as_json: bool = typer.Option(False, "--json"),
|
|
650
657
|
) -> None:
|
|
651
658
|
"""Show manifest state (no Slurm query). Without RUN: active runs."""
|
|
@@ -660,18 +667,19 @@ def status(
|
|
|
660
667
|
if as_json:
|
|
661
668
|
data = []
|
|
662
669
|
for m in targets:
|
|
663
|
-
s = m.to_summary(project.root)
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
670
|
+
s = m.to_summary(project.root, brief=brief)
|
|
671
|
+
if not brief:
|
|
672
|
+
s.update(
|
|
673
|
+
{
|
|
674
|
+
"params": m.params,
|
|
675
|
+
"job": {k: v for k, v in m.job.items() if k != "attempts"},
|
|
676
|
+
"notes": m.notes,
|
|
677
|
+
}
|
|
678
|
+
)
|
|
671
679
|
data.append(s)
|
|
672
680
|
_print_json(data)
|
|
673
681
|
return
|
|
674
|
-
out.print(_status_table(project, targets))
|
|
682
|
+
out.print(_status_table(project, targets, brief=brief))
|
|
675
683
|
|
|
676
684
|
|
|
677
685
|
@app.command("sync")
|
|
@@ -728,6 +736,9 @@ def list_cmd(
|
|
|
728
736
|
tags: Optional[list[str]] = typer.Option(None, "--tag"),
|
|
729
737
|
scratch: bool = typer.Option(False, "--scratch", help="Also show scratch runs."),
|
|
730
738
|
archived: bool = typer.Option(False, "--archived", help="Also show archived runs."),
|
|
739
|
+
brief: bool = typer.Option(
|
|
740
|
+
False, "--brief", help="Leave out params, why and notes (small JSON, short table)."
|
|
741
|
+
),
|
|
731
742
|
as_json: bool = typer.Option(False, "--json"),
|
|
732
743
|
) -> None:
|
|
733
744
|
"""List active and recent runs."""
|
|
@@ -750,12 +761,12 @@ def list_cmd(
|
|
|
750
761
|
)
|
|
751
762
|
runs = select_runs(project, flt)
|
|
752
763
|
if as_json:
|
|
753
|
-
_print_json([m.to_summary(project.root) for m in runs])
|
|
764
|
+
_print_json([m.to_summary(project.root, brief=brief) for m in runs])
|
|
754
765
|
return
|
|
755
766
|
if not runs:
|
|
756
767
|
out.print("no runs (try --all, --scratch, --archived)")
|
|
757
768
|
return
|
|
758
|
-
out.print(_status_table(project, runs))
|
|
769
|
+
out.print(_status_table(project, runs, brief=brief))
|
|
759
770
|
|
|
760
771
|
|
|
761
772
|
@app.command()
|
|
@@ -869,12 +880,22 @@ def archive(
|
|
|
869
880
|
if m.id in plan.superseded_by:
|
|
870
881
|
line += f" -> {', '.join(plan.superseded_by[m.id])}"
|
|
871
882
|
out.print(line)
|
|
883
|
+
for directory in plan.analysis_dirs:
|
|
884
|
+
dest = project.runs_dir / "_archive" / directory.relative_to(project.runs_dir)
|
|
885
|
+
out.print(f" analysis {project.rel(directory)} -> {project.rel(dest)}", markup=False)
|
|
872
886
|
_confirm(f"Archive {len(plan.targets)} runs?", yes)
|
|
873
887
|
archived = archive_runs(
|
|
874
|
-
project,
|
|
888
|
+
project,
|
|
889
|
+
plan.targets,
|
|
890
|
+
superseded_by=plan.superseded_by,
|
|
891
|
+
why=why,
|
|
892
|
+
by=_actor(),
|
|
893
|
+
analysis_dirs=plan.analysis_dirs,
|
|
875
894
|
)
|
|
876
895
|
for run_id, dst in archived:
|
|
877
896
|
out.print(f"archived {run_id} -> {project.rel(dst)}")
|
|
897
|
+
for directory in plan.analysis_dirs:
|
|
898
|
+
out.print(f"archived analysis {project.rel(directory)}", markup=False)
|
|
878
899
|
|
|
879
900
|
|
|
880
901
|
@app.command("mv")
|