bathos 0.3.0__tar.gz → 0.3.1__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.
- {bathos-0.3.0 → bathos-0.3.1}/CHANGELOG.md +10 -0
- {bathos-0.3.0 → bathos-0.3.1}/CLAUDE.md +40 -25
- {bathos-0.3.0 → bathos-0.3.1}/PKG-INFO +42 -3
- {bathos-0.3.0 → bathos-0.3.1}/README.md +41 -2
- {bathos-0.3.0 → bathos-0.3.1}/agent_assets/docs/claude-code-integration.md +7 -3
- {bathos-0.3.0 → bathos-0.3.1}/agent_assets/using_bathos/SKILL.md +2 -2
- {bathos-0.3.0 → bathos-0.3.1}/pyproject.toml +1 -1
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/schema.py +3 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/sync.py +18 -3
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_cluster_workflow.py +1 -1
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_sync.py +47 -2
- {bathos-0.3.0 → bathos-0.3.1}/uv.lock +1 -1
- {bathos-0.3.0 → bathos-0.3.1}/.agent/workspace.id +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/.bth.toml +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/.coverage +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/.github/SECRETS.md +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/.github/workflows/publish.yml +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/.github/workflows/test.yml +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/.gitignore +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/.python-version +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/.readthedocs.yaml +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/LICENSE +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/agent_assets/docs/gemini-cli-integration.md +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/Makefile +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/source/api.rst +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/source/architecture.rst +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/source/conf.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/source/contributing.rst +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/source/index.rst +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/source/slurm-integration.rst +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/source/user-guide.rst +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/superpowers/plans/2026-05-15-bathos-v01-core.md +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/superpowers/plans/2026-05-19-agent-onboarding-export.md +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/superpowers/plans/2026-05-19-decorator.md +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/superpowers/plans/2026-05-19-historical-migration.md +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/superpowers/plans/2026-05-19-linter.md +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/superpowers/plans/2026-05-19-remote-management.md +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/superpowers/plans/2026-05-19-schema-versioning.md +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/superpowers/plans/2026-05-19-skill-and-export-mcp.md +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/superpowers/plans/2026-05-19-v02-feature-wiring.md +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/superpowers/plans/2026-05-20-agentic-integrity-design.md +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/superpowers/plans/2026-05-20-agentic-integrity-impl-plan.md +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/docs/superpowers/specs/2026-05-15-bathos-design.md +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/inventory.txt +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/main.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/praxia.toml +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/scripts/benchmarks/.bth.toml +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/scripts/experiments/.bth.toml +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/scripts/slurm/_bth_env.sh +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/__init__.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/archive.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/campaigns.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/catalog.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/checker.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/cli.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/compact.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/config.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/decorators.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/export.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/git.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/init.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/linter.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/mcp.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/migrate.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/new_experiment.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/prereg.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/query.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/remote.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/runner.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/sidecar.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/sprint_audit.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/templates/_bth_env.sh +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/src/bathos/validate.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/__init__.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/conftest.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_archive.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_campaigns.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_catalog.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_checker.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_cli.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_compact.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_config.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_decorators.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_export.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_git.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_init.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_integration.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_linter.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_mcp_integration.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_mcp_server.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_migrate.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_new_experiment.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_prereg.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_query.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_remote.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_runner.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_schema.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_sidecar.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_slurm_integration.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_sprint_audit.py +0 -0
- {bathos-0.3.0 → bathos-0.3.1}/tests/test_validate.py +0 -0
|
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **`bth sync` indefinite hang** — `sync_catalog()` now passes SSH options (`ConnectTimeout=10`, `BatchMode=yes`) to rsync so unreachable hosts fail in ≤10 s instead of blocking forever; adds `subprocess.run(timeout=120)` as a safety net; raises `RuntimeError` with actionable message on timeout; drops silent `--progress` flag (output was captured, not displayed)
|
|
13
|
+
|
|
14
|
+
- **Parquet timestamp timezone-aware fix** — Ensure timestamps loaded from Parquet are timezone-aware (UTC) to avoid comparisons between naive and aware datetimes in query functions; prevents TypeError and incorrect filtering.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
8
18
|
## [0.3.0] - 2026-05-20
|
|
9
19
|
|
|
10
20
|
### Added
|
|
@@ -10,15 +10,19 @@ bathos is a standalone experiment tracking CLI for a single researcher across 10
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
## Current Status (as of 2026-05-
|
|
13
|
+
## Current Status (as of 2026-05-20)
|
|
14
14
|
|
|
15
|
-
**v0.
|
|
15
|
+
**v0.3.0: complete and merged to main.** 254 tests passing.
|
|
16
16
|
|
|
17
17
|
- Full design spec: `.praxia/specs/bathos-design.md`
|
|
18
18
|
- v0.1 implementation plan: `.praxia/specs/bathos-v01-plan.md`
|
|
19
|
-
- Backlog: items #124–
|
|
19
|
+
- Backlog: items #124–142 in praxia DB (see below); #124–141 done
|
|
20
20
|
|
|
21
|
-
**
|
|
21
|
+
**Shipped in v0.2:** FastMCP server (#128), `@bth.experiment` decorator (#129), `bth check` (#130), SLURM `_bth_env.sh` (#131), `bth new-experiment` (#132), `uv tool` packaging (#133), `bth lint` (#134), `bth migrate` (#135), `bth sync` (#138), schema versioning v2 (#140), `bth archive` (#141), `bth remote` subcommands, `bth export`, `bth catalog-version`.
|
|
22
|
+
|
|
23
|
+
**Shipped in v0.3:** Agentic integrity gate (`--agent-mode`, `--no-sidecar`, `--derived-from`), lineage tracking (`bth lineage`), campaigns (`bth campaign` subcommands + MCP tools), sprint audit (`bth sprint-audit`), Tier-2 lint checks, schema v3 with campaign/lineage/integrity fields, `--campaign` flag on `bth run`.
|
|
24
|
+
|
|
25
|
+
**Remaining backlog:** #136 (bth-migrate praxia workflow), #137 (global instruction portability), #142 (results management design).
|
|
22
26
|
|
|
23
27
|
---
|
|
24
28
|
|
|
@@ -52,7 +56,7 @@ Cool schema is intentionally minimal (13 provenance fields). Warm adds `metadata
|
|
|
52
56
|
|
|
53
57
|
### Pre-Registration Schemas (per script directory)
|
|
54
58
|
|
|
55
|
-
Every script in `scripts/experiments/` and `scripts/benchmarks/`
|
|
59
|
+
Every script in `scripts/experiments/` and `scripts/benchmarks/` should have a companion sidecar **`<script-stem>.bth.toml`** declaring its hypothesis, expected outcomes, and result schema. In v0.2+, `bth run` enforces this by default; pass `--no-sidecar` to bypass.
|
|
56
60
|
|
|
57
61
|
**Sidecar format (experiments):**
|
|
58
62
|
```toml
|
|
@@ -118,7 +122,7 @@ fix = "str"
|
|
|
118
122
|
| Catalog storage | **DuckDB + Parquet** (not pyiceberg) | pyiceberg is for distributed data lakes; DuckDB+Parquet is simpler, no overhead |
|
|
119
123
|
| FastMCP | Mirror CLI tool-for-tool | `cli.py` and `mcp.py` both thin layers over same core modules |
|
|
120
124
|
|
|
121
|
-
### Source Layout
|
|
125
|
+
### Source Layout
|
|
122
126
|
|
|
123
127
|
```
|
|
124
128
|
src/bathos/
|
|
@@ -133,8 +137,20 @@ src/bathos/
|
|
|
133
137
|
init.py # bth init logic
|
|
134
138
|
runner.py # bth run subprocess wrapper
|
|
135
139
|
query.py # list_runs, get_run, find_runs, run_sql
|
|
136
|
-
checker.py # bth check — git-drift
|
|
137
|
-
sidecar.py # .bth.toml sidecar parse, content-hash, outcome eval
|
|
140
|
+
checker.py # bth check — git-drift freshness gate
|
|
141
|
+
sidecar.py # .bth.toml sidecar parse, content-hash, outcome eval
|
|
142
|
+
campaigns.py # bth campaign subcommands + Campaign dataclass
|
|
143
|
+
sprint_audit.py # bth sprint-audit cross-project audit
|
|
144
|
+
linter.py # bth lint — Tier-1 and Tier-2 checks
|
|
145
|
+
migrate.py # bth migrate — schema version upgrades
|
|
146
|
+
new_experiment.py # bth new-experiment scaffold
|
|
147
|
+
export.py # bth export — skill + MCP registration
|
|
148
|
+
validate.py # sidecar structural validation
|
|
149
|
+
remote.py # bth remote subcommands
|
|
150
|
+
sync.py # bth sync rsync wrapper
|
|
151
|
+
archive.py # bth archive warm→cold export
|
|
152
|
+
prereg.py # agentic integrity pre-registration gate
|
|
153
|
+
decorators.py # @bth.experiment provenance decorator
|
|
138
154
|
templates/
|
|
139
155
|
_bth_env.sh # SLURM env helper template
|
|
140
156
|
experiment.py # bth new-experiment script skeleton
|
|
@@ -150,25 +166,24 @@ src/bathos/
|
|
|
150
166
|
| 125 | `bth init` — dirs, .bth.toml, catalog bootstrap, SLURM config | P1 | 124 |
|
|
151
167
|
| 126 | `bth run` — CLI wrapper, provenance capture | P1 | 124 |
|
|
152
168
|
| 127 | `bth ls` / `show` / `find` / `sql` — query interface | P1 | 126 |
|
|
153
|
-
| 128 | FastMCP server — mirrors CLI tool-for-tool | P1 | 126, 127, 130 |
|
|
154
|
-
| 129 | `@bth.experiment` — provenance decorator for Typer scripts | P2 | 124 |
|
|
155
|
-
| 130 | `bth check` — freshness/validity vs git HEAD | P2 | 126 |
|
|
156
|
-
| 131 | SLURM `_bth_env.sh` integration | P2 | 125, 126 |
|
|
157
|
-
| 132 | `bth new-experiment` — Typer + sidecar scaffold | P2 | 125 |
|
|
158
|
-
| 133 | `uv tool` packaging + release | P3 | 126–130 |
|
|
159
|
-
| 134 | Script convention linter | P3 | — |
|
|
160
|
-
| 135 | `bth migrate` — Phase 1 mechanical (existing projects) | P2 | 125 |
|
|
161
|
-
| 136 | `bth-migrate` praxia workflow — agentic classification + git mv plan | P2 | 135 |
|
|
162
|
-
| 137 | Global instruction portability (separate design session needed) | P2 | — |
|
|
163
|
-
| 138 | `bth sync` — rsync cool-tier catalog to/from cluster remote | P2 | 125, v0.1 done |
|
|
164
|
-
| 139 | `bth compact` + warm-tier DuckDB (`bth sql` catalog queries) | P2 | v0.1 done |
|
|
165
|
-
| 140 | Schema versioning + extended provenance (hostname, slurm_job_id, metadata JSON, migrations) | P2 | 139 |
|
|
166
|
-
| 141 | `bth archive` — warm→cold partitioned Parquet export | P3 | 139, 140 |
|
|
167
|
-
| 142 | Results management — output convention, file-count utilities, direct management interface design | P2 | 139 |
|
|
169
|
+
| 128 | FastMCP server — mirrors CLI tool-for-tool | P1 ✓ done (v0.2) | 126, 127, 130 |
|
|
170
|
+
| 129 | `@bth.experiment` — provenance decorator for Typer scripts | P2 ✓ done (v0.2) | 124 |
|
|
171
|
+
| 130 | `bth check` — freshness/validity vs git HEAD | P2 ✓ done (v0.1/v0.2) | 126 |
|
|
172
|
+
| 131 | SLURM `_bth_env.sh` integration | P2 ✓ done (v0.1) | 125, 126 |
|
|
173
|
+
| 132 | `bth new-experiment` — Typer + sidecar scaffold | P2 ✓ done (v0.2) | 125 |
|
|
174
|
+
| 133 | `uv tool` packaging + release | P3 ✓ done (v0.2) | 126–130 |
|
|
175
|
+
| 134 | Script convention linter | P3 ✓ done (v0.2) | — |
|
|
176
|
+
| 135 | `bth migrate` — Phase 1 mechanical (existing projects) | P2 ✓ done (v0.2) | 125 |
|
|
177
|
+
| 136 | `bth-migrate` praxia workflow — agentic classification + git mv plan | P2 (not started) | 135 |
|
|
178
|
+
| 137 | Global instruction portability (separate design session needed) | P2 (not started) | — |
|
|
179
|
+
| 138 | `bth sync` — rsync cool-tier catalog to/from cluster remote | P2 ✓ done (v0.2) | 125, v0.1 done |
|
|
180
|
+
| 139 | `bth compact` + warm-tier DuckDB (`bth sql` catalog queries) | P2 ✓ done (v0.1) | v0.1 done |
|
|
181
|
+
| 140 | Schema versioning + extended provenance (hostname, slurm_job_id, metadata JSON, migrations) | P2 ✓ done (v0.2) | 139 |
|
|
182
|
+
| 141 | `bth archive` — warm→cold partitioned Parquet export | P3 ✓ done (v0.2) | 139, 140 |
|
|
183
|
+
| 142 | Results management — output convention, file-count utilities, direct management interface design | P2 (not started) | 139 |
|
|
168
184
|
|
|
169
185
|
**Not yet backlogged:**
|
|
170
|
-
-
|
|
171
|
-
- Outcome evaluation + `runs.outcome` column in warm DuckDB (add as P2, depends on 139)
|
|
186
|
+
- *(none — sidecar enforcement and outcome evaluation shipped in v0.2/v0.3)*
|
|
172
187
|
|
|
173
188
|
---
|
|
174
189
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bathos
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Local-first, zero-server experiment tracking for researchers
|
|
5
5
|
Project-URL: Homepage, https://github.com/mariellerossi/bathos
|
|
6
6
|
Project-URL: Documentation, https://bathos.readthedocs.io
|
|
@@ -66,13 +66,52 @@ bth run scripts/experiments/benchmark_tip3p.py -- --n-steps 1000 --out outputs/r
|
|
|
66
66
|
bth ls --since 7d
|
|
67
67
|
bth show <run-id>
|
|
68
68
|
|
|
69
|
-
# Check
|
|
70
|
-
bth check outputs
|
|
69
|
+
# Check catalog runs for git-drift freshness
|
|
70
|
+
bth check [--status <status>] [--check-outputs]
|
|
71
71
|
|
|
72
72
|
# Escape hatch: raw DuckDB SQL against the catalog
|
|
73
73
|
bth sql "SELECT project_slug, count(*) FROM runs GROUP BY 1"
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
### `bth run` flags
|
|
77
|
+
|
|
78
|
+
**v0.3+ flags:**
|
|
79
|
+
- `--agent-mode collaborative|autonomous` — declare whether this run is agent-driven
|
|
80
|
+
- `--derived-from <run-id>` — record parent run for lineage tracking
|
|
81
|
+
- `--campaign <campaign-id>` — associate this run with a campaign
|
|
82
|
+
- `--no-sidecar` — bypass sidecar enforcement (use for ad-hoc runs)
|
|
83
|
+
|
|
84
|
+
## CLI Reference
|
|
85
|
+
|
|
86
|
+
**Core commands:**
|
|
87
|
+
- `bth init` — initialize bathos in a project
|
|
88
|
+
- `bth run` — execute and track an experiment
|
|
89
|
+
- `bth ls` — list recent runs
|
|
90
|
+
- `bth show <run-id>` — display run details
|
|
91
|
+
- `bth find` — search runs by criteria
|
|
92
|
+
- `bth sql` — raw DuckDB query against catalog
|
|
93
|
+
- `bth check` — check catalog runs for git-drift freshness
|
|
94
|
+
- `bth lineage <run-id>` — show ancestor chain following parent_run_id links
|
|
95
|
+
- `bth sprint-audit [--hours N]` — audit recent runs across all registered projects
|
|
96
|
+
- `bth lint [--project-root PATH]` — check scripts/ for naming conventions and missing sidecars
|
|
97
|
+
- `bth new-experiment <name>` — scaffold a new experiment script and sidecar
|
|
98
|
+
- `bth migrate` — upgrade cool-tier Parquet fragments to current schema version
|
|
99
|
+
- `bth export` — export the using-bathos skill and register MCP server
|
|
100
|
+
|
|
101
|
+
**`bth remote`** — Manage sync remotes
|
|
102
|
+
- `bth remote add <name> <url>` — add an SSH remote for catalog sync
|
|
103
|
+
- `bth remote list` — list configured remotes
|
|
104
|
+
- `bth remote remove <name>` — remove a remote
|
|
105
|
+
- `bth remote test <name>` — test SSH connectivity to a remote
|
|
106
|
+
|
|
107
|
+
**`bth campaign`** — Manage experiment campaigns (v0.3+)
|
|
108
|
+
- `bth campaign create <id> --hypothesis <text>` — create a new campaign
|
|
109
|
+
- `bth campaign add <run-id> --campaign <id>` — associate a run with a campaign
|
|
110
|
+
- `bth campaign ls` — list campaigns
|
|
111
|
+
- `bth campaign show <id>` — show campaign details and runs
|
|
112
|
+
- `bth campaign review <id>` — statistical summary and anomaly detection
|
|
113
|
+
- `bth campaign conclude <id> --outcome <label>` — close campaign with outcome
|
|
114
|
+
|
|
76
115
|
## Script conventions
|
|
77
116
|
|
|
78
117
|
`bth init` scaffolds the following structure in your project:
|
|
@@ -30,13 +30,52 @@ bth run scripts/experiments/benchmark_tip3p.py -- --n-steps 1000 --out outputs/r
|
|
|
30
30
|
bth ls --since 7d
|
|
31
31
|
bth show <run-id>
|
|
32
32
|
|
|
33
|
-
# Check
|
|
34
|
-
bth check outputs
|
|
33
|
+
# Check catalog runs for git-drift freshness
|
|
34
|
+
bth check [--status <status>] [--check-outputs]
|
|
35
35
|
|
|
36
36
|
# Escape hatch: raw DuckDB SQL against the catalog
|
|
37
37
|
bth sql "SELECT project_slug, count(*) FROM runs GROUP BY 1"
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
### `bth run` flags
|
|
41
|
+
|
|
42
|
+
**v0.3+ flags:**
|
|
43
|
+
- `--agent-mode collaborative|autonomous` — declare whether this run is agent-driven
|
|
44
|
+
- `--derived-from <run-id>` — record parent run for lineage tracking
|
|
45
|
+
- `--campaign <campaign-id>` — associate this run with a campaign
|
|
46
|
+
- `--no-sidecar` — bypass sidecar enforcement (use for ad-hoc runs)
|
|
47
|
+
|
|
48
|
+
## CLI Reference
|
|
49
|
+
|
|
50
|
+
**Core commands:**
|
|
51
|
+
- `bth init` — initialize bathos in a project
|
|
52
|
+
- `bth run` — execute and track an experiment
|
|
53
|
+
- `bth ls` — list recent runs
|
|
54
|
+
- `bth show <run-id>` — display run details
|
|
55
|
+
- `bth find` — search runs by criteria
|
|
56
|
+
- `bth sql` — raw DuckDB query against catalog
|
|
57
|
+
- `bth check` — check catalog runs for git-drift freshness
|
|
58
|
+
- `bth lineage <run-id>` — show ancestor chain following parent_run_id links
|
|
59
|
+
- `bth sprint-audit [--hours N]` — audit recent runs across all registered projects
|
|
60
|
+
- `bth lint [--project-root PATH]` — check scripts/ for naming conventions and missing sidecars
|
|
61
|
+
- `bth new-experiment <name>` — scaffold a new experiment script and sidecar
|
|
62
|
+
- `bth migrate` — upgrade cool-tier Parquet fragments to current schema version
|
|
63
|
+
- `bth export` — export the using-bathos skill and register MCP server
|
|
64
|
+
|
|
65
|
+
**`bth remote`** — Manage sync remotes
|
|
66
|
+
- `bth remote add <name> <url>` — add an SSH remote for catalog sync
|
|
67
|
+
- `bth remote list` — list configured remotes
|
|
68
|
+
- `bth remote remove <name>` — remove a remote
|
|
69
|
+
- `bth remote test <name>` — test SSH connectivity to a remote
|
|
70
|
+
|
|
71
|
+
**`bth campaign`** — Manage experiment campaigns (v0.3+)
|
|
72
|
+
- `bth campaign create <id> --hypothesis <text>` — create a new campaign
|
|
73
|
+
- `bth campaign add <run-id> --campaign <id>` — associate a run with a campaign
|
|
74
|
+
- `bth campaign ls` — list campaigns
|
|
75
|
+
- `bth campaign show <id>` — show campaign details and runs
|
|
76
|
+
- `bth campaign review <id>` — statistical summary and anomaly detection
|
|
77
|
+
- `bth campaign conclude <id> --outcome <label>` — close campaign with outcome
|
|
78
|
+
|
|
40
79
|
## Script conventions
|
|
41
80
|
|
|
42
81
|
`bth init` scaffolds the following structure in your project:
|
|
@@ -38,14 +38,18 @@ The skill is loaded automatically at session start in Claude Code. In a new sess
|
|
|
38
38
|
|
|
39
39
|
| MCP Tool | CLI equivalent | Status |
|
|
40
40
|
|----------|---------------|--------|
|
|
41
|
-
| `
|
|
41
|
+
| `run` | `bth run` | ✅ Available |
|
|
42
42
|
| `list_runs` | `bth ls` | ✅ Available |
|
|
43
43
|
| `get_run` | `bth show <id>` | ✅ Available |
|
|
44
44
|
| `find_runs` | `bth find` | ✅ Available |
|
|
45
45
|
| `run_sql` | `bth sql` | ✅ Available |
|
|
46
46
|
| `compact_catalog` | `bth compact` | ✅ Available |
|
|
47
|
-
| `
|
|
48
|
-
| `
|
|
47
|
+
| `check` | `bth check` | ✅ Available |
|
|
48
|
+
| `archive` | `bth archive` | ✅ Available |
|
|
49
|
+
| `campaign_create` | `bth campaign create` | ✅ Available |
|
|
50
|
+
| `campaign_list` | `bth campaign ls` | ✅ Available |
|
|
51
|
+
| `campaign_review` | `bth campaign review` | ✅ Available |
|
|
52
|
+
| `campaign_conclude` | `bth campaign conclude` | ✅ Available |
|
|
49
53
|
|
|
50
54
|
## Update
|
|
51
55
|
|
|
@@ -13,7 +13,7 @@ description: "Use when working in any bathos-tracked research project — experi
|
|
|
13
13
|
|
|
14
14
|
**Scope:** Single researcher, 10+ projects, SLURM cluster integration.
|
|
15
15
|
|
|
16
|
-
**Status:** ✅ v0.
|
|
16
|
+
**Status:** ✅ v0.3.0 shipped — 254 tests passing. Full CLI + MCP server available, including campaigns and agentic integrity gates.
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
@@ -34,7 +34,7 @@ description: "Use when working in any bathos-tracked research project — experi
|
|
|
34
34
|
| Command | Arguments | Status | Notes |
|
|
35
35
|
|---------|-----------|--------|-------|
|
|
36
36
|
| bth init | --slug, --remote, --slurm-partition | ✅ | Project initialization |
|
|
37
|
-
| bth run | <script> [-- args], --tag, --out, --campaign, --agent-mode, --no-sidecar | ✅ | Execute + provenance capture |
|
|
37
|
+
| bth run | <script> [-- args], --tag, --out, --campaign, --agent-mode, --derived-from, --no-sidecar | ✅ | Execute + provenance capture; v0.3: `--agent-mode` (collaborative/autonomous), `--derived-from` (lineage), `--campaign` (campaign association), `--no-sidecar` (bypass enforcement) |
|
|
38
38
|
| bth ls | --since, --status, --limit, --project | ✅ | List recent runs + OUTCOME column |
|
|
39
39
|
| bth show | <run-id> | ✅ | Full run details + git state |
|
|
40
40
|
| bth find | --project, --since, --status, --tag, --output-file | ✅ | Flexible filtered query |
|
|
@@ -137,6 +137,9 @@ class Run:
|
|
|
137
137
|
ts = pydict["timestamp"][i]
|
|
138
138
|
if not isinstance(ts, datetime):
|
|
139
139
|
ts = ts.as_py()
|
|
140
|
+
# Ensure timestamp is timezone-aware in UTC for internal comparisons
|
|
141
|
+
if ts.tzinfo is None:
|
|
142
|
+
ts = ts.replace(tzinfo=UTC)
|
|
140
143
|
return cls(
|
|
141
144
|
id=pydict["id"][i],
|
|
142
145
|
project_slug=pydict["project_slug"][i],
|
|
@@ -7,6 +7,8 @@ from pathlib import Path
|
|
|
7
7
|
|
|
8
8
|
from bathos.config import ProjectConfig
|
|
9
9
|
|
|
10
|
+
_SYNC_TIMEOUT_S = 120 # rsync kill switch: fail if no completion within 2 minutes
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
@dataclass
|
|
12
14
|
class SyncResult:
|
|
@@ -53,17 +55,30 @@ def sync_catalog(
|
|
|
53
55
|
src = str(local_runs) + "/"
|
|
54
56
|
dst = remote_runs
|
|
55
57
|
|
|
56
|
-
#
|
|
58
|
+
# ConnectTimeout=10: fail in 10s if host is unreachable rather than hanging
|
|
59
|
+
# BatchMode=yes: never prompt for a password — fail immediately instead
|
|
60
|
+
ssh_opts = "ssh -o ConnectTimeout=10 -o BatchMode=yes"
|
|
61
|
+
|
|
57
62
|
cmd = [
|
|
58
63
|
"rsync",
|
|
59
|
-
"-
|
|
64
|
+
"-az",
|
|
65
|
+
"--partial",
|
|
66
|
+
f"-e{ssh_opts}",
|
|
60
67
|
"--ignore-existing",
|
|
61
68
|
src,
|
|
62
69
|
dst,
|
|
63
70
|
]
|
|
64
71
|
|
|
65
72
|
start_time = time.time()
|
|
66
|
-
|
|
73
|
+
try:
|
|
74
|
+
result = subprocess.run(
|
|
75
|
+
cmd, capture_output=True, text=True, timeout=_SYNC_TIMEOUT_S
|
|
76
|
+
)
|
|
77
|
+
except subprocess.TimeoutExpired:
|
|
78
|
+
raise RuntimeError(
|
|
79
|
+
f"bth sync timed out after {_SYNC_TIMEOUT_S}s — "
|
|
80
|
+
"check that the remote host is reachable and SSH keys are configured"
|
|
81
|
+
)
|
|
67
82
|
duration_s = time.time() - start_time
|
|
68
83
|
|
|
69
84
|
if result.returncode != 0:
|
|
@@ -177,7 +177,7 @@ remote_root = "~/projects/testproj"
|
|
|
177
177
|
|
|
178
178
|
# Verify rsync command structure
|
|
179
179
|
assert cmd[0] == "rsync"
|
|
180
|
-
assert "-
|
|
180
|
+
assert "-az" in cmd
|
|
181
181
|
assert "--ignore-existing" in cmd
|
|
182
182
|
# Should have source and destination with runs/ directories
|
|
183
183
|
assert any("runs/" in str(arg) for arg in cmd)
|
|
@@ -40,14 +40,59 @@ def test_sync_constructs_correct_rsync_command_push(tmp_path: Path):
|
|
|
40
40
|
|
|
41
41
|
# Should be rsync command
|
|
42
42
|
assert cmd[0] == "rsync"
|
|
43
|
-
# Should have -
|
|
44
|
-
assert "-
|
|
43
|
+
# Should have -az flags (no -P: progress is useless when output is captured)
|
|
44
|
+
assert "-az" in cmd
|
|
45
|
+
# Should pass SSH options for fast failure: ConnectTimeout + BatchMode
|
|
46
|
+
assert any("ConnectTimeout" in str(a) for a in cmd)
|
|
47
|
+
assert any("BatchMode=yes" in str(a) for a in cmd)
|
|
45
48
|
# Should have --ignore-existing flag
|
|
46
49
|
assert "--ignore-existing" in cmd
|
|
47
50
|
# Should reference runs directories
|
|
48
51
|
assert any("runs/" in str(arg) for arg in cmd)
|
|
49
52
|
|
|
50
53
|
|
|
54
|
+
def test_sync_passes_timeout_to_subprocess(tmp_path: Path):
|
|
55
|
+
"""sync_catalog passes a timeout to subprocess.run so it cannot hang forever."""
|
|
56
|
+
config = ProjectConfig(
|
|
57
|
+
slug="test",
|
|
58
|
+
root=Path("/home/user/test"),
|
|
59
|
+
remotes={"engaging": {"host": "engaging", "remote_root": "~/projects/test"}},
|
|
60
|
+
)
|
|
61
|
+
catalog_dir = tmp_path / "catalog"
|
|
62
|
+
catalog_dir.mkdir()
|
|
63
|
+
(catalog_dir / "runs").mkdir()
|
|
64
|
+
|
|
65
|
+
with patch("bathos.sync.subprocess.run") as mock_run:
|
|
66
|
+
mock_run.return_value.returncode = 0
|
|
67
|
+
mock_run.return_value.stdout = ""
|
|
68
|
+
|
|
69
|
+
sync_catalog("engaging", config, catalog_dir, pull=False)
|
|
70
|
+
|
|
71
|
+
call_kwargs = mock_run.call_args[1]
|
|
72
|
+
assert "timeout" in call_kwargs, "subprocess.run must have a timeout to prevent indefinite hangs"
|
|
73
|
+
assert call_kwargs["timeout"] > 0
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_sync_raises_on_timeout(tmp_path: Path):
|
|
77
|
+
"""sync_catalog raises RuntimeError with clear message when rsync times out."""
|
|
78
|
+
import subprocess as _subprocess
|
|
79
|
+
|
|
80
|
+
config = ProjectConfig(
|
|
81
|
+
slug="test",
|
|
82
|
+
root=Path("/home/user/test"),
|
|
83
|
+
remotes={"engaging": {"host": "engaging", "remote_root": "~/projects/test"}},
|
|
84
|
+
)
|
|
85
|
+
catalog_dir = tmp_path / "catalog"
|
|
86
|
+
catalog_dir.mkdir()
|
|
87
|
+
(catalog_dir / "runs").mkdir()
|
|
88
|
+
|
|
89
|
+
with patch("bathos.sync.subprocess.run") as mock_run:
|
|
90
|
+
mock_run.side_effect = _subprocess.TimeoutExpired(cmd=["rsync"], timeout=120)
|
|
91
|
+
|
|
92
|
+
with pytest.raises(RuntimeError, match="timed out"):
|
|
93
|
+
sync_catalog("engaging", config, catalog_dir, pull=False)
|
|
94
|
+
|
|
95
|
+
|
|
51
96
|
def test_sync_pull_reverses_direction(tmp_path: Path):
|
|
52
97
|
"""sync_catalog pulls from remote when pull=True."""
|
|
53
98
|
config = ProjectConfig(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{bathos-0.3.0 → bathos-0.3.1}/docs/superpowers/plans/2026-05-20-agentic-integrity-impl-plan.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|