# PR-09 Asset Move Action and Relocate Wizard

Domain owner: `docs/studio`

## Briefing

Adicionar a action `Move` na área de actions do asset selecionado e conectá-la a um wizard de relocação explícita.

O usuário deve escolher o destino do asset e revisar um resumo antes da execução.
Depois da confirmação, o Studio não move diretórios localmente.
Ele apenas envia um comando de relocação para o packer, que passa a ser o owner completo da mudança:

- atualiza o estado interno necessário;
- move o diretório do asset dentro da árvore `assets` do projeto;
- emite eventos operacionais até a conclusão.

Este plano também fecha uma regra operacional que precisa existir nas duas pontas:

- o diretório destino final do asset não pode já ser um root de asset;
- portanto, o root destino não pode conter `asset.json`.

Após a confirmação do resumo, o modal deve entrar em estado de espera com spinner, escutando o evento operacional do packer.
Quando a operação terminar:

- sucesso: o Studio dispara refresh, fecha o modal e reposiciona a seleção;
- falha: o modal sai do estado de espera e mostra a falha sem fechar silenciosamente.

## Objective

Entregar um fluxo de `Move` que seja explícito, previsível e compatível com o modelo em que o packer executa a mutação real e o Studio apenas comanda e observa.

Após este PR:

- a seção `Actions` do selected asset expõe `Move`;
- clicar em `Move` abre um wizard dedicado;
- o wizard coleta o parent de destino e o nome final do diretório;
- o wizard mostra um passo final de resumo antes do comando final;
- o Studio não aceita um destino cujo root já contenha `asset.json`;
- o packer também rejeita esse destino como regra de segurança e conformance;
- a confirmação final envia um comando de relocation para o packer via API;
- o modal entra em espera com spinner até receber o evento terminal da operação;
- o refresh estrutural só ocorre depois do evento de conclusão do packer.

## Dependencies

- [`./PR-05e-assets-staged-mutations-preview-and-apply.md`](./PR-05e-assets-staged-mutations-preview-and-apply.md)
- [`./PR-07c-asset-details-and-form-lifecycle.md`](./PR-07c-asset-details-and-form-lifecycle.md)
- [`./PR-07d-asset-mutation-and-structural-sync-orchestration.md`](./PR-07d-asset-mutation-and-structural-sync-orchestration.md)
- [`../specs/4. Assets Workspace Specification.md`](../specs/4.%20Assets%20Workspace%20Specification.md)
- cross-domain reference: [`../../packer/pull-requests/PR-05-sensitive-mutations-preview-apply-and-studio-write-adapter.md`](../../packer/pull-requests/PR-05-sensitive-mutations-preview-apply-and-studio-write-adapter.md)
- cross-domain reference: [`../../packer/pull-requests/PR-09-event-lane-progress-and-studio-operational-integration.md`](../../packer/pull-requests/PR-09-event-lane-progress-and-studio-operational-integration.md)

## Scope

- adicionar a action `Move` na seção `Actions` do details
- introduzir um `Relocate Wizard` efetivamente utilizável pelo selected asset atual
- coletar destino por:
  - parent directory
  - destination name
  - target root derivado
- mostrar passo final de resumo antes da confirmação
- enviar um comando `RELOCATE_ASSET` com `targetRoot` explícito para o packer
- abrir estado modal de espera com spinner após confirmação
- correlacionar a operação via `operationId`
- escutar o evento operacional do packer até `ACTION_APPLIED` ou `ACTION_FAILED`
- publicar structural sync explícito apenas após conclusão bem-sucedida
- validar no Studio que `targetRoot/asset.json` não exista
- validar no packer que `targetRoot/asset.json` não exista, mesmo se o Studio falhar em bloquear antes

## Non-Goals

- não redesenhar o mutation preview panel inteiro
- não introduzir rename inline fora do wizard
- não adicionar batch move
- não redefinir semântica de identidade do asset
- não permitir fallback para target automático quando o usuário iniciou `Move`
- não mover diretórios diretamente pelo Studio fora do comando ao packer

## Execution Method

