Away run(无人值守运行)
操作员离开;队列得到处理。每个项目都在一个全新的无头进程中运行,因此一次使用限制或崩溃只消耗一次迭代,而不是整个夜晚。状态保存在运行文件夹的磁盘上;进程退出替代 /clear。claude -p 的标志事实位于 headless-claude 技能中。
仓库配置和配置文件。 <repo>/.claude/project-workflow.json 是可选的;该技能读取其键:projects_dir(默认 my-projects)、profile(默认 <projects_dir>/WORKFLOW.md)、backlog_file(默认 <projects_dir>/backlog.md)和 bootstrap(一个 argv 列表,或 null)。如果文件存在,则读取配置文件的 § Away run 部分:测试命令、发现来源、自动允许的类。当该技能与配置文件冲突时,以配置文件为准。
阶段 — 进入阶段时加载一个文件
| 阶段 | 执行者 | 读取文件 |
|---|---|---|
| arm(布防) | 操作员在场 | 下方 § Arm,然后 discover.md 构建队列 |
| iteration(迭代) | away-orchestrator,每个进程一个 | iteration.md |
| status, disarm(状态,撤防) | 操作员 | 下方 § Status,§ Disarm |
project-workflow 和 away-run 共享文件(积压文件、<projects_dir>/proposals/open/),不共享调用,除了一种情况:一个 project 行通过 Skill 工具以无人值守模式调用 /project-workflow。
一个项目浪潮跨越多个 project 行,每行对应 wave.md § Session shape 的一个步骤组(1;2-3;4-7)。每行从 ## Resume 命名步骤开始处理到其步骤组的末尾,提交 chore(<NNNN>): checkpoint wave N at step <n>,并追加下一步骤的后续行,除非已经到达边界。只有当一行至少完成了一个步骤时,它才追加一行(attempts 为 0);一行如果未完成任何步骤,则保持 claimed 状态,并根据自身的 attempts 重试。这会终止:每个后续行至少跟随浪潮的七个步骤之一,而尝试上限结束了一个永远无法完成的步骤。检查点和 ## Resume 是唯一的交接点(iteration.md § 3)。
布局
<repo>-worktrees/away-<date>/ 工作树,分支 away/<date> 从 main 分离
<run folder>/ 在 away/<date> 上跟踪;arm.ps1 -RunFolder,
queue.md decisions.md log.md 默认 <projects_dir>/away/<date>/
morning-report.md 由关闭迭代写入
<repo>-worktrees/away-<date>-run/ 临时空间,未跟踪:away.env, watchdog.sh,
entry-prompt.md, watchdog.log, iter-NNN.*, locks
计划任务 away-<repo>-<date> 每 15 分钟运行一次,直到硬停止
队列行
templates/queue.md 保存模式。列:id | item | agent | status | claimed_by | lease_until | attempts | evidence。agent 是 mechanical-worker、stream-worker、researcher、project 或 discover。每次队列编辑都需获取锁:mkdir <scratch>/queue.lock(原子操作;如果失败,每 10 秒重试一次,持续 2 分钟;上次修改时间超过 10 分钟的锁文件夹视为过期,无论是否包含 owner 文件:将其移除),编辑,rm -rf 锁。2 分钟重试失败后的处理参见 iteration.md § 2 和 § 4。一次声明将 claimed_by 设置为迭代的声明标签(iter-NNN,与入口提示中给出的完全相同)和 lease_until;过期的租约意味着迭代已死亡,该行可再次声明,attempts + 1。
Arm(布防,操作员在场)
- 队列。 使用
discover.md构建队列:仅第一层级行,每行都有一个命名检查。第二层级工作变为提案。为每行可能遇到的每个决策指定默认值;一个具有未决决策且无默认值的行不会被排入队列。 - 姿态。 清楚说明:本次运行使用
--permission-mode bypassPermissions,因此每个工具调用都会无提示执行;全局拒绝规则仍然适用。“无门控”(开放问题变为命名默认值,失败跳过并重试)是每个运行的选择加入机制,在队列头部设置为gates: none;绝不可从先前的运行中推断。 - 布防。 先干运行,然后正式执行,从 PowerShell 运行:
powershell -NoProfile -File <skill>/arm.ps1 -Repo <path> -StopAt "<YYYY-MM-DD HH:MM>" -Queue <queue.md> -WhatIf。 它从main在away/<date>上创建工作树,从templates/播种运行文件夹并将其与队列一起提交,运行配置的bootstrapargv({worktree}替换为工作树路径,cwd 是主检出;如果键不存在或为 null 则跳过)并等待其完成,将watchdog.sh和entry-prompt.md复制到临时空间,写入away.env,并注册任务(Register-ScheduledTask,绝不使用schtasks /Create:PowerShell 5.1 会弄乱/TR引号)。非零的 bootstrap 退出会在任何任务存在之前拒绝;工作树和分支保留以供检查。任务没有委托人,因此仅在操作员登录时运行,在一个控制台窗口中运行,关闭窗口会终止任务:锁定屏幕,不要注销。 - 检查。
Get-ScheduledTask -TaskName 'away-*'显示任务;第一次触发将watchdog up写入watchdog.log。 - 后续队列编辑。 arm.ps1 提交队列一次。在布防后对
away/<date>上的队列所做的任何编辑,请自行提交(在任务触发后,在队列锁下进行):迭代将不是自己创建的未提交工作视为他人的工作,并且永远不会暂存它。
看门狗的功能(watchdog.sh)
- 启动
claude -p --agent away-orchestrator --max-turns N,stdin 上提供提示。模型和努力程度来自代理的前置元数据;没有--effort,没有 TTL 标志,没有--disable-slash-commands(它会禁用 Skill)。 - 通过
is_error/api_error_status以及queue.md是否更改来判断一次迭代,绝不通过num_turns。连续三次没有队列更改的迭代将终止。 - 使用限制:睡眠到重置,消息状态告知可通过。“您已达到 Opus 限制”仅在
mechanical-worker类型的行上继续使用 Sonnet(--model sonnet);如果没有可声明的行,则睡眠到重置。 - 预算超支(
subtypeerror_max_budget_usd,kindbudget):不睡眠,因为上限是每个进程的。它保留该行的声明,因此下一次迭代处理下一行,当该行租约过期时,此行返回;超支计入FAIL_MAX,就像错误一样。 - 配额储备:在滚动 5 小时内估算支出达到
WINDOW_CAP_USD时,睡眠直到窗口释放;最后的RESERVE_MIN分钟预留给关闭操作。 - 队列清空:一次关闭迭代写入晨间报告,然后退出。任何其他退出都会留下由看门狗写入的存根报告。每次退出都会写入
STOP,因此后续的任务触发变为空操作;删除它以恢复。 - 每次项目迭代后,它会释放该迭代声明标签下持有的所有租约,因此因限制或错误而中断的行会被重试,而不会搁置到关闭。它在关闭后跳过此操作(关闭不声明任何东西),以及在预算超支后(如上所述)。
- 每次迭代开始时记录
claude: <path>:即将运行的二进制文件。 - 拒绝在
main、主检出或不在away/*上的分支上运行。 - 干运行:
CLAUDE=<存根脚本> AWAY_NO_SLEEP=1 bash watchdog.sh <away.env>针对away/*上的临时工作树;睡眠被记录,但不实际执行。环境中设置的CLAUDE或PY优于away.env中指定的值,因此即使存在 arm 写入的away.env,存根也能运行;通过claude: <存根>日志行确认。
Status(状态)
查看 <scratch>/watchdog.log 的尾部;读取 queue.md。在信任“另一个看门狗正在运行”之前,确认存在一个 claude.exe 进程(tasklist)和最近的 iteration N starting 行:一个孤立的锁会使每次触发静默挂起。Git Bash 没有 pgrep。
Disarm(撤防)
powershell -NoProfile -File <skill>/disarm.ps1 -Repo <path> -Date <date>:它写入 STOP,注销任务并检查 Get-ScheduledTask -TaskName 'away-*' 返回为空。保持注册的任务会每 15 分钟产生一个 bash 进程。工作树和分支保留以供检查:阅读晨间报告,然后通过仓库的常规途径合并 away/<date>,或删除它。
为何如此构建
- 弹性位于 CLI 之外。
CronCreate durable:true返回为仅会话(2026-09-19);/loop重新进入同一会话;从 Bash 工具调用启动的nohup … &是该 shell 的子进程;Git Bash 没有setsid。 - 使用限制通过睡眠到重置来处理,消息状态告知可通过,而不是使用递增的退避;迭代绝不被低
num_turns判定为失败:因为退避会错过重置,而一次迭代可以在一个报告的 turn 内关闭一个行。