diff --git a/session-mechanism/assets/start-supervise.ps1.tpl b/session-mechanism/assets/start-supervise.ps1.tpl deleted file mode 100644 index c06a740..0000000 --- a/session-mechanism/assets/start-supervise.ps1.tpl +++ /dev/null @@ -1,132 +0,0 @@ -# collabd supervisor keeper -- NEVER returns on purpose. -# -# 🔴🔴 2026-10-04 修:首行原本多打了三个双引号(即「三连双引号 + #」开头, -# 把整份 `.ps1` 变成了「Python 看着合法、PowerShell 看着语法错」的畸形文件 -# ⇒ 生成物被 PowerShell 判定 9 处语法错、**一秒内秒退** ⇒ 常驻彻底没人续命。 -# ⛔ 这个文件是 **PowerShell**(不是 Python)⇒ 注释一律用 `#`,⛔ 不要三引号。 -# -# ⚙️ 本文件由 `init_workspace.py` **按工作区变量自动生成**(⛔ 请勿手改:要改改模板 + 重跑脚本)。 -# 生成时间:__STAMP__ -# 适用工作区:__WS__ -# -# Why this file exists(⛔ 下面几条是踩出来的,⛔ 别"简化"掉): -# ① 计划任务**只在任务失败(非零退出)时重启**。早前版本末尾直接前台调 pythonw, -# pythonw 死掉后脚本返回 0 ⇒ 任务被判"成功"⇒ RestartCount=999 永不触发 -# ⇒ **常驻死了就永远死着**。⇒ **重启逻辑必须住在脚本里**。 -# ② ⛔ **绝不能用 `& $pyw ...`** 起常驻:pythonw 是 GUI 子系统程序,PowerShell 的 -# 调用运算符**不阻塞**它 ⇒ 立刻返回 ⇒ 脚本以为"collabd 退出了"⇒ 每几秒就重拉 -# ⇒ **叠出一堆重复常驻**。⇒ 用 `Start-Process -Wait`(真阻塞)。 -# ③ **存活判据=心跳,不是退出码**:collabd 发现有活的常驻时会**故意 exit 0**(幂等), -# 那个 0 退出**绝不能**触发重拉风暴。 -# ④ UTF-8 **带 BOM**(⛔ 不带 ⇒ PowerShell 5.1 按 ANSI/GBK 解码 ⇒ CJK 路径被毁 -# ⇒ 任务一秒内 Result=1 退出)。 - -$ErrorActionPreference = "Continue" - -$env:CODEBUDDY_CONFIG_DIR = "__CFGDIR__" -$env:COLLABD_CONFIG = "__COLLABDCFG__" -$env:PYTHONIOENCODING = "utf-8" -$env:PYTHONUNBUFFERED = "1" # stdout 重定向到文件,Python 会块缓冲 ⇒ 不设它诊断全压在 4KB 之后 - -$root = "__WS__" -$pyw = "__PYW__" -$script = "__SCRIPT__" -$hbPath = "__HBPATH__" -$logPath = "__LOG__" -$stampPath = "__STAMP__" -# 🔴 停止标志:机制侧 `--set-life 已完成` ⇒ 写它 ⇒ 常驻优雅退出。 -# ⚠️ 改前缺陷:keeper 不知道它 ⇒ 目标收口后**每 60 秒重拉一次、每次秒退** -# (实测**空转 370 次/6 小时**)⇒ "完成即收工"只做到"停掉常驻", -# ⛔ **没做到"别再拉它起来"** —— 那是同一件事的两半。 -$stopFlag = "__STOPFLAG__" - -$staleSec = 90 # 与 collabd.supervise_alive() 同一陈旧阈值 -Set-Location $root - -function Say([string]$m) { - $ts = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") - Add-Content -LiteralPath $logPath -Value ("[" + $ts + "] " + $m) -Encoding UTF8 -} - -function Get-HbAge { - try { - if (-not (Test-Path -LiteralPath $hbPath)) { return -1 } - $raw = Get-Content -LiteralPath $hbPath -Raw -Encoding UTF8 - if (-not $raw) { return -1 } - $ts = [double](($raw | ConvertFrom-Json).ts) - if ($ts -le 0) { return -1 } - return [int]((Get-Date).ToString("U") - $ts) - } catch { return -1 } -} - -function Wait-HeartbeatFresh([int]$maxWait) { - $waited = 0 - while ($waited -lt $maxWait) { - $age = Get-HbAge - if ($age -ge 0 -and $age -lt $staleSec) { - Say ("another supervisor is alive (heartbeat " + $age + "s old) => standing down") - return $true - } - Start-Sleep -Seconds 5 - $waited += 5 - } - return $false -} - -Say ("keeper up. keeper_pid=" + $PID + " script=" + $script) - -$backoff = 5 -while ($true) { - # ① 循环开头:目标已完成 ⇒ 收工,不再重拉 - if (Test-Path -LiteralPath $stopFlag) { - Say "guard.stop present => target finished; keeper stands down (no more respawn)" - exit 0 - } - $ageBefore = Get-HbAge - if ($ageBefore -ge 0 -and $ageBefore -lt $staleSec) { - if (Wait-HeartbeatFresh 300) { continue } - } - - Say ("spawn collabd --supervise (backoff=" + $backoff + "s)") - $outLog = "__OUTLOG__" - $errLog = "__ERRLOG__" - try { - # -Wait 给的是**真阻塞**(`&` 给不了 GUI 子系统程序);-Redirect* 让证据落盘 - $proc = Start-Process -FilePath $pyw ` - -ArgumentList @("-u", $script, "--supervise") ` - -WorkingDirectory $root ` - -WindowStyle Hidden ` - -RedirectStandardOutput $outLog ` - -RedirectStandardError $errLog ` - -PassThru -Wait - $code = $proc.ExitCode - } catch { - Say ("spawn threw: " + $_.Exception.Message + " => retry in " + $backoff + "s") - Start-Sleep -Seconds $backoff - if ($backoff -lt 60) { $backoff = [Math]::Min(60, $backoff * 2) } - continue - } - - $ageAfter = Get-HbAge - if ($ageAfter -ge 0 -and $ageAfter -lt $staleSec) { - $verdict = "heartbeat still fresh (" + $ageAfter + "s) => idle exit, no respawn yet" - } elseif ($ageAfter -ge 0) { - $verdict = "heartbeat stale (" + $ageAfter + "s) => supervisor really died" - } else { - $verdict = "heartbeat unreadable" - } - Say ("collabd exited (exit=" + $code + ", " + $verdict + ")") - Set-Content -LiteralPath $stampPath -Value ((Get-Date).ToString("yyyy-MM-dd HH:mm:ss")) -Encoding UTF8 - - # ② 退避**期间**标志可能出现 ⇒ 别再睡满一轮(⛔ 漏这里 ⇒ 收工后还会多拉一次) - $waitLeft = $backoff - while ($waitLeft -gt 0) { - if (Test-Path -LiteralPath $stopFlag) { - Say "guard.stop appeared during backoff => keeper stands down early" - exit 0 - } - Start-Sleep -Seconds 5 - $waitLeft -= 5 - } - if ($backoff -lt 60) { $backoff = [Math]::Min(60, $backoff * 2) } -}