gabriel / musehub public
feat BREAKING feat/229-proposal-type-canonical-merge #1 / 1
AI Agent gabriel · 2 days ago · Oct 22, 2026 · Diff

feat: rename legacy proposalType state_merge to canonical merge (musehub#229)

Follow-up to muse#20's Phase 3 split-out. Migration 0070 canonicalised merge_strategy's legacy values (state_overlay→overlay, state_weave→weave, state_rebase→replay, domain_selective→selective) but never touched the separate proposal_type column — ProposalType.STATE_MERGE was the one member left using the old state_* naming while the other six members already follow the plain-noun convention.

state_merge → merge

New migration 0082: - Backfills existing rows: UPDATE musehub_proposals SET proposal_type = 'merge' WHERE proposal_type = 'state_merge'. - Alters the column's server_default from 'state_merge' to 'merge', mirroring migration 0072's drift-fix pattern for merge_strategy (so future raw inserts default to the canonical value without relying on the application layer).

Enum and model (musehub/models/musehub.py): - ProposalType.STATE_MERGE renamed to ProposalType.MERGE (member name, not just value) — found two additional usages beyond the ticket's own audit (lines 915, 1007) by searching for ProposalType.STATE_MERGE symbol references, not just the string literal. - Two Field(...) defaults/docstrings updated (lines 1397, 1536).

DB model (musehub/db/musehub_social_models.py): column default/server_default updated to match the migration.

Service + MCP (musehub_proposals.py x3, write_tools/proposals.py, dispatcher.py, mcp/tools/musehub.py): all default-value fallbacks and the MCP tool's JSON-schema enum/default updated.

Templates (proposal_rows.html x2, proposal_row_detail.html x2, proposal_detail.html): comparison/fallback literals updated — these drive which type gets an empty "it's the default" badge vs an explicit label.

Fixtures and tests: scripts/seed_local_proposals.py, and six tests/test_proposal_*.py files with hardcoded "state_merge"/STATE_MERGE references updated throughout (including test_proposal_type_badge.py, currently skipped pending the unrelated musehub#96 design decision — still updated so it doesn't carry a stale literal once re-enabled).

Added a new invariant test in test_proposal_reimagination_phase1.py: no ProposalType member may use state_*/domain_* legacy naming, guarding against this exact drift recurring the next time a new type is added.

Deliberately left untouched: alembic/versions/0045_proposal_type_and_merge_strategy.py (the historical migration that originally created the column with server_default="state_merge" — it's a faithful record of what was true at that point in time, not something to rewrite) and two test functions whose names contain "state_merge" as a substring of "state_merged" (proposal *lifecycle* state, unrelated to proposal_type).

Verification: - Grep gate: zero "state_merge"/"STATE_MERGE" occurrences anywhere in the repo except the two deliberate exceptions above. - muse hub proposal list --json against the local dev hub confirms all 3 existing proposals read back as "proposalType": "merge" after running `alembic upgrade head` inside the musehub container. - Confirmed create_proposal's live (container-loaded) signature default is proposal_type: str = "merge" via direct inspection inside the running musehub container, proving the fix is live, not just on disk. - Both musehub and musehub_worker containers restarted and confirmed healthy post-migration (docker ps healthy, /healthz db:true, worker "MuseHub worker started").

Regression: 841 tests passed, 10 skipped (pre-existing, unrelated musehub#96 skip) across the full proposal, MCP dispatcher, and MCP write-tools test suites — no regressions.

sha256:e2af87b322a29648518e056674c1326acbc5ee7c49445ff2a38c0c3d667d62bb sha
+13 ~37 −1 symbols
17 changed · 1098 in snapshot files
sha256:e0346a106800e10c2c2f856544dbef3285e9bc78137dd933ca3e1ee2e3753796 snapshot
+13
symbols added
~37
symbols modified
−1
symbol removed
17
files changed
1098
files in snapshot
0
dead code introduced
Semantic Changes 51 symbols
+ branch_labels variable variable branch_labels L27–27
+ depends_on variable variable depends_on L28–28
+ down_revision variable variable down_revision L26–26
+ downgrade function function downgrade L43–52
+ Sequence import import Sequence L18–18
+ Union import import Union L18–18
+ annotations import import annotations L16–16
+ op import import op L20–20
+ sa import import sa L21–21
+ revision variable variable revision L25–25
+ upgrade function function upgrade L31–40
~ musehub/mcp/dispatcher.py .py 1 symbol modified
~ scripts/seed_local_proposals.py .py 1 symbol modified
~ tests/test_proposal_type_badge.py .py 1 symbol added, 1 symbol removed, 2 symbols modified
− test_T9_3_state_merge_shows_label function async_function test_T9_3_state_merge_shows_label L149–167
+ test_T9_3_merge_shows_label function async_function test_T9_3_merge_shows_label L149–167
Files Changed
+1 ~16
1098 in snapshot
← Older Oldest on feat/229-proposal-type-canonical-merge
All commits
Newer → Latest on feat/229-proposal-type-canonical-merge

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:e2af87b322a29648518e056674c1326acbc5ee7c49445ff2a38c0c3d667d62bb --body "your comment"