Files
claudetools/.claude/scripts/register-orphan-detector.ps1
Howard Enos 8b016edb9d sync: auto-sync from HOWARD-HOME at 2026-07-07 13:55:03
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-07 13:55:03
2026-07-07 13:55:32 -07:00

109 lines
4.5 KiB
PowerShell

# register-orphan-detector.ps1
# Register the "ClaudeTools - Orphaned Session Detector" scheduled task on this
# Windows machine. The task runs detect_orphaned_sessions.py, which scans the
# per-machine Claude Code transcript directory for unsaved substantive sessions,
# auto-builds banner-marked recovery logs, commits + pushes them, and posts an
# FYI to #bot-alerts.
#
# Mirrors the GrepAI watcher registration pattern in .claude/OLLAMA.md.
#
# Triggers:
# - AtLogOn (catch sessions lost since the last logon)
# - Daily, repeating every 4 hours (catch crashes during a long workday;
# 4h cadence pairs with the detector's 90-minute idle gate so an active
# session is never grabbed mid-flight)
#
# Idempotent: -Force replaces any existing task with the same name.
# This script only REGISTERS the task. It does not run the detector now.
#
# Run from an ordinary (non-admin) PowerShell:
# powershell -ExecutionPolicy Bypass -File D:\claudetools\.claude\scripts\register-orphan-detector.ps1
$ErrorActionPreference = "Stop"
$TaskName = "ClaudeTools - Orphaned Session Detector"
# Resolve the repo root portably. Prefer claudetools_root from identity.json
# (per-machine, gitignored); fall back to two levels up from this script
# (.claude/scripts/ -> repo root), resolved to a full path.
$ScriptDir = $PSScriptRoot
$FallbackRoot = (Resolve-Path (Join-Path $ScriptDir "..\..")).Path
$IdentityPath = Join-Path $FallbackRoot ".claude\identity.json"
$RepoRoot = $FallbackRoot
if (Test-Path $IdentityPath) {
try {
$identity = Get-Content -Raw -Path $IdentityPath | ConvertFrom-Json
if ($identity.claudetools_root -and (Test-Path $identity.claudetools_root)) {
$RepoRoot = (Resolve-Path $identity.claudetools_root).Path
}
} catch {
Write-Host "[WARNING] Could not parse $IdentityPath; using $FallbackRoot" -ForegroundColor Yellow
}
}
$Script = Join-Path $RepoRoot ".claude\scripts\detect_orphaned_sessions.py"
if (-not (Test-Path $Script)) {
Write-Host "[ERROR] Detector not found at $Script" -ForegroundColor Red
exit 1
}
# Resolve pythonW.exe (the GUI-subsystem Python host) so the detector runs with NO
# console window flashing on the desktop at logon / every 4h. Using py.exe or
# python.exe (console subsystem) draws a visible window each run. Prefer pythonw next
# to the active interpreter; fall back to a PATH lookup, then py.exe as a last resort.
$PyPath = $null
$PyCmd = Get-Command py -ErrorAction SilentlyContinue
if ($null -ne $PyCmd) {
try {
$exe = (& py -c "import sys;print(sys.executable)").Trim()
$wexe = Join-Path (Split-Path $exe) "pythonw.exe"
if (Test-Path $wexe) { $PyPath = $wexe }
} catch { }
}
if ($null -eq $PyPath) {
$PwCmd = Get-Command pythonw -ErrorAction SilentlyContinue
if ($null -ne $PwCmd) { $PyPath = $PwCmd.Source }
}
if ($null -eq $PyPath) {
if ($null -ne $PyCmd) { $PyPath = $PyCmd.Source } else { $PyPath = "py" }
Write-Host "[WARNING] pythonw.exe not found; task may flash a console window." -ForegroundColor Yellow
}
$Action = New-ScheduledTaskAction `
-Execute $PyPath `
-Argument "`"$Script`"" `
-WorkingDirectory $RepoRoot
# Trigger 1: at logon for the current user.
$TriggerLogon = New-ScheduledTaskTrigger -AtLogOn -User $env:USERNAME
# Trigger 2: daily at a fixed start, repeating every 4 hours all day.
$TriggerDaily = New-ScheduledTaskTrigger -Daily -At 9am
$TriggerDaily.Repetition = (New-ScheduledTaskTrigger `
-Once -At 9am `
-RepetitionInterval (New-TimeSpan -Hours 4) `
-RepetitionDuration (New-TimeSpan -Hours 24)).Repetition
$Settings = New-ScheduledTaskSettingsSet `
-ExecutionTimeLimit (New-TimeSpan -Minutes 30) `
-MultipleInstances IgnoreNew `
-StartWhenAvailable `
-DontStopOnIdleEnd `
-Hidden
Register-ScheduledTask `
-TaskName $TaskName `
-Action $Action `
-Trigger $TriggerLogon, $TriggerDaily `
-Settings $Settings `
-Description "Scans Claude Code transcripts for unsaved substantive sessions and auto-recovers them into session logs." `
-Force | Out-Null
Write-Host "[OK] Registered scheduled task '$TaskName'."
Write-Host "[INFO] Action: $PyPath `"$Script`""
Write-Host "[INFO] WorkDir: $RepoRoot"
Write-Host "[INFO] Triggers: AtLogOn ($env:USERNAME) + daily every 4h"
Write-Host "[INFO] To inspect: Get-ScheduledTask -TaskName '$TaskName' | Format-List"
Write-Host "[INFO] To run now: Start-ScheduledTask -TaskName '$TaskName'"
Write-Host "[INFO] To remove: Unregister-ScheduledTask -TaskName '$TaskName' -Confirm:`$false"