发布:常驻文档按现行形态重写 + 作业规矩/01 先并后删

一、常驻机制文档 references/supervise-persistence.md(整份重写 410→469 行)
- 照抄段由废弃的 start-supervise.ps1 形态,改为现行形态:
  计划任务 collabd-keepalive-<区>(每 5 分钟)→ pythonw.exe → supervise-launch.py → collabd.py --supervise
- 旧 ps1 形态整体降级为「§四 旧形态留痕」(逐条标 🟠,内容一字未删,供读老日志/老进程用)
- 判据订正:LastTaskResult 在长驻运行中是 267009(旧口径「必须 0」属"跑一次就退"时代,已作废);
  BOM 那条随 ps1 形态一并降为历史;另两条仍有效(CODEBUDDY_CONFIG_DIR 空库 / WorkingDirectory 必须是工作区根)
- 删除 assets/start-supervise.ps1.tpl —— SKILL.md、manifest.md、collabd.py、selftest.py 四处早已按「该模板已删除」口径,本次把磁盘与文档对齐

二、references/作业规矩/01 先并后删(用户选定 A 方案:不丢内容 + 只剩一处)
- 判据类并入 references/02-功能优先协作协议.md:
  §3.2 补「规则冲突裁决顺序」「冲突 ≠ 门禁」;§3.3 补回完整语言转换表(原处"已收敛到通用技能"在并包后成了悬空指针);
  §5.3 铁律由五条补到六条 + 接上配套硬红线「只做正向迭代」;新增 §5.5「提报前必答三问 + 回话前自检」
- 排版类并入 references/03-回复排版-核心块.md 的「完整版」段(十四条反模式 / 骨架路由表 / 文案点名主体 / 文档直入主题)
  该段放在 REPLY-CORE 标记之外 ⇒ 每轮注入块逐字未变(实测仍 1172 字符)
- 删除 references/作业规矩/01-协作与提报用户判据.md,并跟改 6 处引用(SKILL.md 第一屏表、作业规矩/00 索引表与两处指针、
  作业规矩/03-多棒接力编排、00 的 frontmatter 变更记录)——含一处二级指针「见 §6 第 0 条」,已改指 03 完整版段

三、判据与卫生
- pitfalls.md:P0-74 去冗余(7107 → 5982 B,重复叙述合并),「沉淀纪律」由 FAIL 1 转绿
- install.py:manifest_files() 补排 logs/ —— 与它自己「运行日志不入表」的口径一致,否则跑一次钩子表就过期
- .gitignore:补 logs/;撤跟踪 logs/_dr_probe.json(钩子输出转储,全包零引用)
- references/manifest.md 用生成器重算:66 份文件,语法失败 0

验收读数:selftest.py rc=0 PASS 99 / FAIL 0(另 1 条报告型不计入);
session-rules-check.py fail 0 / warn 1("此刻无活会话",正常态)/ ok 13;改动文件行尾全 LF。
This commit is contained in:
admin committed 2026-10-07 00:32:47 +08:00
1 parent 9fd120f40b
commit e5dfb6e4ef
14 files changed
+456 -721

No files matched your search

@@ -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) }
}