#Requires -Version 5.1 <# .SYNOPSIS Bookworm Smart Assistant v6.6-rc2 Agent 信任边界体系一键回滚 .DESCRIPTION 代号: v6.6-rc2-20260422-1859 按分级回滚 P3 → P2 → P1 → P0 各阶段,最终重签 HMAC 完整性链。 数据文件 (logs/agent-returns.jsonl, state/claim-mismatches.jsonl) 不删除,保留审计。 Linux/WSL 用户: 逐步等价 bash 版待 port。核心动作参见每步注释的 bash 等价。 .PARAMETER Scope 回滚范围: all -- 全量回滚到 v6.5.1 (默认) P3-only -- 仅移除 agent-claim-cross-verify.js P2-down -- 移除 P3 + Dashboard + 诚实度统计 P1-down -- 移除 P3 + P2 + verifier + snapshot-taker (保留 P0 观察) .PARAMETER DryRun 预演模式: 只打印 "将移除 / 将恢复" 提示, 不实际执行任何删除/写入, 不调用 integrity-check --generate, 不追加 evolution-log. 真回滚前强烈建议先跑一次 -DryRun 审视预期动作。 .EXAMPLE pwsh .\rollback-v6.6-rc2.ps1 pwsh .\rollback-v6.6-rc2.ps1 -Scope P3-only pwsh .\rollback-v6.6-rc2.ps1 -DryRun # 预演全量回滚 pwsh .\rollback-v6.6-rc2.ps1 -Scope P1-down -DryRun .NOTES 每一步都是幂等的 (Test-Path 先查再删)。多次运行无副作用。 成功执行后 evolution-log.jsonl 追加一条 rollback 事件。 #> param( [ValidateSet('all','P3-only','P2-down','P1-down')] [string]$Scope = 'all', [switch]$DryRun ) $ErrorActionPreference = 'Stop' $CLAUDE_ROOT = Join-Path $env:USERPROFILE '.claude' $HOOKS = Join-Path $CLAUDE_ROOT 'hooks' $SCRIPTS = Join-Path $CLAUDE_ROOT 'scripts' $STATE = Join-Path $CLAUDE_ROOT 'state' $CONFIG = Join-Path $CLAUDE_ROOT 'config' $CONSTITUTION = Join-Path $CLAUDE_ROOT 'constitution\anti-arrogance.md' $SETTINGS = Join-Path $CLAUDE_ROOT 'settings.json' $EVOLUTION = Join-Path $CLAUDE_ROOT 'debug\evolution-log.jsonl' $CODE = 'v6.6-rc2-20260422-1859' function Write-Step { param([string]$Msg) Write-Host "[rollback] $Msg" -ForegroundColor Cyan } function Remove-IfExists { param([string]$Path, [string]$Tag) if (Test-Path -LiteralPath $Path) { if ($script:DryRun) { Write-Step "$Tag [DRY-RUN] 将移除: $Path" } else { Remove-Item -LiteralPath $Path -Force Write-Step "$Tag 已移除: $Path" } } else { Write-Step "$Tag 不存在 (跳过): $Path" } } function Restore-LatestBak { param([string]$Target, [string]$BakPrefix, [string]$Tag) $dir = Split-Path $Target -Parent $name = Split-Path $Target -Leaf $pattern = "$name.$BakPrefix*" $bak = Get-ChildItem -LiteralPath $dir -Filter $pattern -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -First 1 if ($bak) { if ($script:DryRun) { Write-Step "$Tag [DRY-RUN] 将从 $($bak.Name) 恢复" } else { Copy-Item -LiteralPath $bak.FullName -Destination $Target -Force Write-Step "$Tag 已从 $($bak.Name) 恢复" } } else { Write-Step "$Tag 未找到 $pattern 备份 (可能未曾应用该阶段)" } } # Scope → 各阶段是否执行 (PowerShell 无 goto, 用标志位分级控制流) $runP3 = $true $runP2 = ($Scope -ne 'P3-only') $runP1 = ($Scope -notin @('P3-only','P2-down')) $runP0 = ($Scope -eq 'all') $modeTag = if ($DryRun) { ' [DRY-RUN 预演模式]' } else { '' } Write-Host "============================================================" -ForegroundColor Yellow Write-Host " Bookworm v6.6-rc2 回滚$modeTag · Scope=$Scope" -ForegroundColor Yellow Write-Host " 阶段执行: P3=$runP3 P2=$runP2 P1=$runP1 P0=$runP0" -ForegroundColor Yellow Write-Host "============================================================" -ForegroundColor Yellow # ------------------------------------------------------------------ # P3 层 (T12) # ------------------------------------------------------------------ if ($runP3) { Write-Step '--- Phase P3 ---' # bash: rm -f $CLAUDE_ROOT/hooks/agent-claim-cross-verify.js Remove-IfExists (Join-Path $HOOKS 'agent-claim-cross-verify.js') '[T12]' Remove-IfExists (Join-Path $CONFIG 'cross-verify-budget.json') '[T12]' } # ------------------------------------------------------------------ # P2 层 (T09, T10, T11) # ------------------------------------------------------------------ if ($runP2) { Write-Step '--- Phase P2 ---' Remove-IfExists (Join-Path $HOOKS 'agent-honesty-stats.js') '[T09]' Remove-IfExists (Join-Path $CLAUDE_ROOT 'dashboard\agent-honesty.html') '[T11]' # T10 对 daily-health-snapshot.js 是扩展, 走 sentinel 撤销 (待 T10 补丁填充 undo 段) Write-Step '[T10] TODO: 调用 scripts/patches/v6.6-rc2-04-health-snapshot-ext.js --undo (T10 落地后填充)' Remove-IfExists (Join-Path $CONFIG 'health-weights.json') '[T09/T10 参数]' } # ------------------------------------------------------------------ # P1 层 (T05, T06, T07, T08) # ------------------------------------------------------------------ if ($runP1) { Write-Step '--- Phase P1 ---' Remove-IfExists (Join-Path $HOOKS 'agent-claim-verifier.js') '[T07]' Remove-IfExists (Join-Path $HOOKS 'agent-snapshot-taker.js') '[T06]' # T05 对 subagent-route-injector.js 追加契约模板, 回滚到 P0 版本 Restore-LatestBak (Join-Path $HOOKS 'subagent-route-injector.js') 'bak.v6.6-rc2-03-claim-contract' '[T05]' } # ------------------------------------------------------------------ # P0 层 (T02, T03, T04) # ------------------------------------------------------------------ if ($runP0) { Write-Step '--- Phase P0 ---' # T02: 卸载 agent-claim-observer.js + 撤销 SubagentStop 挂载 Remove-IfExists (Join-Path $HOOKS 'agent-claim-observer.js') '[T02 hook]' Restore-LatestBak $SETTINGS 'bak.v6.6-rc2-01-register-subagent-stop' '[T02 settings]' # T03: subagent-route-injector 恢复 v5.2 版本 (P0 traceId 注入) Restore-LatestBak (Join-Path $HOOKS 'subagent-route-injector.js') 'bak.v6.6-rc2-02-inject-traceid' '[T03]' # T04: 宪法追加段删除 + log-rotator 配置回退 Write-Step '[T04] 宪法 sentinel 段删除:' if (Test-Path -LiteralPath $CONSTITUTION) { $text = Get-Content -LiteralPath $CONSTITUTION -Raw -Encoding UTF8 $pattern = '(?s).*?' if ($text -match $pattern) { if ($DryRun) { Write-Step ' [DRY-RUN] 将移除 sentinel 段 (原子写)' } else { $cleaned = [regex]::Replace($text, $pattern, '').TrimEnd() + "`n" # 原子写 $tmp = "$CONSTITUTION.tmp.rollback.$PID" [IO.File]::WriteAllText($tmp, $cleaned, [Text.UTF8Encoding]::new($false)) Move-Item -LiteralPath $tmp -Destination $CONSTITUTION -Force Write-Step ' sentinel 段已移除 (原子写)' } } else { Write-Step ' sentinel 段不存在 (跳过)' } } Restore-LatestBak (Join-Path $HOOKS 'log-rotator.js') 'bak.v6.6-rc2-04-log-rotator' '[T04]' # 数据文件 保留审计 (原 prompt 第 8 条: 保留 logs/ 和 state/ 数据) Write-Step 'logs/agent-returns.jsonl 和 state/claim-mismatches.jsonl 按审计要求保留' } # ------------------------------------------------------------------ # 最后: HMAC 完整性链重签 (所有 scope 都执行) # ------------------------------------------------------------------ Write-Step '--- Reseal HMAC ---' if ($DryRun) { Write-Step '[DRY-RUN] 将调用: node hooks/integrity-check.js --generate' Write-Step '[DRY-RUN] 将追加 evolution-log.jsonl rollback 事件' } else { # bash: node $CLAUDE_ROOT/hooks/integrity-check.js --generate & node (Join-Path $HOOKS 'integrity-check.js') --generate if ($LASTEXITCODE -ne 0) { throw "integrity-check --generate 失败, exit=$LASTEXITCODE" } # 追加 evolution-log try { $entry = @{ ts = (Get-Date).ToString('o') event = 'rollback' code = $CODE scope = $Scope operator = "$env:USERNAME@$env:COMPUTERNAME" } | ConvertTo-Json -Compress Add-Content -LiteralPath $EVOLUTION -Value $entry -Encoding UTF8 Write-Step 'evolution-log.jsonl 已追加 rollback 事件' } catch { Write-Step "evolution-log 追加失败 (非阻塞): $_" } } $finishTag = if ($DryRun) { '预演完成 (未实际变更)' } else { '回滚完成' } Write-Host '' Write-Host '============================================================' -ForegroundColor Green Write-Host " $finishTag · Scope=$Scope" -ForegroundColor Green if (-not $DryRun) { Write-Host " 下一步验证: node $HOOKS\integrity-check.js (PostToolUse 模拟)" -ForegroundColor Green } Write-Host '============================================================' -ForegroundColor Green