# muse shelf read — UX fixes and files list bug ## Background `muse shelf read` has two problems discovered during normal development use: 1. **Bug**: `files_count` and `files` are semantically inconsistent. `files_count` counts files that *differ from HEAD* (the actual change set), but `files` dumps the entire snapshot manifest — every tracked file in the repo. On a large repo this means `files_count: 6` with a 1000+ entry `files` list, which is actively misleading. 2. **UX**: The JSON schema in the `--help` output for all shelf subcommands is a single dense line. It is hard to read at a glance — you have to actively parse it rather than letting your eyes scan line-by-line. 3. **Docs gap**: It is not documented that `muse shelf` (bare, no subcommand) is identical to `muse shelf save`, or that custom names are supported (`muse shelf save my-auth-refactor`). ## Goal - `files` in `muse shelf read --json` contains only the files that differ from HEAD — the same set that `files_count` counts. - The human-readable `muse shelf read` output shows only changed files. - JSON schema blocks in all shelf `--help` descriptions break each key onto its own line. - `muse shelf --help` and `muse shelf save --help` document the bare-command alias and custom name support. ## Phases ### Phase 1 — Fix `files` list bug **The invariant that must hold after this phase:** `len(output["files"]) + len(output["deleted"]) == output["files_count"]` - [x] `SF_01` — `run_read`: compute `changed_files` as paths where `entry["snapshot"][p] != head_manifest.get(p)` (covers new files and modifications) - [x] `SF_02` — `run_read` JSON: emit `files=changed_files` instead of all snapshot keys - [x] `SF_03` — `run_read` human output: iterate `changed_files` instead of all snapshot keys - [x] `SF_04` — Test: `files_count == len(files) + len(deleted)` invariant holds when HEAD has a mix of changed, unchanged, and new files - [x] `SF_05` — Test: `files` list is empty when shelf snapshot matches HEAD exactly ### Phase 2 — Pretty-print help JSON schemas - [x] `SF_06` — `muse shelf save --help`: break JSON schema across lines (one key per line) - [x] `SF_07` — `muse shelf read --help`: same - [x] `SF_08` — `muse shelf list --help`: same - [x] `SF_09` — `muse shelf apply --help`: same - [x] `SF_10` — `muse shelf pop --help`: same - [x] `SF_11` — `muse shelf drop --help`: same - [x] `SF_12` — `muse shelf diff --help`: same ### Phase 3 — Document bare `muse shelf` and custom names - [x] `SF_13` — `muse shelf --help` (top-level): note that `muse shelf` with no subcommand is equivalent to `muse shelf save` - [x] `SF_14` — `muse shelf save --help`: add example showing custom name (`muse shelf save my-auth-refactor -m "intent text"`) - [x] `SF_15` — `muse shelf save --help`: clarify auto-name format (`branch/NNN`) and that custom names are looked up by exact string or integer index ## Acceptance criteria - `muse shelf read 0 --json | jq '.files | length'` returns 6 (not 1000+) on the test shelf entry - `muse shelf read --help` JSON schema block has one key per line - `muse shelf --help` mentions the bare-command alias - All SF_0x tests pass ## Out of scope - `created_by` enrichment (read username from `~/.muse/identity.toml`) — tracked separately; requires identity config integration - Shelf entry expiry and GC — separate concern