Skip to content

Run Cherries Experiments

Status and scope

This is a historical target design, not the installed skill. The runtime now implements local CAS sealing, active-run helpers, archive/restore, metadata merge, labels/reviews, leases, lightweight analysis, rerun, payload-free metadata checkpoints, and single-machine maintenance. Follow the maintained installed-skill source at skills/run-cherries-experiments/SKILL.md and the record guide for actual commands and limits.

The remaining sections describe intended extensions. Treat automatic environment reconstruction, remote checkpoint compaction, remote attempt transfer, and destructive fleet cleanup as unavailable unless the implementation and maintained skill say otherwise. The separate experiment repository still owns authored scripts, documents, LFS fixtures, and Apple/Melon gitlinks; it never owns generated run payloads.

Repository and storage boundary

Treat these as distinct stores:

experiment-repo/                 # Git superproject
  libs/apple/                    # pinned Git submodule
  libs/melon/                    # pinned Git submodule
  exp/YYYY/mm/dd/study/
    src/  configs/  docs/  fixtures/  analysis/
<configured-storage-root>/       # outside the Git worktree
  objects/sha256/ab/<digest>      # immutable canonical blob
  records/<run-id>/               # record.json, manifest.json, RUN.md
  work/<run-id>/                  # writable independent/reflink copies
  runs/<run-id>/                  # optional ordinary view, never canonical
  metadata/events/<machine-id>/   # durable local updates
  metadata/checkpoints/           # downloaded versioned metadata
  cache/catalog.sqlite            # disposable query projection
  index/

Git LFS is only for deliberately curated fixtures and selected reviewable assets. Generated inputs, logs, checkpoints, and numerical outputs belong in Cherries CAS storage. Never use broad LFS patterns that turn every generated mesh or array into a permanent Git object. Remote storage uses the same objects, records, and metadata layout. For active library development, the experiment project may use editable path dependencies to its submodules. This makes current changes visible and makes capture at active main mandatory. cherries init --storage PATH is the planned one-time collection and local volume registration command. Do not invent it when the installed CLI lacks it.

Sealed daily experiment

python exp/2026/10/05/mouthopen/src/10-run.py --steps 200
uv run python exp/2026/10/05/mouthopen/src/10-run.py --steps 200

Keep the usual bottom-of-script call; normal arguments remain unchanged:

if __name__ == "__main__":
    cherries.main(main)

main() runs once in this process. It allocates work/<id> on the configured data volume, captures the entry script, supplied config, runtime evidence, each relevant repository/submodule HEAD plus combined binary diff, and selected untracked code copied separately. Work never writable-hardlinks into CAS. The commit bases must remain obtainable. There is no default bootstrap, relaunch, sandbox, daemon, or complete environment-artifact capture. This is provenance observed at the main boundary, not proof of already imported module state: record source stability and never claim replay_verified. Keep imports with data reads/writes, GPU or solver setup, hidden random state, and live config/input parsing inside main. Asset helpers are valid only in active main. Config defaults are raw paths or strings; never call them in class definitions:

class Config(cherries.BaseConfig):
    mesh: str = "sha256:<full-digest>"
def main(cfg: Config) -> None:
    mesh = cherries.input(cfg.mesh, name="mesh.vtu")
    output = cherries.output("solution.npz")
    scratch = cherries.temp("solver")

input accepts a full sha256: digest, local path/source string, or run:<id>/path; it verifies and copies bytes to work/inputs. output returns work/outputs, log_output imports an external result there, and temp uses disposable work/scratch. File content SHA-256 is asset_id, canonically stored at objects/sha256/<2hex>/<digest>; manifests/catalog index run, relative path, digest, and local-or-remote locations. For an unqualified identical asset, choose a complete local producer then remote, verify it, record chosen run/path/digests, and register the parent before reading. source_run=ID restricts provenance. Unknown hashes fail visibly; log/import a local path in a run first. A bundle ID is sha256-tree over every canonical companion digest; plain file hashes do not promise a bundle. Exact equal bytes deduplicate; no near-duplicate, block-deduplication, or compression promise applies. On success, import retained work payloads to CAS, stage, fsync, and rename complete local record metadata, append its sealed event, then reclaim disposable work. Missing outputs or storage failure yield nonzero incomplete and retain the stage. Execution failures retain a small receipt and discard payload only for a stopped, unpinned, never-published, unsealed local leaf with no dependent or hold. Do not automatically create Git commits. An authored experiment or library commit and outer gitlink update may be made intentionally after inspecting its scope; it is a convenient reference separate from immutable captured source.

