# Snapshot tool — how it works, and how to run it The snapshot tool makes a **timestamped, detached copy of the model**, opens a Revit onto that copy on its own (nobody in front of it), runs a batch inside it, and closes — so the engineer's own model and session are never tied up. It is two halves: 1. **`SnapshotClose` pushbutton** (Tools panel, runs *inside* the live Revit). Its one irreplaceable job is **Phase A: hand over the model's IDENTITY.** Only the open document can cheaply report a cloud model's **region + GUIDs**, and without those nothing else can find the model again. Phase A also indexes the model as it stands (this is where the reinforce feature registry is refreshed) and journals what it did. It then writes a **request file** (the cached identity) and **spawns the detached host cycle** — it does *not* make the copy itself. 2. **`tools/snapshot_cycle.py`** (plain host CPython, detached — Claude can start it, no Revit needs to be open in front of anyone). Five steps: `DETACH → close-sandbox → open-sandbox → run batch → CLOSE`, each journalled. ## Why a copy is made by SaveAs, not "Detach from Central" A **cloud** model cannot be opened detached: any `DetachFromCentralOption` on a cloud `ModelPath` raises *"Detach option is not valid for cloud model,"* Autodesk says **SaveAs is the way**, and the UI greys the checkbox out. So the cycle's "detach" is a **SaveAs to a timestamped copy** under `snapshot.detached_dir`. ## The one rule that makes it usable: identity is captured once, from a live press A cloud model is **only identifiable from a session that has it open** — the region and GUIDs live in the open document. So: - **You must press `SnapshotClose` once from a live session that has the model open.** That press captures the cloud GUIDs and caches them (the request file). - **After that, the cycle can run with NO live session** — it reopens the model from the cached GUIDs. This is the path to **auto-running snapshots** with nobody in front of Revit: identity cached once → every later cycle is headless. If the identity was never cached (e.g. the press was interrupted), the cycle **cannot start** and says so — a cloud model with only a display path and no GUIDs can't be located. Fix: open the model and press `SnapshotClose` once more. ## Running the cycle by hand (after the identity is cached) ``` python tools/snapshot_cycle.py \ --fresh-detach \ # write a new timestamped copy first --job "" \ --request \ # OR --source , OR # snapshot.source_cloud in job knowledge --revit 2024 \ # PIN the year — the machine has several Revits; # omitting this is what silently no-fired before --revit-exe "C:/Program Files/Autodesk/Revit 2024/Revit.exe" \ --pyrevit "C:/Users//AppData/Roaming/pyRevit-Master/bin/pyrevit.exe" \ --dry-run # print the whole plan and do NOTHING — always dry-run first ``` Drop `--dry-run` to actually run. Useful flags: `--run ""` (the batch, default `snapshot.batch`), `--keep-open`, `--wait-minutes`, `--use ` (skip the detach and cycle onto an existing copy). ### Job-knowledge keys the cycle reads (`WILLTOOLS_JOBS//knowledge.yaml`) ``` snapshot: detached_dir: # REQUIRED, or --detached-dir source_cloud: {region: ..., project_guid: ..., model_guid: ...} # optional: lets the # cycle run with no live press ever, once you have the GUIDs ``` ## Journal — every run is recorded, silence is never success `/snapshots.jsonl` gets a line on **every** exit path (this was a real bug once: a day the cycle never fired looked exactly like a day it worked, so a missing run is now reported in capitals at the top of the report). Phase A also journals `phase-a-snapshot` (piece count, timing, provenance) and `phase-a-update-stats` (the reinforce feature-ID diff). ## Known failure modes - **`snapshot.detached_dir is not set`** → set it in job knowledge, or `--detached-dir`. - **"a fresh detach needs to know WHICH model to copy"** → identity not cached; press `SnapshotClose` once from the live model (see the identity rule above). - **Silent no-fire in ~16 s** → historically a missing `--revit=` with several Revit versions installed; **always pin `--revit`.** The cycle now resolves the year from the exe and journals on every exit, so this is loud now. ## Toward fully automatic Once `snapshot.source_cloud` (the GUIDs) is stored in the job knowledge — captured once from a live press — the cycle needs no Revit open in front of anyone and no request file, so it can be scheduled/auto-run headlessly. That is the intended end state.