gabriel / musehub public
feat BREAKING dev
AI Agent gabriel · 171 days ago · Apr 9, 2026 · Diff

feat: replace milestones with Muse-native release tracking via commit anchors

Delete MusehubMilestone entirely — milestones were a GitHub-ism for connecting issues to releases when the VCS lacked that link. Muse has commit_anchors on every issue; the VCS graph is the source of truth.

Changes: - Drop musehub_milestones and musehub_issue_milestones tables (migration 0036) - Remove MusehubMilestone, MusehubIssueMilestone ORM models - Remove milestone_id FK from MusehubIssue - Remove MilestoneCreate/Response/ListResponse Pydantic models - Delete milestones.py and ui_milestones.py route modules - Delete all milestone templates and macros (6 files) - Delete all milestone test files (3 files) - Add get_issue_release_context() service function: resolves commit anchors against MusehubRelease records to determine which release(s) a fix landed in - Issue detail sidebar: replace milestone card with release card showing 'landed in vX.Y.Z', 'fix on dev (unreleased)', or 'no commits yet' - Issue list: remove milestone filter, bulk milestone select, milestone sidebar - Update SCSS: add release card theme, remove all milestone styles - Clean up all milestone references from TS, docstrings, and test helpers

sha256:79bee467f8df740a1b02378037307566416bf0639cc8f11eeeb04f58f221e1ea sha
+10 ~54 −276 symbols
sha256:913a1e4d1f86687a9f4b0508558a36db8eaa9cd57e3716ac7e110003b1b7d68c snapshot
+10
symbols added
~54
symbols modified
−276
symbols removed
0
dead code introduced
Semantic Changes 340 symbols
+ branch_labels variable variable branch_labels L15–15
+ depends_on variable variable depends_on L16–16
+ down_revision variable variable down_revision L14–14
+ downgrade function function downgrade L39–41
+ op import import op L11–11
+ revision variable variable revision L13–13
+ upgrade function function upgrade L19–36
~ musehub/api/routes/musehub/milestones.py .py 35 symbols removed
− MilestoneUpdate class class MilestoneUpdate L45–64
− _get_issue_counts function async_function _get_issue_counts L88–102
− _to_milestone_response function function _to_milestone_response L70–85
− create_milestone function async_function create_milestone L155–180
− delete_milestone function async_function delete_milestone L274–310
− get_milestone function async_function get_milestone L189–213
− APIRouter import import APIRouter L20–20
− AsyncSession import import AsyncSession L23–23
− CamelModel import import CamelModel L33–33
− Depends import import Depends L20–20
− Field import import Field L21–21
− HTTPException import import HTTPException L20–20
− MilestoneCreate import import MilestoneCreate L28–28
− MilestoneListResponse import import MilestoneListResponse L28–28
− MilestoneResponse import import MilestoneResponse L28–28
− Query import import Query L20–20
− TokenClaims import import TokenClaims L25–25
− annotations import import annotations L14–14
− datetime import import datetime L18–18
− db import import db L27–27
− func function import func L22–22
− get_db import import get_db L26–26
− logging import import logging L17–17
− musehub_issues import import musehub_issues L34–34
− musehub_repository import import musehub_repository L35–35
− optional_token import import optional_token L25–25
− require_scope import import require_scope L25–25
− require_valid_token import import require_valid_token L25–25
− select import import select L22–22
− status import import status L20–20
− update import import update L22–22
− list_milestones function async_function list_milestones L114–145
− logger variable variable logger L37–37
− router variable variable router L39–39
− update_milestone function async_function update_milestone L222–265
− APIRouter import import APIRouter L29–29
− AsyncSession import import AsyncSession L31–31
− BranchParam import import BranchParam L35–35
− Depends import import Depends L29–29
− FilePathParam import import FilePathParam L35–35
− HTTPException import import HTTPException L29–29
− IssueListResponse import import IssueListResponse L38–38
− JSONObject import import JSONObject L37–37
− MilestoneListResponse import import MilestoneListResponse L38–38
− MilestoneResponse import import MilestoneResponse L38–38
− Query import import Query L29–29
− Request import import Request L29–29
− SlugParam import import SlugParam L35–35
− StarletteResponse import import StarletteResponse L32–32
− _breadcrumbs import import _breadcrumbs L45–45
− _resolve_repo import import _resolve_repo L45–45
− get_db import import get_db L36–36
− http_status import import http_status L30–30
− logging import import logging L27–27 → moved to musehub/api/routes/musehub/ui_issues.py
− musehub_issues import import musehub_issues L43–43
− negotiate_response import import negotiate_response L34–34
− templates import import templates L44–44
− logger variable variable logger L47–47 → moved to musehub/api/routes/musehub/ui_issues.py
− milestone_detail_page function async_function milestone_detail_page L151–246
− milestones_list_page function async_function milestones_list_page L68–139
− router variable variable router L49–49
~ tests/test_issues_milestones.py .py 125 symbols removed
− TestDataIntegrity class class TestDataIntegrity L1018–1108
− test_assign_issue_does_not_affect_other_issues method async_method test_assign_issue_does_not_affect_other_issues L1050–1061
− test_cross_repo_issue_isolation method async_method test_cross_repo_issue_isolation L1042–1047
− test_delete_comment_returns_false_for_wrong_issue method async_method test_delete_comment_returns_false_for_wrong_issue L1093–1108
− test_issue_number_survives_deletions method async_method test_issue_number_survives_deletions L1020–1029
− test_milestone_state_closed_persists method async_method test_milestone_state_closed_persists L1083–1090
− test_soft_delete_preserves_comment_in_db method async_method test_soft_delete_preserves_comment_in_db L1064–1080
− test_update_does_not_change_number method async_method test_update_does_not_change_number L1032–1039
− TestE2EComments class class TestE2EComments L700–755
− test_create_comment_201 method async_method test_create_comment_201 L702–714
− test_delete_comment_204 method async_method test_delete_comment_204 L735–755
− test_list_comments method async_method test_list_comments L717–732
− TestE2EIssues class class TestE2EIssues L570–697
− test_assign_issue method async_method test_assign_issue L668–679
− test_close_issue method async_method test_close_issue L622–632
− test_create_issue_201 method async_method test_create_issue_201 L572–585
− test_get_issue_by_number method async_method test_get_issue_by_number L588–595
− test_get_nonexistent_issue_404 method async_method test_get_nonexistent_issue_404 L598–603
− test_list_issues_default_open method async_method test_list_issues_default_open L606–619
− test_reopen_issue method async_method test_reopen_issue L635–649
− test_unassign_issue method async_method test_unassign_issue L682–697
− test_update_issue_patch method async_method test_update_issue_patch L652–665
− TestE2EMCPTools class class TestE2EMCPTools L887–939
− test_execute_create_comment method async_method test_execute_create_comment L927–939
− test_execute_create_issue method async_method test_execute_create_issue L889–902
− test_execute_create_issue_missing_repo method async_method test_execute_create_issue_missing_repo L905–911
− test_execute_update_issue_close method async_method test_execute_update_issue_close L914–924
− TestE2EMilestones class class TestE2EMilestones L758–884
− test_create_milestone_201 method async_method test_create_milestone_201 L760–773
− test_delete_milestone_204 method async_method test_delete_milestone_204 L829–843
− test_get_milestone_by_number method async_method test_get_milestone_by_number L776–787
− test_remove_issue_milestone_via_http method async_method test_remove_issue_milestone_via_http L866–884
− test_set_issue_milestone_via_http method async_method test_set_issue_milestone_via_http L846–863
− test_update_milestone method async_method test_update_milestone L790–807
− test_update_milestone_clear_due_on method async_method test_update_milestone_clear_due_on L810–826
− TestIntegrationCommentCount class class TestIntegrationCommentCount L427–457
− test_comment_count_in_issue_response method async_method test_comment_count_in_issue_response L429–439
− test_soft_deleted_comments_not_counted method async_method test_soft_deleted_comments_not_counted L442–457
− TestIntegrationListFilters class class TestIntegrationListFilters L460–515
− test_list_all_state method async_method test_list_all_state L473–480
− test_list_by_label method async_method test_list_by_label L483–490
− test_list_by_milestone method async_method test_list_by_milestone L493–506
− test_list_open_default method async_method test_list_open_default L462–470
− test_list_ordered_by_number method async_method test_list_ordered_by_number L509–515
− TestIntegrationMilestoneProgress class class TestIntegrationMilestoneProgress L518–562
− test_delete_milestone_unlinks_issues method async_method test_delete_milestone_unlinks_issues L538–562
− test_open_and_closed_counts method async_method test_open_and_closed_counts L520–535
− TestPerformance class class TestPerformance L1218–1294
− test_create_issue_under_50ms method async_method test_create_issue_under_50ms L1265–1274
− test_list_50_issues_under_200ms method async_method test_list_50_issues_under_200ms L1220–1234
− test_list_milestones_with_counts_under_300ms method async_method test_list_milestones_with_counts_under_300ms L1237–1262
− test_pagination_total_consistent method async_method test_pagination_total_consistent L1277–1294
− TestSecurity class class TestSecurity L1116–1210
− test_close_requires_auth method async_method test_close_requires_auth L1128–1138
− test_comment_body_max_length_enforced method async_method test_comment_body_max_length_enforced L1189–1199
− test_comment_create_requires_auth method async_method test_comment_create_requires_auth L1141–1151
− test_create_issue_requires_auth method async_method test_create_issue_requires_auth L1118–1125
− test_cross_repo_issue_not_accessible method async_method test_cross_repo_issue_not_accessible L1166–1174
− test_milestone_create_requires_auth method async_method test_milestone_create_requires_auth L1154–1163
− test_read_endpoints_accessible_without_auth method async_method test_read_endpoints_accessible_without_auth L1202–1210
− test_title_max_length_enforced method async_method test_title_max_length_enforced L1177–1186
− TestStress class class TestStress L947–1010
− test_100_issues_in_one_repo method async_method test_100_issues_in_one_repo L949–959
− test_bulk_label_replacement method async_method test_bulk_label_replacement L962–974
− test_deep_comment_thread method async_method test_deep_comment_thread L977–991
− test_milestone_with_50_issues method async_method test_milestone_with_50_issues L994–1010
− TestUnitComments class class TestUnitComments L260–329
− test_create_and_list_comment method async_method test_create_and_list_comment L262–272
− test_include_deleted_exposes_soft_deleted method async_method test_include_deleted_exposes_soft_deleted L289–301
− test_invalid_parent_raises_value_error method async_method test_invalid_parent_raises_value_error L321–329
− test_soft_delete_hides_comment method async_method test_soft_delete_hides_comment L275–286
− test_threaded_reply_validates_parent method async_method test_threaded_reply_validates_parent L304–318
− TestUnitIssueCreate class class TestUnitIssueCreate L116–150
− test_creates_in_open_state method async_method test_creates_in_open_state L118–121
− test_numbers_independent_per_repo method async_method test_numbers_independent_per_repo L132–138
− test_sequential_numbers method async_method test_sequential_numbers L124–129
− test_stores_author method async_method test_stores_author L141–144
− test_stores_labels method async_method test_stores_labels L147–150
− TestUnitIssueStateTransitions class class TestUnitIssueStateTransitions L153–184
− test_close_issue method async_method test_close_issue L155–160
− test_close_nonexistent_returns_none method async_method test_close_nonexistent_returns_none L172–175
− test_reopen_idempotent method async_method test_reopen_idempotent L178–184
− test_reopen_issue method async_method test_reopen_issue L163–169
− TestUnitIssueUpdate class class TestUnitIssueUpdate L187–223
− test_update_body_only method async_method test_update_body_only L199–206
− test_update_labels_replaces_all method async_method test_update_labels_replaces_all L209–215
− test_update_nonexistent_returns_none method async_method test_update_nonexistent_returns_none L218–223
− test_update_title method async_method test_update_title L189–196
− TestUnitLabelOps class class TestUnitLabelOps L226–257
− test_assign_labels_replaces method async_method test_assign_labels_replaces L228–234
− test_remove_label_idempotent method async_method test_remove_label_idempotent L247–257
− test_remove_label_single method async_method test_remove_label_single L237–244
− TestUnitMilestones class class TestUnitMilestones L332–419
− test_clear_issue_milestone method async_method test_clear_issue_milestone L362–374
− test_completeness_sort method async_method test_completeness_sort L402–419
− test_create_milestone method async_method test_create_milestone L334–339
− test_cross_repo_milestone_raises method async_method test_cross_repo_milestone_raises L377–385
− test_list_milestones_open_only_by_default method async_method test_list_milestones_open_only_by_default L388–399
− test_milestone_numbers_sequential method async_method test_milestone_numbers_sequential L342–347
− test_set_issue_milestone method async_method test_set_issue_milestone L350–359
− _api_issue function async_function _api_issue L95–108
− _api_repo function async_function _api_repo L87–92
− _issue function async_function _issue L53–67
− _milestone function async_function _milestone L70–83
− _now function function _now L45–46
− _repo function async_function _repo L49–50
− _uid function function _uid L41–42
− AsyncClient import import AsyncClient L28–28
− AsyncSession import import AsyncSession L29–29
− IssueResponse import import IssueResponse L33–33
− JSONObject import import JSONObject L36–36
− MilestoneResponse import import MilestoneResponse L33–33
− StrDict import import StrDict L36–36
− annotations import import annotations L21–21
− create_repo import import create_repo L35–35
− datetime import import datetime L25–25
− db import import db L32–32
− func function import func L30–30
− musehub_issues import import musehub_issues L34–34
− pytest import import pytest L27–27
− select import import select L30–30
− time import import time L23–23
− timedelta import import timedelta L25–25
− timezone import import timezone L25–25
− uuid import import uuid L24–24
~ tests/test_musehub_ui_milestones.py .py 29 symbols removed
− _make_issue function async_function _make_issue L83–106
− _make_milestone function async_function _make_milestone L59–80
− _make_repo function async_function _make_repo L44–56
− AsyncClient import import AsyncClient L29–29
− AsyncSession import import AsyncSession L30–30
− MusehubIssue import import MusehubIssue L32–32
− MusehubMilestone import import MusehubMilestone L32–32
− MusehubRepo import import MusehubRepo L32–32
− annotations import import annotations L26–26
− pytest import import pytest L28–28
− test_milestone_detail_has_linked_issues_js function async_function test_milestone_detail_has_linked_issues_js L274–284
− test_milestone_detail_has_progress_bar function async_function test_milestone_detail_has_progress_bar L260–270
− test_milestone_detail_has_state_filter_tabs function async_function test_milestone_detail_has_state_filter_tabs L288–298
− test_milestone_detail_json_has_linked_issues function async_function test_milestone_detail_json_has_linked_issues L315–329
− test_milestone_detail_json_issue_counts function async_function test_milestone_detail_json_issue_counts L354–370
− test_milestone_detail_json_response function async_function test_milestone_detail_json_response L302–311
− test_milestone_detail_no_auth_required function async_function test_milestone_detail_no_auth_required L248–256
− test_milestone_detail_page_returns_200 function async_function test_milestone_detail_page_returns_200 L235–244
− test_milestone_detail_unknown_number_404 function async_function test_milestone_detail_unknown_number_404 L333–340
− test_milestone_detail_unknown_repo_404 function async_function test_milestone_detail_unknown_repo_404 L344–350
− test_milestones_list_has_progress_bar_js function async_function test_milestones_list_has_progress_bar_js L138–147
− test_milestones_list_has_sort_controls_js function async_function test_milestones_list_has_sort_controls_js L166–175
− test_milestones_list_has_state_tabs_js function async_function test_milestones_list_has_state_tabs_js L151–162
− test_milestones_list_json_has_milestones_key function async_function test_milestones_list_json_has_milestones_key L192–204
− test_milestones_list_json_response function async_function test_milestones_list_json_response L179–188
− test_milestones_list_no_auth_required function async_function test_milestones_list_no_auth_required L127–134
− test_milestones_list_page_returns_200 function async_function test_milestones_list_page_returns_200 L115–123
− test_milestones_list_shows_base_url_not_repo_id function async_function test_milestones_list_shows_base_url_not_repo_id L218–226
− test_milestones_list_unknown_repo_404 function async_function test_milestones_list_unknown_repo_404 L208–214
~ tests/test_musehub_ui_milestones_ssr.py .py 17 symbols removed
− _make_issue function async_function _make_issue L75–98
− _make_milestone function async_function _make_milestone L51–72
− _make_repo function async_function _make_repo L36–48
− AsyncClient import import AsyncClient L21–21
− AsyncSession import import AsyncSession L22–22
− MusehubIssue import import MusehubIssue L24–24
− MusehubMilestone import import MusehubMilestone L24–24
− MusehubRepo import import MusehubRepo L24–24
− annotations import import annotations L18–18
− pytest import import pytest L20–20
− test_milestone_detail_issue_state_filter_closed function async_function test_milestone_detail_issue_state_filter_closed L207–225
− test_milestone_detail_renders_milestone_title function async_function test_milestone_detail_renders_milestone_title L173–183
− test_milestone_detail_shows_linked_issues function async_function test_milestone_detail_shows_linked_issues L187–203
− test_milestone_detail_unknown_number_404 function async_function test_milestone_detail_unknown_number_404 L229–236
− test_milestones_list_htmx_state_switch_returns_fragment function async_function test_milestones_list_htmx_state_switch_returns_fragment L146–164
− test_milestones_list_progress_bar_has_correct_width function async_function test_milestones_list_progress_bar_has_correct_width L124–142
− test_milestones_list_renders_title_server_side function async_function test_milestones_list_renders_title_server_side L107–120
~ musehub/api/routes/musehub/issues.py .py 2 symbols removed, 1 symbol modified
− remove_issue_milestone function async_function remove_issue_milestone L496–518
− set_issue_milestone function async_function set_issue_milestone L354–381
~ musehub/api/routes/musehub/ui_issues.py .py 2 symbols added, 2 symbols modified
+ logging import import logging L12–12 ← moved from musehub/api/routes/musehub/ui_milestones.py
+ logger variable variable logger L14–14 ← moved from musehub/api/routes/musehub/ui_milestones.py
~ musehub/db/musehub_models.py .py 2 symbols removed, 3 symbols modified
− MusehubIssueMilestone class class MusehubIssueMilestone L429–460
− MusehubMilestone class class MusehubMilestone L380–426
~ musehub/models/musehub.py .py 3 symbols removed, 1 symbol modified
− MilestoneCreate class class MilestoneCreate L680–695
− MilestoneListResponse class class MilestoneListResponse L713–716
− MilestoneResponse class class MilestoneResponse L698–710
~ musehub/services/musehub_issues.py .py 1 symbol added, 9 symbols removed, 12 symbols modified
− _next_milestone_number function async_function _next_milestone_number L106–112
− _to_milestone_response function function _to_milestone_response L79–94
− create_milestone function async_function create_milestone L617–641
− get_milestone function async_function get_milestone L695–718
− MilestoneListResponse import import MilestoneListResponse L26–26
− MilestoneResponse import import MilestoneResponse L26–26
− selectinload import import selectinload L22–22
− list_milestones function async_function list_milestones L644–692
− set_issue_milestone function async_function set_issue_milestone L442–480
+ get_issue_release_context function async_function get_issue_release_context L529–603
~ musehub/templates/musehub/static/js/pages/issue-detail.ts .ts 1 symbol removed, 1 symbol modified
− animateMilestone function function animateMilestone L32–41
~ musehub/templates/musehub/static/js/pages/issue-list.ts .ts 1 symbol removed, 1 symbol modified
− bulkAssignMilestone function function bulkAssignMilestone L82–82
~ tests/test_musehub_issues.py .py 16 symbols removed, 1 symbol modified
− test_assign_issue_to_milestone function async_function test_assign_issue_to_milestone L574–597
− test_create_milestone function async_function test_create_milestone L552–570
− test_delete_issue_milestone_idempotent function async_function test_delete_issue_milestone_idempotent L935–948
− test_delete_issue_milestone_not_found function async_function test_delete_issue_milestone_not_found L952–963
− test_delete_issue_milestone_removes_link function async_function test_delete_issue_milestone_removes_link L901–931
− test_delete_milestone_unlinks_issues function async_function test_delete_milestone_unlinks_issues L826–867
− test_edit_issue_title_and_body function async_function test_edit_issue_title_and_body L682–698
− test_get_milestone_by_number function async_function test_get_milestone_by_number L732–757
− test_get_milestone_not_found function async_function test_get_milestone_not_found L761–772
− test_issue_comment_count_in_response function async_function test_issue_comment_count_in_response L653–678
− test_list_milestones function async_function test_list_milestones L702–728
− test_list_milestones_sort_by_title function async_function test_list_milestones_sort_by_title L871–892
− test_reopen_issue function async_function test_reopen_issue L601–620
− test_threaded_comment_reply function async_function test_threaded_comment_reply L624–649
− test_update_milestone_clear_due_on function async_function test_update_milestone_clear_due_on L802–822
− test_update_milestone_title_and_state function async_function test_update_milestone_title_and_state L776–798
~ tests/test_musehub_ui_issue_list_enhanced.py .py 9 symbols removed, 3 symbols modified
− _make_milestone function async_function _make_milestone L141–161
− MusehubMilestone import import MusehubMilestone L86–86
− test_issue_list_bulk_assign_milestone_js_present function async_function test_issue_list_bulk_assign_milestone_js_present L811–818
− test_issue_list_bulk_milestone_select_present function async_function test_issue_list_bulk_milestone_select_present L720–727
− test_issue_list_filter_milestone_select_present function async_function test_issue_list_filter_milestone_select_present L507–515
− test_issue_list_milestone_progress_bar_css_present function async_function test_issue_list_milestone_progress_bar_css_present L436–443
− test_issue_list_milestone_progress_heading_present function async_function test_issue_list_milestone_progress_heading_present L425–432
− test_issue_list_milestone_progress_in_right_sidebar function async_function test_issue_list_milestone_progress_in_right_sidebar L402–410
− test_issue_list_milestone_progress_list_present function async_function test_issue_list_milestone_progress_list_present L447–454
← 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:79bee467f8df740a1b02378037307566416bf0639cc8f11eeeb04f58f221e1ea --body "your comment"