1. Expor `Move` na seção `Actions`.
   O botão deve existir apenas quando houver asset selecionado e deve abrir o wizard a partir do `AssetReference` atual.

2. Implementar o wizard de relocação como fluxo explícito de destino.
   O wizard deve reutilizar a linguagem já existente de `relocateWizard` e coletar:
   - root atual
   - diretório parent de destino
   - nome final do diretório
   - target root calculado

3. Adicionar validação local de destino.
   O wizard deve bloquear avanço/confirmação quando:
   - o target root for igual ao root atual;
   - o target root sair da área válida esperada;
   - o target root já contiver `asset.json`.

4. Adicionar passo final de resumo.
   Antes do comando final, o usuário deve ver um resumo do:
   - asset atual
   - root atual
   - parent de destino
   - nome final
   - target root resultante

5. Integrar o wizard ao fluxo de comando assíncrono do packer.
   A saída do wizard deve virar `PackerMutationRequest(RELOCATE_ASSET, ..., targetRoot)`, sem usar target automático.
   Depois do `OK`, o Studio inicia a operação, captura o `operationId` retornado e coloca o modal em estado de espera.

6. Esperar conclusão por evento, não por refresh cego.
   O modal deve escutar `StudioPackerOperationEvent` correlacionado por `operationId`.
   Regras:
   - `ACTION_APPLIED`: disparar refresh estrutural, fechar modal e reselecionar o asset relocado;
   - `ACTION_FAILED`: sair do spinner, manter modal aberto e mostrar a falha;
   - eventos intermediários como `PROGRESS_UPDATED` podem atualizar a mensagem/estado visual, mas não fecham o modal.

7. Endurecer a regra no packer.
   O preview/apply de relocation deve recusar destino cujo root já contenha `asset.json`, produzindo blocker claro e estável.

8. Orquestrar o pós-conclusão como mudança estrutural.
   Relocation bem-sucedida deve acionar sync estrutural explícito e reposicionar a seleção para o asset movido no novo root.

## Acceptance Criteria

- `Move` aparece na seção `Actions` do asset selecionado
- clicar em `Move` abre wizard dedicado em vez de mutação imediata
- o wizard exige destino explícito escolhido pelo usuário
- existe passo final de resumo antes da conclusão
- `targetRoot/asset.json` bloqueia o fluxo já no Studio
- o packer também bloqueia `targetRoot/asset.json` como regra de segurança
- o `OK` final envia o comando ao packer e coloca o modal em espera com spinner
- o modal só fecha depois de `ACTION_APPLIED` para a mesma operação
- falha operacional não fecha o modal silenciosamente
- sucesso operacional executa structural sync explícito
- a seleção final aponta para o asset já movido, não para o root antigo

## Validation

- unit tests para validação de target root no wizard
- unit tests para derivação de `targetRoot` a partir de parent + destination name
- unit tests para correlação `operationId -> modal state`
- unit tests para sucesso/falha dirigidos por `StudioPackerOperationEvent`
- unit tests para publication/orchestration de relocation como structural sync
- packer tests para blocker quando `targetRoot/asset.json` já existe
- smoke test de UI para:
  - abrir `Move`
  - editar destino
  - ver resumo final
  - bloquear destino inválido
  - confirmar operação
  - ver spinner de espera
  - fechar no evento de sucesso
  - manter aberto no evento de falha

## Affected Artifacts

- `docs/studio/specs/4. Assets Workspace Specification.md` se a regra de destino inválido precisar ser tornada mais explícita
- `prometeu-studio/src/main/java/p/studio/workspaces/assets/details/actions/...`
- `prometeu-studio/src/main/java/p/studio/workspaces/assets/wizards/...`
- `prometeu-studio/src/main/java/p/studio/workspaces/assets/...` mutation orchestration wiring
- `prometeu-studio/src/main/java/p/studio/events/...`
- `prometeu-studio/src/main/resources/i18n/messages.properties`
- `prometeu-packer/src/main/java/p/packer/mutations/...`
- testes de Studio para wizard/flow
- testes de packer para relocation target validation
