feat(6243): a directory moved in the tree keeps its shape judgments
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Failing after 15s
CI & Build / TypeScript typecheck (push) Successful in 55s
CI & Build / integration (push) Successful in 1m15s
CI & Build / Python tests (push) Successful in 2m9s
CI & Build / Build & push image (push) Successful in 30s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Failing after 15s
CI & Build / TypeScript typecheck (push) Successful in 55s
CI & Build / integration (push) Successful in 1m15s
CI & Build / Python tests (push) Successful in 2m9s
CI & Build / Build & push image (push) Successful in 30s
Ledger rows are keyed by path, so after a directory moves the next sync marks every judged row vanished and lists the same shapes again, unjudged. move_shapes(project_id, from_path, to_path) re-keys the rows under one path to the other, in every repo of the project, keeping each row's judgment, uses edges and history and adding a `moved` event that records the path it left. A row already at the target is replaced when nobody judged it; a judged one stands, and the old row is reported in `kept`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -200,7 +200,7 @@ _WRITE_TOOLS = frozenset({
|
||||
"merge_snippets", "unmerge_snippet",
|
||||
"create_process", "update_process", "delete_process",
|
||||
"classify_shapes", "classify_shapes_by_rule", "confirm_shape_proposals",
|
||||
"refresh_pattern_coverage",
|
||||
"refresh_pattern_coverage", "move_shapes",
|
||||
# design systems
|
||||
"create_design_system", "update_design_system", "delete_design_system",
|
||||
"create_design_token", "update_design_token", "delete_design_token",
|
||||
|
||||
@@ -263,7 +263,8 @@ async def shape_history(
|
||||
snippet_id, who, why — one per judgment, so a shape that was an instance
|
||||
of #N and later a variant of #M shows both), `vanished`, `reappeared`,
|
||||
`drifted` (the body moved under a judgment; see list_shapes flag=
|
||||
"recheck"). Each event carries the commit the tree was read at.
|
||||
"recheck"), `moved` (move_shapes carried the row; the event's `path`
|
||||
is the one it left). Each event carries the commit the tree was read at.
|
||||
|
||||
Read it as a timeline: "instance of #N from <first classified at>,
|
||||
re-judged variant of #M at <at> because <reason>, vanished at <commit>".
|
||||
@@ -398,10 +399,38 @@ async def refresh_pattern_coverage(project_id: int) -> dict:
|
||||
}
|
||||
|
||||
|
||||
async def move_shapes(project_id: int, from_path: str, to_path: str) -> dict:
|
||||
"""Carry the judgments of a file or directory that moved in the tree.
|
||||
|
||||
Rows are keyed by path. After `git mv src/old src/new`, the next coverage
|
||||
refresh would mark every row under src/old vanished and list the same
|
||||
shapes again under src/new, unclassified, with every judgment left
|
||||
behind. Run this once the move is committed, before that refresh:
|
||||
each row under `from_path` is re-keyed to the same place under
|
||||
`to_path`, in every repo bound to the project, keeping its judgment,
|
||||
uses edges and history, and gaining a `moved` event (shape_history).
|
||||
|
||||
A row already at the new path is replaced when nobody judged it (the
|
||||
refresh ran first, or the sync stamped it `scoped`); a judged one stands,
|
||||
and the old row is left behind and listed in `kept`. The refresh that
|
||||
follows compares bodies as always: a judged shape whose body changed in
|
||||
the move comes back flagged `recheck`.
|
||||
|
||||
Args:
|
||||
project_id: The project whose ledger moves. Requires write access.
|
||||
from_path: The file or directory the shapes were found at.
|
||||
to_path: Where it lives now. Neither path may contain the other.
|
||||
|
||||
Returns {"moved": N, "replaced": N, "kept": [{path, symbol, kind}]}.
|
||||
"""
|
||||
uid = current_user_id()
|
||||
return await shape_ledger_svc.move_shapes(uid, project_id, from_path, to_path)
|
||||
|
||||
|
||||
def register(mcp) -> None:
|
||||
for fn in (
|
||||
classify_shapes, classify_shapes_by_rule, list_shapes,
|
||||
refresh_pattern_coverage, confirm_shape_proposals, shape_history,
|
||||
stamps_to_review,
|
||||
stamps_to_review, move_shapes,
|
||||
):
|
||||
mcp.tool(name=fn.__name__)(fn)
|
||||
|
||||
Reference in New Issue
Block a user