Muse Utility Reference & Anti-Pattern Inventory
Every canonical ID, path, hash, and display operation has a utility function. Never inline these patterns. Use the function. This document is both a reference and a checkable inventory — every known violation is listed so they can be tracked to zero.
Utility Functions
muse.core._types
| Function | Signature | Purpose | Replaces |
|---|---|---|---|
blob_id |
(data: bytes) → str |
sha256: ID from raw bytes |
"sha256:" + hashlib.sha256(data).hexdigest() |
content_hash |
(obj: JsonValue) → str |
sha256: ID from JSON-serialisable object |
manual json.dumps + hashlib.sha256 |
hash_file |
(path: Path, *, chunk_size=65536) → str |
sha256: ID from file (streaming) |
blob_id(path.read_bytes()) for large files |
long_id |
(hex_digest: str, algo="sha256", *, strip=False) → str |
Add or strip algo: prefix (idempotent) |
f"sha256:{hex}" · "sha256:" + hex · .removeprefix("sha256:") |
short_id |
(full_id: str, algo="sha256", *, strip=False) → str |
Canonical 12-char abbreviated ID | full_id[:12] · full_id[7:19] · manual slicing |
split_id |
(object_id: str) → tuple[str, str] |
Parse (algo, hex) from prefixed or bare ID |
partition(":") inline · .removeprefix("sha256:") at storage boundary |
fake_id |
(seed: str) → str |
Deterministic sha256: ID for tests |
hashlib.sha256(seed.encode()).hexdigest() in tests |
now_utc_iso |
() → str |
Current UTC time as ISO 8601 | datetime.datetime.now(datetime.timezone.utc).isoformat() |
load_json_file |
(path: Path) → Any \| None |
Read + parse JSON file, None on error |
json.loads(path.read_text(...)) in try/except |
encode_sig |
(algorithm: str, raw: bytes) → str |
Encode signature bytes as algo:base64url |
manual base64.urlsafe_b64encode + f-string |
encode_pubkey |
(algorithm: str, raw: bytes) → str |
Encode public key bytes as algo:base64url |
same as above |
decode_sig |
(value: str) → tuple[str, bytes] |
Decode prefixed signature string | manual partition(":") + b64decode |
decode_pubkey |
(value: str) → tuple[str, bytes] |
Decode prefixed public key string | same as above |
sig_algo |
(value: str) → str |
Extract algorithm prefix from crypto value | value.partition(":")[0] inline |
split_sig |
(value: str) → tuple[str, str] |
Parse (algo, b64_str) from prefixed signature string |
sig.removeprefix("ed25519:") · manual partition(":") |
split_pubkey |
(value: str) → tuple[str, str] |
Parse (algo, b64_str) from prefixed public key string |
key.removeprefix("ed25519:") · manual partition(":") |
muse.core._types — Object store layout constants
| Constant | Value | Purpose | Replaces |
|---|---|---|---|
OBJECTS_DIR |
"objects" |
Objects subdirectory name inside .muse/ |
hardcoded "objects" string |
DEFAULT_ALGO |
"sha256" |
Default hash algorithm subdirectory | hardcoded "sha256" string in path construction |
Import these instead of hardcoding the strings. object_store.py imports them here — no other module should redefine them.
muse.core.object_store — Object path utilities
| Function | Purpose | Replaces |
|---|---|---|
object_path(root, object_id) |
.muse/objects/sha256/<shard>/<rest> |
root / ".muse" / "objects" / "sha256" / hex[:2] / hex[2:] |
objects_algo_dir(root) |
.muse/objects/sha256/ directory |
root / ".muse" / "objects" / "sha256" · root / ".muse" / "objects" / DEFAULT_ALGO |
object_path accepts a full sha256:<64hex> ID and handles shard-prefix length from config. Never construct these paths by hand.
muse.core.store — Path constructors
| Function | Purpose | Replaces |
|---|---|---|
commit_path(root, commit_id) |
.muse/commits/sha256/<hex>.msgpack |
_commits_dir(root) / f"{id.removeprefix('sha256:')}.msgpack" |
snapshot_path(root, snapshot_id) |
.muse/snapshots/sha256/<hex>.msgpack |
inline path construction |
tag_path(root, repo_id, tag_id) |
.muse/tags/sha256/<r-hex>/sha256/<t-hex>.msgpack |
inline construction |
release_path(root, repo_id, release_id) |
.muse/releases/sha256/<r-hex>/sha256/<re-hex>.msgpack |
inline construction |
muse.core.validation — Input guards
| Function | Purpose |
|---|---|
validate_object_id(s) |
Assert sha256:<64-hex>; raise ValueError |
sanitize_display(s) |
Strip control chars for terminal output |
sanitize_provenance(s) |
Strip unsafe chars from agent/model IDs |
contain_path(base, rel) |
Resolve and assert stays inside base |
assert_write_inside_repo(root, path) |
Raise if path escapes repo root |
ID Format Rules
| Entity | Format | Notes |
|---|---|---|
| Object, Commit, Snapshot, Tag, Release | sha256:<64-hex> |
Always prefixed |
| Repo genesis ID | sha256:<64-hex> |
content_hash({"created_at":…,"domain":…,"path":…}) |
| Signature | ed25519:<base64url> |
No padding |
| Public key | ed25519:<base64url> |
No padding |
| Coordination IDs (reservation, intent) | UUID string | Ephemeral advisory — legitimately UUID |
| Task queue task IDs | UUID string | Ephemeral — legitimately UUID |
| Test hub repo slugs | arbitrary string | External names — not Muse object IDs |
UUIDs are not used for any content-addressed system entity. uuid.uuid4() for
repo_id, commit_id, snapshot_id, object_id, tag_id, release_id is a bug.
The Storage-Boundary Rule
In-memory, content-addressed IDs are always prefixed (sha256:<64hex>). Always.
The prefix is stripped only at the storage boundary — when constructing a filesystem path that uses bare hex as a directory/filename component. It is added back only when reading an ID back from disk. Nowhere else.
in memory: sha256:abcdef... ← always full prefixed form
↓ write path
on disk: .muse/objects/sha256/ab/cdef... ← algo dir, then bare hex sharded
↓ read path
in memory: sha256:abcdef... ← reconstitute prefix immediately on read
Legitimate uses of split_id() / long_id(strip=True):
- Inside
object_path(),commit_path(),snapshot_path(),tag_path(),release_path()— path construction only - GC traversal that walks raw filesystem paths and needs to reconstruct IDs
- Prefix-scan globs where the filesystem requires bare hex
Not legitimate:
- Stripping prefix to pass an ID between in-memory functions
- Stripping to do string comparison (compare full prefixed IDs)
- Stripping to shorten for display (use
short_id()instead — it handles the prefix)
UUID truncation is exempt from short_id(). Coordination IDs (reservation_id,
intent_id), task queue IDs, hub proposal IDs, and other UUIDs are not content-addressed
entities. [:8] or [:12] on a UUID for a debug log is fine — do not apply short_id()
to UUIDs. short_id() is only for sha256:-prefixed IDs.
Anti-Pattern Inventory
Pattern 1 — Manual sha256: prefix construction
Fix: long_id(hex) · blob_id(data) · content_hash(obj)
| File | Notes | |
|---|---|---|
| ✅ | muse/core/gc.py |
Fixed — long_id() |
| ✅ | tests/test_implicit_edge_cache.py |
Fixed — blob_id() |
| ✅ | tests/test_guard_supercharge.py |
Fixed — fake_id() |
| ✅ | tests/test_symbol_log_supercharge.py |
Fixed — fake_id() |
| ✅ | tests/test_symbols_supercharge.py |
Fixed — fake_id() |
| ✅ | tests/test_algo_prefix_globs.py |
Fixed — fake_id() |
| ✅ | tests/test_verify_tag_supercharge.py |
Fixed — fake_id() |
| ✅ | tests/test_predict_supercharge.py |
Fixed — fake_id() |
| ✅ | tests/test_cmd_cherry_pick_hardening.py |
Fixed — fake_id() |
| ✅ | tests/test_cmd_cat_object.py |
Fixed — fake_id() |
| ✅ | tests/test_cmd_verify_object.py |
Fixed — fake_id() |
| ✅ | tests/test_merge_base_supercharge.py |
Fixed — fake_id() |
| ✅ | tests/test_cmd_merge_base.py |
Fixed — fake_id() |
| ✅ | tests/test_cmd_read_snapshot.py |
Fixed — fake_id() |
| ✅ | tests/test_read_snapshot_supercharge.py |
Fixed — fake_id() |
| ✅ | tests/test_cmd_read_commit.py |
Fixed — fake_id() |
| ✅ | tests/test_read_commit_supercharge.py |
Fixed — fake_id() |
| ✅ | tests/test_cmd_commit_tree.py |
Fixed — fake_id() |
| ✅ | tests/test_harmony_cli.py |
Fixed — fake_id() |
| ✅ | tests/test_harmony_phase1.py |
Fixed — fake_id() |
| — | tests/test_update_ref_supercharge.py:472 |
Assertion string, not construction — intentional |
| — | tests/test_verify_supercharge.py:400,401 |
Expected-value assertions for long_id — intentional |
| — | tests/test_core_types.py |
Unit tests for long_id itself — intentional |
| — | muse/core/snapshot.py docstring |
Example strings in module docstring — intentional |
All actionable Pattern 1 violations are resolved.
Pattern 2 — Manual prefix stripping outside the storage boundary
Rule: IDs in memory are always prefixed. Strip only inside path-construction functions.
Fix: split_id(x) → (algo, hex) · or long_id(x, strip=True) for bare hex.
Any removeprefix("sha256:") or [7:] outside of object_path()/commit_path()/snapshot_path()/tag_path()/release_path() or a GC filesystem walk is a violation.
Production code
| File | Notes | |
|---|---|---|
| ✅ | muse/core/gc.py |
Fixed — long_id(id_str, strip=True) |
| ✅ | muse/core/object_store.py |
Fixed — split_id(object_id) (×2) |
| ✅ | muse/core/store.py |
Fixed — long_id(safe_ref, strip=True) |
| ✅ | muse/cli/commands/read.py |
Fixed — long_id(ref, strip=True) |
| ✅ | muse/cli/commands/log.py |
Fixed — long_id(ref, strip=True) (×2) |
| ✅ | muse/cli/commands/rev_parse.py |
Fixed — long_id(ref, strip=True) |
| ✅ | muse/cli/commands/read_commit.py |
Fixed — long_id(commit_id, strip=True) |
| ✅ | muse/cli/commands/code_check.py |
Fixed — long_id(ref, strip=True) |
| ✅ | muse/cli/commands/snapshot_cmd.py |
Fixed — long_id(snapshot_id, strip=True) |
| ✅ | muse/cli/commands/snapshot_diff.py |
Fixed — long_id(prefix, strip=True) |
| ✅ | muse/cli/commands/name_rev.py |
Fixed — long_id(s, strip=True) |
Test code
| File | Notes | |
|---|---|---|
| ✅ | tests/test_apply_pack_oserror_integrity.py |
Fixed — commit_path() |
| ✅ | tests/test_cmd_code_add.py |
Fixed — split_id() / startswith assertion |
| ✅ | tests/test_directories_feature.py |
Fixed — split_id() |
| ✅ | tests/test_cmd_reset_hardening.py |
Fixed — split_id() / snapshot_path() |
| ✅ | tests/test_cmd_snapshot_hardening.py |
Fixed — split_id() |
| ✅ | tests/test_harmony_phase4.py |
Fixed — split_id() |
| ✅ | tests/test_integrity_I5_commit_integrity.py |
Fixed — long_id(strip=True) |
| ✅ | tests/test_algo_prefix_globs.py |
Fixed — long_id(strip=True) |
| ✅ | tests/test_ls_tree_supercharge.py |
Fixed — split_id() |
| ✅ | tests/test_cmd_ls_files.py |
Fixed — split_id(f["object_id"]) |
| ✅ | tests/test_cmd_revert_hardening.py |
Fixed — short_id(cid, strip=True) |
Note:
muse/core/snapshot.pylines 474–475 strip before hashing — the hash computation intentionally uses bare hex as input. Leave as-is.
Pattern 3 — Manual hashlib.sha256 for object IDs
Fix: blob_id(data) · content_hash(obj) · hash_file(path)
Only flagged where result is used as a stored/returned ID, not streaming verification.
| File | Notes | |
|---|---|---|
| ✅ | tests/test_implicit_edge_cache.py |
Already fixed — blob_id(raw) |
| ✅ | muse/plugins/code/manifest.py |
Fixed — blob_id(…) (×2); also storage-boundary fix with long_id(strip=True) |
| ✅ | muse/plugins/midi/manifest.py |
Fixed — blob_id(file_path.encode()) |
| ✅ | muse/plugins/midi/entity.py |
Fixed — split_id(blob_id(track_path.encode()))[1][:8] |
Pattern 4 — Manual short ID truncation
Fix: short_id(full_id) (returns sha256:abcdef123456) · short_id(full_id, strip=True) (returns abcdef123456)
Production code
Only applies to sha256:-prefixed content-addressed IDs. UUID-based IDs (reservation_id,
intent_id, task_id, proposal_id) are exempt — [:8] on a UUID is fine.
| File | Notes | |
|---|---|---|
| ✅ | muse/cli/commands/migrate.py |
Fixed — short_id(sha, strip=True) (×2) |
| ✅ | muse/plugins/midi/plugin.py |
Fixed — short_id(cid, strip=True) |
| ✅ | muse/cli/commands/tension.py |
Fixed — short_id(commit.commit_id, strip=True) |
| ✅ | muse/cli/commands/scale_detect.py |
Fixed — short_id(commit.commit_id, strip=True) |
| ✅ | muse/cli/commands/rhythm.py |
Fixed — short_id(commit.commit_id, strip=True) |
| ✅ | muse/cli/commands/velocity_profile.py |
Fixed — short_id(commit.commit_id, strip=True) |
| ✅ | muse/cli/commands/release.py |
Fixed — short_id(release_id, strip=True) (×2) |
muse/core/dag.py:594,muse/core/task_queue.py:578,660,1068,muse/core/coordination.py:362,568,797,944,muse/cli/commands/hub/proposals.py:600,642— UUID truncations, not violations.
Test code (representative — use short_id consistently)
| File | Notes | |
|---|---|---|
| ✅ | tests/test_cmd_gc.py |
Fixed — short_id(orphan_id, strip=True) |
| ✅ | tests/test_cmd_check.py |
Fixed — short_id(cids[-1], strip=True) |
| ✅ | tests/test_cmd_tag.py |
Fixed — short_id(commit_id) |
| ✅ | tests/test_harmony_cli.py |
Fixed — short_id(pid) (×4) |
| ✅ | tests/test_cmd_show.py |
Fixed — short_id(cid) |
| ✅ | tests/test_cmd_read_snapshot.py |
Fixed — short_id(sid) |
| ✅ | tests/test_cmd_read_commit.py |
Fixed — short_id(cid) |
| ✅ | tests/test_cmd_cherry_pick_hardening.py |
Fixed — short_id(cid) (×2) |
| ✅ | tests/test_cmd_revert_hardening.py |
Fixed — short_id(cid) (×2) |
| ✅ | tests/test_cmd_bisect_hardening.py |
Fixed — short_id(mid) (×3) |
| ✅ | tests/test_cmd_snapshot_hardening.py |
Fixed — short_id(snap_id) (×7) |
| ✅ | tests/test_cmd_branch.py |
Fixed — short_id(first_sha) (×2) |
| ✅ | tests/test_cmd_archive_hardening.py |
Fixed — short_id(commit_id) (×2) |
| — | tests/test_algo_prefix_globs.py |
bare_hex[:12] — bare hex variable, not prefixed, exempt |
| — | tests/test_cmd_reflog_hardening.py |
_SHA_B[:12] — bare hex constant, not prefixed, exempt |
Pattern 5 — Manual UTC timestamp
Fix: now_utc_iso()
| File | Notes | |
|---|---|---|
| ✅ | muse/core/bisect.py |
Fixed — now_utc_iso() |
| ✅ | tools/demo.py |
Fixed — now_utc_iso() (×3 including line 490) |
| ✅ | tests/test_directories_feature.py |
Fixed — now_utc_iso() (×3) |
| ✅ | tests/test_workdir_integrity.py |
Fixed — now_utc_iso() |
| ✅ | tests/test_cmd_coord_gc.py |
Fixed — now_utc_iso() (×2) |
| ✅ | tests/test_cmd_watch_coord.py |
Fixed — now_utc_iso() (×5) |
| ✅ | tests/test_release_analysis.py |
Fixed — now_utc_iso() |
| ✅ | tests/test_security_object_store_poisoning.py |
Fixed — now_utc_iso() (×2) |
Pattern 6 — Manual JSON file loading
Fix: load_json_file(path) — returns None on any error
Production code
| File | Notes | |
|---|---|---|
| ✅ | muse/cli/commands/status.py |
Fixed — load_json_file(cfg_path) |
| — | muse/plugins/code/stage.py |
Uses msgpack, not JSON file — not applicable |
| ✅ | tools/render_html.py |
Fixed — load_json_file(json_path) |
| ✅ | tools/demo.py |
Fixed — load_json_file(f) (×2) |
Note:
verify_tag.py:182andverify_commit.py:121use_json.loads(resp.read().decode())on HTTP response bodies — not file paths, leave as-is.
Test code (representative sample)
| File | Notes | |
|---|---|---|
| ✅ | tests/test_cli_workflow.py |
Fixed — load_json_file(...) |
| ✅ | tests/test_cmd_reserve.py |
Fixed — load_json_file(...) (×3) |
| ✅ | tests/test_cmd_sparse_checkout.py |
Fixed — load_json_file(...) (×6) |
Pattern 7 — uuid.uuid4() for content-addressed entity IDs
Fix: content_hash({…}) for genesis IDs · fake_id(seed) for deterministic test IDs
Legitimate UUIDs: coordination reservation_id/intent_id, task_queue task IDs, test hub slugs, CRDT tokens.
Everything below is a bug — repo_id, tag_id, release_id, commit_id must not be UUIDs.
| File | Notes | |
|---|---|---|
| ✅ | tests/test_cmd_gc.py |
Fixed — fake_id("repo") |
| ✅ | tests/test_rebase_missing_snapshot_guard.py |
Fixed — fake_id(...) |
| ✅ | tests/test_security_ast_dos.py |
Fixed — fake_id(...) |
| ✅ | tests/test_merge_data_integrity.py |
Fixed — fake_id(...) |
| ✅ | tests/test_merge_supercharge.py |
Fixed — fake_id(...) |
| ✅ | tests/test_cmd_merge_dry_run.py |
Fixed — fake_id(...) |
| ✅ | tests/test_cmd_check.py |
Fixed — fake_id(...) |
| ✅ | tests/test_cmd_shelf.py |
Fixed — fake_id(...) |
| ✅ | tests/test_workdir_integrity.py |
Fixed — fake_id(...) |
| ✅ | tests/test_gc_full.py |
Fixed — fake_id(...) |
| ✅ | tests/test_cmd_merge.py |
Fixed — fake_id(...) |
| ✅ | tests/test_cmd_tag.py |
Fixed — fake_id(...) (×5) |
| ✅ | tests/test_pull_missing_snapshot_guard.py |
Fixed — fake_id(...) |
| ✅ | tests/test_cmd_reset_revert.py |
Fixed — fake_id(...) |
| ✅ | tests/test_cmd_config.py |
Fixed — fake_id(...) |
| ✅ | tests/test_cmd_bisect.py |
Fixed — fake_id(...) |
| ✅ | tests/test_cmd_archive_hardening.py |
Fixed — fake_id(...) |
| ✅ | tests/test_gc_supercharge.py |
Fixed — fake_id(...) |
| ✅ | tests/test_cmd_bisect_hardening.py |
Fixed — fake_id(...) (×2) |
| ✅ | tests/test_cmd_gc_hardening.py |
Fixed — fake_id(...) |
| ✅ | tests/test_security_code_porcelain.py |
Fixed — fake_id(...) |
| ✅ | tests/test_cmd_reflog.py |
Fixed — fake_id(...) |
| ✅ | tests/test_cmd_plan_merge.py |
Fixed — fake_id(...) (×2) |
| ✅ | tests/test_cmd_release_hardening.py |
Fixed — fake_id(...); stale import uuid removed |
Pattern 8 — Manual fake_id equivalent in tests
Fix: fake_id(seed) — deterministic, prefixed, well-formed
| File | Notes | |
|---|---|---|
| ✅ | tests/test_security_agent_impersonation.py |
Fixed — fake_id(cid) |
| — | tests/test_msign_dual_sig.py |
Nonces, not IDs — legitimate, leave as-is |
| — | tests/test_core_msign.py |
Signing verification hashes — legitimate, leave as-is |
Pattern 9 — Manual object path construction
Fix: object_path(root, object_id) from muse.core.object_store
Never inline root / ".muse" / "objects" / "sha256" / hex[:2] / hex[2:].
| File | Notes | |
|---|---|---|
| ✅ | tests/test_cmd_invariants.py |
Already using object_path() |
| ✅ | tests/test_cmd_gc_hardening.py |
Fixed — object_path(root, "sha256:" + sha) (×2) |
| ✅ | tests/test_gc_supercharge.py |
Already using object_path() |
| ✅ | tests/test_porcelain_security.py |
Already using object_path() |
| ✅ | tests/test_core_gc.py |
Already using object_path() |
| ✅ | tests/test_cmd_code_add.py |
Already using object_path() |
| ✅ | tests/test_code_manifest.py |
Already using object_path() |
| ✅ | tests/test_merge_data_integrity.py |
Already using object_path() |
Pattern 10 — Manual cryptographic prefix stripping / construction
Fix: split_sig(value) → (algo, b64_str) · split_pubkey(value) → (algo, b64_str) · encode_sig(algo, raw) · encode_pubkey(algo, raw)
Never use removeprefix("ed25519:"), "ed25519:" + b64, or partition(":") inline on signature/pubkey strings.
| File | Notes | |
|---|---|---|
| ✅ | tests/test_core_provenance.py |
Fixed — split_sig() · encode_sig() / decode_sig() |
Pattern 11 — --format flag instead of --json
Universal rule: Every muse CLI command follows the same output convention:
- Default (no flag): plain text, human-readable
--json/-j: machine-readable JSON for agents and scripts
There is no --format flag on any muse command. --format text, --format json,
and --format xml do not exist. Code or tests using --format are wrong.
In tests: never pass --format <value> to any muse CLI invocation.
In production code: never add a --format argument to a command's parser.
JSON parsing: cmd --json output is always an envelope dict — for list-style
commands the entries are under the "entries" key, never at the top level as a bare array.
Known violations
| | File | Location | Fix |
|--|------|----------|-----|
| ✅ | tests/test_cmd_rev_parse.py | TestDefaultFormat, TestBranchResolution, TestAbbrevRef, TestEdgeCases, TestErrorJson | Removed --format text/xml; rewrote to use plain-text default |
| ✅ | tests/test_cmd_shelf.py | TestSecurity::test_invalid_format_exits_1 | assert r.exit_code != 0 (no --format flag exists) |
| ✅ | tests/test_cmd_shelf.py | TestListJsonSchema, TestReadJsonSchema, TestApplyJsonSchema, TestPopJsonSchema, TestDropJsonSchema, TestRoundTrips, TestStress | json.loads(r.output) → json.loads(r.output)["entries"] |
| ✅ | muse/cli/commands/intent.py | Fixed — replaced --format/-f with --json/-j bool flag; updated test_cmd_intent.py |
Legitimate --format uses (not violations)
| File | What --format controls |
|---|---|
snapshot_cmd.py |
Archive encoding: tar.gz or zip — file container format, not output mode |
archive.py |
Same |
narrative.py |
Narrative style: timeline or prose — content structure, not output mode |
docs_cmd.py |
Documentation output type: html, md, text, json — multi-format docs renderer; json choice is a violation but html/md have no --json equivalent |
Grep target:
"--format"in test files (no legitimate uses);add_argument.*"--format".*choices.*text.*jsonin command files.