feat(worktrees): création intelligente (auto) + commit/push/promotion + grille agrandissable

- addWorktree résout la branche par dépôt (branchExists) : checkout si présente, suivi de origin/<b> si seulement remote, sinon création (-b) depuis la branche par défaut. Corrige le 'fatal: invalid reference' sur les groupes hétérogènes ; newBranch -> mode (déprécié, mappé en route).
- Nouvelles opérations git : commit (add -A), push (upstream auto), promotion « en principal » (la branche du worktree devient le checkout principal, sans merge ni conflit, ancienne branche conservée). Routes /worktrees/{commit,push,promote} auditées + GET /repos/:id/branches.
- Web : actions Commit/Push/Promouvoir sur WorktreeCard, sélecteur de branche de base (datalist) dans RepoSection et GroupSessionModal, agrandissement d'un terminal au choix dans TerminalGrid.
- Court-circuite la session de groupe quand aucun worktree n'a pu être créé (fini le masquage par « no resolvable worktree »).
- Tests : git.ts (branchExists/listBranches/commitAll/auto), worktree-manager (commit/promote/branches) ; acceptance P5 étend le scénario worktree de groupe sur branche neuve + commit + promotion.
This commit is contained in:
2026-06-22 19:55:45 +02:00
parent e84c6a7f6d
commit f4fb6c3b52
18 changed files with 732 additions and 62 deletions

View File

@@ -12,6 +12,14 @@
{{ t('groups.spanBadge', spannedCount) }}
</span>
<span class="ml-auto shrink-0 font-mono text-[11px] text-zinc-500">{{ session.command }}</span>
<button
class="shrink-0 rounded p-0.5 text-zinc-500 transition-colors hover:text-zinc-200"
:aria-label="maximized ? t('terminal.restore') : t('terminal.maximize')"
:title="maximized ? t('terminal.restore') : t('terminal.maximize')"
@click="emit('toggle-maximize')"
>
<component :is="maximized ? Minimize2 : Maximize2" class="h-3.5 w-3.5" />
</button>
</header>
<DialogPrompt v-if="isWaiting" :session="session" class="px-2 pt-2" />
<div class="min-h-0 flex-1">
@@ -23,13 +31,15 @@
<script setup lang="ts">
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { Maximize2, Minimize2 } from '@lucide/vue';
import type { SessionSummary } from '@arboretum/shared';
import { useWorktreesStore } from '../stores/worktrees';
import SessionStateBadge from './SessionStateBadge.vue';
import DialogPrompt from './DialogPrompt.vue';
import TerminalView from './TerminalView.vue';
const props = defineProps<{ session: SessionSummary }>();
const props = defineProps<{ session: SessionSummary; maximized?: boolean }>();
const emit = defineEmits<{ 'toggle-maximize': [] }>();
const worktrees = useWorktreesStore();
const { t } = useI18n();