feat(deck): surface remapped labels in move-card response
Round-3 review polish on PR #885: - deck_move_card_to_board now captures the moved DeckCard and returns its post-move label titles in CardOperationResponse.labels, so LLM clients can confirm the cross-board label remap (the tool's headline behaviour) without a follow-up deck_get_card. The field is optional and defaults to None for the other card operations that share this response model. - Tighten test_move_card_to_board_restores_done_state to assert the returned card reflects the restored done state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
7a39767482
commit
69b32f345c
@@ -337,6 +337,14 @@ class CardOperationResponse(StatusResponse):
|
|||||||
card_id: int = Field(description="ID of the affected card")
|
card_id: int = Field(description="ID of the affected card")
|
||||||
stack_id: int = Field(description="ID of the stack containing the card")
|
stack_id: int = Field(description="ID of the stack containing the card")
|
||||||
board_id: int = Field(description="ID of the board containing the card")
|
board_id: int = Field(description="ID of the board containing the card")
|
||||||
|
labels: list[str] | None = Field(
|
||||||
|
default=None,
|
||||||
|
description=(
|
||||||
|
"Label titles on the card after the operation, when relevant — "
|
||||||
|
"e.g. after a cross-board move that remaps board-scoped labels to "
|
||||||
|
"the destination board"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Label Response Models
|
# Label Response Models
|
||||||
|
|||||||
@@ -1291,7 +1291,7 @@ def configure_deck_tools(mcp: FastMCP):
|
|||||||
order: Position within the destination stack (default 0 = top)
|
order: Position within the destination stack (default 0 = top)
|
||||||
"""
|
"""
|
||||||
client = await get_client(ctx)
|
client = await get_client(ctx)
|
||||||
await client.deck.move_card_to_board(
|
moved = await client.deck.move_card_to_board(
|
||||||
source_board_id,
|
source_board_id,
|
||||||
source_stack_id,
|
source_stack_id,
|
||||||
card_id,
|
card_id,
|
||||||
@@ -1299,12 +1299,15 @@ def configure_deck_tools(mcp: FastMCP):
|
|||||||
target_stack_id,
|
target_stack_id,
|
||||||
order,
|
order,
|
||||||
)
|
)
|
||||||
|
# Surface the post-move labels so callers can confirm the remap without
|
||||||
|
# a follow-up get_card (label remapping is this tool's whole point).
|
||||||
return CardOperationResponse(
|
return CardOperationResponse(
|
||||||
success=True,
|
success=True,
|
||||||
message="Card moved to board successfully",
|
message="Card moved to board successfully",
|
||||||
card_id=card_id,
|
card_id=card_id,
|
||||||
stack_id=target_stack_id,
|
stack_id=target_stack_id,
|
||||||
board_id=target_board_id,
|
board_id=target_board_id,
|
||||||
|
labels=[label.title for label in (moved.labels or [])],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Label Tools
|
# Label Tools
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ async def test_move_card_to_board_restores_done_state(mocker):
|
|||||||
)
|
)
|
||||||
|
|
||||||
client = DeckClient(mocker.AsyncMock(spec=httpx.AsyncClient), "testuser")
|
client = DeckClient(mocker.AsyncMock(spec=httpx.AsyncClient), "testuser")
|
||||||
await client.move_card_to_board(
|
result = await client.move_card_to_board(
|
||||||
source_board_id=1,
|
source_board_id=1,
|
||||||
source_stack_id=10,
|
source_stack_id=10,
|
||||||
card_id=8,
|
card_id=8,
|
||||||
@@ -134,6 +134,8 @@ async def test_move_card_to_board_restores_done_state(mocker):
|
|||||||
done_call = mock_make_request.call_args_list[3]
|
done_call = mock_make_request.call_args_list[3]
|
||||||
assert done_call.args[0] == "PUT"
|
assert done_call.args[0] == "PUT"
|
||||||
assert done_call.args[1] == "/apps/deck/cards/8/done"
|
assert done_call.args[1] == "/apps/deck/cards/8/done"
|
||||||
|
# The returned card reflects the re-fetched (restored) done state
|
||||||
|
assert result.done is not None
|
||||||
|
|
||||||
|
|
||||||
async def test_move_card_to_board_rejects_stack_not_on_target_board(mocker):
|
async def test_move_card_to_board_rejects_stack_not_on_target_board(mocker):
|
||||||
|
|||||||
Reference in New Issue
Block a user