gabriel / musehub public
feat BREAKING proposals task/proposal-models-v2 #3 / 19
AI Agent gabriel · 129 days ago · May 8, 2026 · Diff

feat(proposals): PATCH endpoint for partial proposal updates

T10.1–T10.9 all pass: - ProposalUpdate model (title, body, proposal_type, merge_strategy — all optional, at least one required, extra fields forbidden) - update_proposal() service function (partial, only non-None fields written) - PATCH /api/repos/{repo_id}/proposals/{proposal_id} route (author-only via require_valid_token + handle check; 401/403/404 guarded) - Agent guidance: proposal titles must be plain English, not branch-name style

sha256:adf01087d7c78d79aea00d30d12abff941c2c60724bdb28aa322b6d4f464a7d4 sha
+32 ~26 symbols
sha256:41262d6547de7b5a615e82cde641e8f4346313f0438ff03d9578457fd7d83b40 snapshot
+32
symbols added
~26
symbols modified
0
dead code introduced
Semantic Changes 58 symbols
~ tests/test_proposal_update.py .py 24 symbols added
+ _make_proposal function async_function _make_proposal L43–72
+ _make_repo function async_function _make_repo L30–40
+ _seq variable variable _seq L27–27
+ AsyncClient import import AsyncClient L20–20
+ AsyncSession import import AsyncSession L21–21
+ MusehubProposal import import MusehubProposal L24–24
+ MusehubRepo import import MusehubRepo L24–24
+ annotations import import annotations L15–15
+ compute_identity_id import import compute_identity_id L23–23
+ compute_proposal_id import import compute_proposal_id L23–23
+ compute_repo_id import import compute_repo_id L23–23
+ datetime import import datetime L17–17
+ now_utc_iso import import now_utc_iso L25–25
+ pytest import import pytest L19–19
+ timezone import import timezone L17–17
+ test_T10_1_author_can_update_title function async_function test_T10_1_author_can_update_title L80–95
+ test_T10_2_author_can_update_body function async_function test_T10_2_author_can_update_body L103–117
+ test_T10_3_author_can_update_proposal_type function async_function test_T10_3_author_can_update_proposal_type L125–139
+ test_T10_4_author_can_update_merge_strategy function async_function test_T10_4_author_can_update_merge_strategy L147–161
+ test_T10_5_partial_update_only_changes_supplied_fields function async_function test_T10_5_partial_update_only_changes_supplied_fields L169–191
+ test_T10_6_non_author_cannot_update function async_function test_T10_6_non_author_cannot_update L199–213
+ test_T10_7_unauthenticated_update_returns_401 function async_function test_T10_7_unauthenticated_update_returns_401 L221–232
+ test_T10_8_missing_proposal_returns_404 function async_function test_T10_8_missing_proposal_returns_404 L240–253
+ test_T10_9_empty_patch_body_returns_422 function async_function test_T10_9_empty_patch_body_returns_422 L261–274
~ .cursorrules .cursorrules
~ .windsurfrules .windsurfrules
~ AGENTS.md .md 2 symbols added, 3 symbols modified
+ Proposal Titles section Proposal Titles L147–164
+ table@L154 section table@L154 L154–159
~ musehub/models/musehub.py .py 3 symbols added, 4 symbols modified
+ ProposalUpdate class class ProposalUpdate L936–954
+ at_least_one_field method method at_least_one_field L951–954
+ ConfigDict import import ConfigDict L12–12
~ Field
+ update_proposal function async_function update_proposal L488–518

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