public/Invoke-OctaTaskBrowser.ps1

function Invoke-OctaTaskBrowser {
    <#
        .SYNOPSIS
        Lists scheduled tasks and can enable/disable/run/stop/delete one by TaskPath\TaskName.
        FR-044. Enable/disable reuse the same snapshot + Run Record mechanism as
        Invoke-OctaStartupManager - Undo-OctaRun needs no changes.
    #>

    [CmdletBinding()]
    param(
        [string]$Enable,
        [string]$Disable,
        [string]$Run,
        [string]$Stop,
        [string]$Delete,
        [switch]$Yes
    )

    function Split-OctaTaskFullName {
        param([string]$FullName)
        $lastSlash = $FullName.LastIndexOf('\')
        # A name with no backslash at all (user typed just "MyTask") has no path component -
        # LastIndexOf returns -1, which used to yield TaskPath = '' and a confusing downstream
        # failure. Default to the root task path, which is where such a task would actually live.
        if ($lastSlash -lt 0) {
            return @{ TaskPath = '\'; TaskName = $FullName }
        }
        return @{
            TaskPath = $FullName.Substring(0, $lastSlash + 1)
            TaskName = $FullName.Substring($lastSlash + 1)
        }
    }

    function Test-OctaTaskExists {
        param([hashtable]$Parts)
        return [bool](Get-ScheduledTask -TaskPath $Parts.TaskPath -TaskName $Parts.TaskName -ErrorAction SilentlyContinue)
    }

    if (-not ($Enable -or $Disable -or $Run -or $Stop -or $Delete)) {
        $tasks = @(Get-ScheduledTask -ErrorAction SilentlyContinue)
        foreach ($t in $tasks) {
            Write-Host ("{0,-10} {1}{2}" -f $t.State, $t.TaskPath, $t.TaskName)
        }
        return $tasks
    }

    if ($Enable -or $Disable) {
        $fullName = if ($Enable) { $Enable } else { $Disable }
        $parts = Split-OctaTaskFullName -FullName $fullName
        # ponytail: check the task actually exists BEFORE doing anything. Enable/Disable-ScheduledTask
        # only raise a non-terminating error for an unknown task, so this used to create a run
        # folder, write a Run Record with a null snapshot, and return Status = 'Success' for a task
        # that was never touched (verified: '\NoExiste\TareaFantasma123' reported Success).
        if (-not (Test-OctaTaskExists -Parts $parts)) {
            return [pscustomobject]@{ Status = 'NotFound'; Message = "Scheduled task not found: $fullName" }
        }

        # ponytail: named $runFolder, NOT $run - PowerShell variable names are case-insensitive,
        # so the old `$run = New-OctaRunFolder` silently overwrote this function's own [string]$Run
        # parameter with a folder object. Harmless only because this branch returns before the
        # `if ($Run)` block below ever reads it; renaming removes the landmine entirely.
        $runFolder = New-OctaRunFolder
        $snapshot = Save-OctaActionSnapshot -Action (New-OctaAction -TargetType ScheduledTask -TargetIdentifier "$($parts.TaskPath)|$($parts.TaskName)" -CurrentValue 'n/a' -PlannedValue 'n/a') -RunFolder $runFolder.Path

        try {
            if ($Enable) {
                Enable-ScheduledTask -TaskPath $parts.TaskPath -TaskName $parts.TaskName -ErrorAction Stop | Out-Null
            }
            else {
                Disable-ScheduledTask -TaskPath $parts.TaskPath -TaskName $parts.TaskName -ErrorAction Stop | Out-Null
            }
        }
        catch {
            return [pscustomobject]@{ Status = 'Error'; Message = $_.Exception.Message }
        }

        Save-OctaRunRecord -RunFolder $runFolder.Path -RunRecord ([pscustomobject]@{
                RunId                      = $runFolder.RunId
                Timestamp                  = (Get-Date).ToString('o')
                CategoriesApplied          = @('task-browser')
                RestorePointStatus         = 'NotAttempted'
                RestorePointSequenceNumber = $null
                ActionSnapshots            = @($snapshot)
                IrreversibleActionRefs     = @()
                Status                     = 'Completed'
            })
        return [pscustomobject]@{ Status = 'Success'; RunId = $runFolder.RunId }
    }

    if ($Run) {
        $parts = Split-OctaTaskFullName -FullName $Run
        if (-not (Test-OctaTaskExists -Parts $parts)) {
            return [pscustomobject]@{ Status = 'NotFound'; Message = "Scheduled task not found: $Run" }
        }
        try { Start-ScheduledTask -TaskPath $parts.TaskPath -TaskName $parts.TaskName -ErrorAction Stop }
        catch { return [pscustomobject]@{ Status = 'Error'; Message = $_.Exception.Message } }
        return [pscustomobject]@{ Status = 'Success'; Message = "Started $Run" }
    }

    if ($Stop) {
        $parts = Split-OctaTaskFullName -FullName $Stop
        if (-not (Test-OctaTaskExists -Parts $parts)) {
            return [pscustomobject]@{ Status = 'NotFound'; Message = "Scheduled task not found: $Stop" }
        }
        try { Stop-ScheduledTask -TaskPath $parts.TaskPath -TaskName $parts.TaskName -ErrorAction Stop }
        catch { return [pscustomobject]@{ Status = 'Error'; Message = $_.Exception.Message } }
        return [pscustomobject]@{ Status = 'Success'; Message = "Stopped $Stop" }
    }

    if ($Delete) {
        $parts = Split-OctaTaskFullName -FullName $Delete
        # Checked before prompting, so the user is never asked to confirm deleting something
        # that isn't there.
        if (-not (Test-OctaTaskExists -Parts $parts)) {
            return [pscustomobject]@{ Status = 'NotFound'; Message = "Scheduled task not found: $Delete" }
        }
        Write-Host "Deleting a scheduled task is irreversible (no snapshot can re-create its definition)."
        if (-not $Yes) {
            $response = Read-Host "Delete $Delete ? (y/N)"
            if ($response -notin @('y', 'Y', 's', 'S')) {
                return [pscustomobject]@{ Status = 'Cancelled' }
            }
        }
        try { Unregister-ScheduledTask -TaskPath $parts.TaskPath -TaskName $parts.TaskName -Confirm:$false -ErrorAction Stop }
        catch { return [pscustomobject]@{ Status = 'Error'; Message = $_.Exception.Message } }
        return [pscustomobject]@{ Status = 'Success'; Message = "Deleted $Delete" }
    }
}