Public/New-WorkBranch.ps1

function New-WorkBranch {
    <#
    .SYNOPSIS
    Start a new working area for an isolated task, fix, or doc change.
 
    .DESCRIPTION
    New-WorkBranch creates a new working area starting from the current point and switches to it. Use it when starting a new feature, a bug fix, or a documentation pass that should not mix with the active working area.
 
    The command refuses to start a new working area when an unfinished merge, rebase, cherry-pick, revert, or bisect is in progress, or when there are unfinished conflicts. It also rejects names that are not valid working-area identifiers (spaces, control characters, leading dashes, and similar) and refuses to overwrite a working area that already exists.
 
    Each invocation writes a self-contained diagnostic log file. Successful runs log silently; failures throw a plain-English message and point at the log file with the technical detail.
 
    .PARAMETER Name
    The name of the new working area. Must be a valid identifier (no spaces, no control characters, no leading dash, etc.).
 
    .PARAMETER LogPath
    Override the directory where the diagnostic log for this run is written. Defaults to %LOCALAPPDATA%\GitEasy\Logs.
 
    .EXAMPLE
    New-WorkBranch -Name fix-readme
 
    .EXAMPLE
    Find-CodeChange; New-WorkBranch -Name docs-refresh
 
    .NOTES
    Safety:
    - Refuses to run during an unfinished merge, rebase, cherry-pick, revert, or bisect.
    - Refuses to run while there are unfinished conflicts.
    - Refuses to overwrite an existing working area.
    - Validates the name through git check-ref-format.
 
    Steps:
    1. Probe for the project folder root and start a diagnostic log session.
    2. Check that no merge, rebase, or other in-progress operation is underway.
    3. Validate the working area name format.
    4. Confirm no working area with that name already exists.
    5. Handle WhatIf and return early if applicable.
    6. Create the new working area and switch into it.
    7. Return a structured result with the new working area name.
 
    .LINK
    Switch-Work
 
    .LINK
    Find-CodeChange
 
    .LINK
    Save-Work
    #>

    [CmdletBinding(SupportsShouldProcess)]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory, Position = 0)]
        [string]$Name,

        [Parameter()]
        [string]$LogPath = ''
    )

    $repoRoot = $null
    try {
        $rootProbe = Invoke-GEGit -ArgumentList @('rev-parse', '--show-toplevel') -AllowFailure
        if ($rootProbe.ExitCode -eq 0) {
            $repoRoot = $rootProbe.Output | Select-Object -First 1
        }
    }
    catch {
        $repoRoot = $null
    }

    $session = Start-GELogSession -Command 'New-WorkBranch' -Repository ([string]$repoRoot) -LogPath $LogPath

    $userMessageOnFailure = "Could not start the new working area '$Name'."

    try {
        Assert-GESafeSave -Path ([string]$repoRoot) -LogPath $session.Path | Out-Null

        if (-not $repoRoot) {
            $rootResult = Invoke-GEGit -ArgumentList @('rev-parse', '--show-toplevel') -LogPath $session.Path
            $repoRoot = $rootResult.Output | Select-Object -First 1
        }

        $checkRef = Invoke-GEGit -ArgumentList @('check-ref-format', '--branch', $Name) -WorkingDirectory $repoRoot -LogPath $session.Path -AllowFailure
        if ($checkRef.ExitCode -ne 0) {
            throw "'$Name' is not a valid working-area name. Use letters, digits, dashes, slashes, underscores, and dots."
        }

        $existCheck = Invoke-GEGit -ArgumentList @('rev-parse', '--verify', '--quiet', "refs/heads/$Name") -WorkingDirectory $repoRoot -LogPath $session.Path -AllowFailure
        if ($existCheck.ExitCode -eq 0) {
            throw "A working area named '$Name' already exists. Use Switch-Work to move into it, or pick a different name."
        }

        if (-not $PSCmdlet.ShouldProcess($repoRoot, "Create working area '$Name'")) {
            Complete-GELogSession -Path $session.Path -Outcome 'SUCCESS' -UserMessage 'Skipped (WhatIf).'
            return
        }

        Invoke-GEGit -ArgumentList @('checkout', '-b', $Name) -WorkingDirectory $repoRoot -LogPath $session.Path | Out-Null

        Write-Host "Started new working area '$Name'."

        $result = [PSCustomObject]@{
            Repository = $repoRoot
            Branch     = $Name
            Message    = "Working area '$Name' created and active."
        }

        Complete-GELogSession -Path $session.Path -Outcome 'SUCCESS'
        return $result
    }
    catch {
        $err = $_

        $innerMessage = $err.Exception.Message
        if ($innerMessage -like 'git *') {
            $finalMsg = $userMessageOnFailure
        }
        else {
            $finalMsg = $innerMessage
        }

        Complete-GELogSession -Path $session.Path -Outcome 'FAILURE' -UserMessage $finalMsg -ErrorMessage $innerMessage

        throw "$finalMsg Details: $($session.Path)"
    }
}