#!/usr/bin/env node /** * R6 H4-3 现场演示:失败 → watchdog 有界自动重试 → 纠偏/成功(真实 LLM 编排)。 * 通过 GW_TEAM_FAIL_ONCE=first-cli 让第一个外部 CLI 子任务的第 1 次尝试确定性失败, * 引擎 watchdog 记录 auto-retry(injected:true)并退避重试,后续尝试成功。 * 结束校验:①watchdog.json 含 injected 自动重试 ②该子任务 attempts≥2(先 dead 后 done) * ③整体无 dead 子任务(评审若打回则走 correction 纠偏,同样计入证据)。EXIT=0 闭环。 */ import { readFileSync } from "node:fs"; import { resolve, dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { TeamOrchestrator } from "../src/team/orchestrate.js"; const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), ".."); const GOAL = [ "用 Node.js(零第三方依赖)做一个 Markdown 词频统计命令行小工具,团队分工完成三件事:", "①编写可运行的实现脚本 wordcount.mjs:读取 .md 文件,按词统计中文/英文词频,支持 --top=N 参数输出前 N 个高频词,并能对 samples 目录里的样例真实跑出结果;", "②编写 README.md:含功能说明、用法示例(node wordcount.mjs --top=5 samples/sample.txt)、输出格式说明;", "③准备 samples/sample.txt:一份用于演示的 Markdown 样例文本(含若干重复词)。", ].join(""); const runId = `run-watchdog-${Date.now().toString(36)}`; process.env.GW_TEAM_FAIL_ONCE = "first-cli"; process.env.GW_INJECT_RUN_ID = runId; const orch = new TeamOrchestrator({ root: ROOT }); const t0 = Date.now(); const result = await orch.run(GOAL, { runId }); const wall = Date.now() - t0; const evDir = resolve(ROOT, "evidence", "team-orch", runId); const watchdog = JSON.parse(readFileSync(join(evDir, "watchdog.json"), "utf8")); const injectedRetries = watchdog.filter((w) => w.type === "auto-retry" && w.injected); const retriedSub = result.executions.find((e) => e.attempts.length >= 2 && e.attempts.some((a) => a.state === "dead") && e.state === "done"); const problems = []; if (!injectedRetries.length) problems.push("watchdog.json 未记录 injected:true 的 auto-retry"); if (!retriedSub) problems.push("没有子任务呈现『首次失败→重试成功』(attempts 先 dead 后 done)"); if (result.deadSubtasks.length) problems.push(`仍有 dead 子任务:${JSON.stringify(result.deadSubtasks)}`); console.log("\n===== watchdog-demo 验收 ====="); console.log(`runId=${runId} verdict=${result.verdict}/${result.finalScore} 耗时=${wall}ms`); console.log(`watchdog 事件:${watchdog.map((w) => w.type + (w.subtaskId ? "@" + w.subtaskId : "") + (w.injected ? "(注入)" : "")).join(",") || "无"}`); if (retriedSub) console.log(`重试子任务 ${retriedSub.subtaskId}:attempts=${retriedSub.attempts.map((a) => a.state).join("→")}`); console.log(`评审轮次=${result.reviewSummary?.reviewRounds} 纠偏=${result.reviewSummary?.corrections} 自动重试=${result.reviewSummary?.autoRetries}`); if (problems.length) { console.error("[watchdog-demo] 未闭环:\n - " + problems.join("\n - ")); process.exit(2); } console.log("[watchdog-demo] 闭环成功 EXIT=0(失败→自动重试→成功,证据齐全)"); process.exit(0);