Lightweight follow-up analysis

Use the planned commands for work that interprets existing records without claiming strict replay:

cherries analysis new FOLDER --source ID [--source ID] --name NAME
cherries analysis save FOLDER --output out/figure.png --output out/view.pvsm [--used-in weekly/2026-10-05]
cherries analysis close FOLDER

analysis new creates an editable study workspace with selected source IDs and materialized references, then registers a workspace hold on those sources. Write visualization/comparison scripts and findings in that folder, including RUN.md; use the current development environment, ParaView, or another tool. For ParaView, obtain complete declared artifact bundles and companions through cherries path or a full restore, never a guessed single file. Record the PVSM/settings and actual displayed artifact references when available. analysis save captures scripts, findings, selected output bytes/references, and declared source runs as a lightweight dependent record. It does not claim replayable solver execution, require a clean checkout, or require stamping casual media. analysis close ends the editable workspace without changing already saved records and releases its workspace hold. Saved analysis edges remain and protect every source record. Declare promoted outputs in [save].outputs in analysis.toml, or repeat analysis save --output PATH. Missing declared outputs fail save. Use the same workflow for weekly meeting reuse: create a meeting analysis with every discussed run as --source, save its exact references, and optionally record --used-in weekly/2026-10-05. The saved meeting analysis is a dependent record and protects its sources.

Archive, restore, and browse

cherries archive ID [ID ...] [--remote main] [--evict]
cherries restore ID
cherries browse --remote --quality unreviewed --json
cherries browse --remote --label LABEL --json
cherries browse --remote --used-in weekly/2026-10-05 --json
cherries browse --asset sha256:<full-digest> --json
cherries show ID --json
cherries read ID RUN.md
cherries path ID outputs/file

Rclone alone is neither atomic same-key publication nor SHA-256 proof. Require a documented atomic immutable backend or serialized foreground publisher coordination; never use a marker lock or stale-publisher takeover. Archive uploads and read-back-verifies the complete closure, then publishes complete manifests/control metadata and marker last. --evict needs remote verification and no local need by other resident records, active work, reader leases, or this machine's keep-local flag; importance protects logical retention, not eviction. It frees only eligible bytes because objects may be shared. Restore fetches and verifies missing objects into a named ordinary run view. path materializes the requested verified artifact plus declared companions, remaining partial. Associate paths with --workspace FOLDER, or release standalone leases with path --release LEASE. Browse/show use the newest digest-valid checkpoint plus later remote and local unsynchronized events in a disposable cache; no full mirror is required.

Before a complete marker, validate parent receipt IDs/digests, reject self/cycles, and resolve pending parents; unknown/conflicts remain pending and block destruction.

Post-hoc review and labels

Every successful experiment starts quality = unreviewed. Scientific validation, execution status, and subjective review are separate fields.

cherries review ID --quality good --note "Converged and useful for comparison"
cherries label add ID LABEL [LABEL ...]
cherries label remove ID LABEL [LABEL ...]

Reviews, notes, labels, and used-in associations are append-only metadata events synchronized remotely. Quality values are good, bad, inconclusive, or unreviewed; they never rewrite sealed records or CAS objects. bad does not auto-discard a successful record; labels alone create no retention policy.

Retention and deletion

cherries mark ID --important, --no-important, and --keep-local are planned mutable catalog operations. They do not rewrite immutable record content or CAS objects. No record with a dependent may be deleted. This holds for archived records, important records, copied records, old records, and failed descendants. Execution failures may have their payload automatically discarded only after the run is stopped, unpinned, confirmed a leaf, and recorded in deletion history. Retain validation failures until a user manually discards them. For shared multi-machine storage, rare deletion requires every registered machine paused and synchronized, with active readers/leases reconciled. An offline or unknown machine blocks deletion. Do not replace this with a best-effort local check. Logical discard retains tombstones and never removes a blob. prune marks/sweeps live records and pending/active holds. Local GC freezes every reference-creating path sharing that store; remote GC freezes all reference-creating operations in the collection namespace and requires all registered machines paused/synced. Offline blocks it.

Capability gaps and safe reporting

The current in-process main() and legacy local plugin do not provide this capture engine. Eager helpers may run before active main (for example in module-scope configuration) and cannot satisfy passive config defaults or managed asset semantics. The current default Git profile stages the whole containing repository before committing; it must not be used by this workflow. When a proposed command is absent, report the missing implementation and the smallest next design or implementation task. Do not manually approximate a sealed run with an unverified copy, invoke automatic Git commits, or delete records to make the requested workflow appear complete.