gabriel / musehub public
feat patch dev
AI Agent gabriel · 143 days ago · May 1, 2026 · Diff

feat: Phase 6 — storage tier formalisation (HOT/WARM lifecycle)

- musehub/storage/tiers.py: new module with StorageTier enum, prune_packed, classify_object, storage_stats, and auto_pack - StorageTier.HOT = loose files; StorageTier.WARM = pack files - prune_packed removes loose objects covered by packs (missing half of the Phase 5 pack workflow) - classify_object returns HOT/WARM/None with loose taking precedence - storage_stats returns hot/warm/total counts deduplicating objects present in both tiers (pre-prune state) - auto_pack packs + prunes in one call when loose count >= min_loose - 24 new tests in 7 tiers across the full HOT→WARM lifecycle

sha256:12ddea7e93c748883b24ad5ce08bea8fe3cb02abd213de51ac1e2b063a3bc890 sha
+58 symbols
sha256:e60d1a1893f2f0b5f5c7271b651525108660a31a895e657d984f8a3cd87325cb snapshot
+58
symbols added
0
dead code introduced
Semantic Changes 58 symbols
~ musehub/storage/tiers.py .py 16 symbols added
+ AutoPackResult class class AutoPackResult L50–52
+ PruneResult class class PruneResult L35–36
+ StorageStats class class StorageStats L40–46
+ total method method total L45–46
+ StorageTier class class StorageTier L29–31
+ _loose_object_ids function function _loose_object_ids L57–69
+ _loose_path function function _loose_path L72–75
+ _packed_object_ids function function _packed_object_ids L78–87
+ auto_pack function function auto_pack L138–153
+ classify_object class function classify_object L113–123
+ Path import import Path L26–26
+ annotations import import annotations L22–22
+ dataclass class import dataclass L25–25
+ enum import import enum L24–24
+ prune_packed function function prune_packed L92–110
+ storage_stats function function storage_stats L126–135
~ tests/test_storage_tiers.py .py 42 symbols added
+ TestAutoPack class class TestAutoPack L359–410
+ test_exact_threshold_triggers method method test_exact_threshold_triggers L400–410
+ test_packs_and_prunes_when_loose_meets_threshold method method test_packs_and_prunes_when_loose_meets_threshold L360–375
+ test_skips_when_loose_below_threshold method method test_skips_when_loose_below_threshold L377–389
+ test_skips_when_no_loose_objects method method test_skips_when_no_loose_objects L391–398
+ TestClassifyObject class class TestClassifyObject L190–238
+ test_hot_before_prune_loose_and_pack_both_present method method test_hot_before_prune_loose_and_pack_both_present L214–225
+ test_hot_for_loose_object method method test_hot_for_loose_object L191–199
+ test_warm_for_object_in_pack_loose_removed method method test_warm_for_object_in_pack_loose_ L227–238
+ test_warm_for_packed_object_after_prune method method test_warm_for_packed_object_after_prune L201–212
+ TestClassifyObjectUnknown class class TestClassifyObjectUnknown L243–272
+ test_returns_none_after_object_deleted_from_all_tiers method method test_returns_none_after_object_deleted_from_all_tiers L257–272
+ test_returns_none_for_missing_object method method test_returns_none_for_missing_object L244–248
+ test_returns_none_in_empty_repo method method test_returns_none_in_empty_repo L250–255
+ TestFullPromotion class class TestFullPromotion L415–480
+ test_new_objects_written_after_prune_are_hot method async_method test_new_objects_written_after_prune_are_hot L453–480
+ test_objects_readable_through_all_lifecycle_stages method async_method test_objects_readable_through_all_lifecycle_stages L417–450
+ TestPrunePacked class class TestPrunePacked L66–127
+ test_noop_when_no_loose_exists method method test_noop_when_no_loose_exists L115–127
+ test_noop_when_no_packs_exist method method test_noop_when_no_packs_exist L102–113
+ test_removes_all_covered_loose_objects method method test_removes_all_covered_loose_objects L84–100
+ test_removes_loose_after_packing method method test_removes_loose_after_packing L67–82
+ TestPrunePackedPreservesUnpacked class class TestPrunePackedPreservesUnpacked L132–185
+ test_mixed_prune_removes_only_covered method method test_mixed_prune_removes_only_covered L156–185
+ test_preserves_loose_objects_not_in_any_pack method method test_preserves_loose_objects_not_in_any_pack L133–154
+ TestStorageStats class class TestStorageStats L277–354
+ test_all_loose_before_packing method method test_all_loose_before_packing L278–288
+ test_empty_repo_all_zeros method method test_empty_repo_all_zeros L329–335
+ test_mixed_hot_and_warm method method test_mixed_hot_and_warm L306–327
+ test_total_equals_hot_plus_warm method method test_total_equals_hot_plus_warm L337–354
+ test_warm_count_after_pack_and_prune method method test_warm_count_after_pack_and_prune L290–304
+ _count_loose function function _count_loose L52–57
+ _loose_path function function _loose_path L46–49
+ _oid function function _oid L24–27
+ _pack_dir function function _pack_dir L60–61
+ _repo_root function function _repo_root L30–34
+ _write_loose function function _write_loose L37–43
+ Path import import Path L15–15
+ annotations import import annotations L12–12
+ blob_id import import blob_id L19–19
+ pytest import import pytest L17–17
+ uuid import import uuid L14–14
← Older Oldest on dev
All commits
Newer → Latest on dev

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:12ddea7e93c748883b24ad5ce08bea8fe3cb02abd213de51ac1e2b063a3bc890 --body "your comment"