"""Per-task git worktree provisioning.

Every okstra task — regardless of task-type/phase — runs inside an
isolated git worktree rooted at
`~/.okstra/worktrees/<project_id>/<task_group>/<task_id>/`. The same
worktree is reused across all phases of one task-key (requirements-
discovery → error-analysis → implementation-option-selection →
implementation-planning → implementation), so phase N picks up exactly
the working-tree state phase N-1 left behind.

A global registry (`worktree_registry.py`) maps task-keys to the
on-disk path + branch and serialises reservations, so two concurrent
okstra runs cannot collide on the same path or branch name.

Pre-conditions handled here:
  - Skip when `project_root` is not a git repo (degrade gracefully).
  - Skip when `project_root` itself is already a non-main worktree
    (caller's tree is already an isolated workspace; reuse it).
  - Re-entry of the same task-key returns the existing worktree.
  - Branch / path collisions across task-keys raise PrepareError-like
    RuntimeError.

Side effects:
  - `git worktree add -b <branch> <path> <base_ref>` invoked in the
    main worktree of `project_root` (NOT `project_root` itself when it
    is also a worktree — base must be the main checkout).
  - Per-task sync dirs (.project-docs, .scratch, graphify-out by
    default) symlinked from the **main worktree** into the new
    worktree so every task sees the same shared state, irrespective of
    which worktree the caller invoked okstra from.
  - The function does NOT chdir.

구현은 여섯 층으로 나뉜다. 바닥의 세 층 — `naming`(문자열 계산),
`sync_config`(무엇을 옮길지), `git_ops`(git 사실) — 은 서로를 모른다. 그 위에
`cleanliness`(무엇이 더러운가) · `linking`(실제로 링크 걸기) ·
`decisions`(무엇이 일어날지 미리 답하기)가 있고, 부수 효과를 내는 것은
`provision` 하나뿐이다. 이 파일은 밖으로 나가는 이름만 모아 둔다.
"""
from __future__ import annotations

from .cleanliness import (
    dirty_entries_excluding_okstra,
    is_dirty_excluding_okstra,
    nested_worktree_excludes,
    okstra_clean_gate_excludes,
)
from .decisions import (
    StageWorktreeDecision,
    WorktreeDecision,
    preview_worktree_decision,
    resolve_stage_worktree_decision,
)
from .git_ops import (
    MergeError,
    _git,
    _resolve_commit_sha,
    is_ancestor,
    is_git_work_tree,
    main_worktree_path,
    merge_branch,
    move_worktree,
    remove_worktree_force,
)
from .naming import compute_branch_name, compute_worktree_path
from .provision import (
    WorktreeProvision,
    provision_stage_worktree,
    provision_task_worktree,
)

__all__ = [
    "MergeError",
    "StageWorktreeDecision",
    "WorktreeDecision",
    "WorktreeProvision",
    "_git",
    "_resolve_commit_sha",
    "compute_branch_name",
    "compute_worktree_path",
    "dirty_entries_excluding_okstra",
    "is_ancestor",
    "is_dirty_excluding_okstra",
    "is_git_work_tree",
    "main_worktree_path",
    "merge_branch",
    "nested_worktree_excludes",
    "okstra_clean_gate_excludes",
    "preview_worktree_decision",
    "provision_stage_worktree",
    "provision_task_worktree",
    "move_worktree",
    "remove_worktree_force",
    "resolve_stage_worktree_decision",
]
