Files
UI/ITERATION.md
T
2026-10-26 13:55:18 +08:00

7.1 KiB
Raw Blame History

无人值守自我迭代协议(ITERATION.md)

本协议由自动化 Agent 执行,也可供人工参考。任何迭代必须遵守 CODING.md、AGENTS.md、ARCHITECTURE.md 三份规范,门禁 npm run check 不通过的一切产出作废。

运行模式:连续迭代 + 心跳监护

调度器(每小时唤起)不是迭代器,只做两件事:健康检查 + 中断重启。真正的迭代是单次唤起内的连续循环——反复执行《每轮迭代流程》,直到 backlog 清空或时间预算耗尽,中间不停歇。

  • 并发锁:.ua/loop.lock(含时间戳,不入库)。唤起时若锁存在且心跳在 15 分钟内 → 已有实例在跑,直接退出;否则写锁开始循环。每轮开始前刷新锁内时间戳作心跳。
  • 时间预算:单次唤起最多连续迭代约 50 分钟,到点在完成当前轮后停止(防止与下次唤起重叠)。预算判断必须基于客观时钟:点火时用 date +%s 记录起点并写入 .ua/loop.lock,每轮开始时重新取 date +%s 与起点求差,差值 ≥ 2700 秒(45 分钟)即到点;禁止凭感觉估算时长——LLM 无内部时钟,自估时长系统性偏高(实测自报 40+ 分钟而实际约 30 分钟)。
  • 熔断:同一 backlog 条目连续 2 轮失败 → 停止循环,锁照常释放,等待下次唤起。
  • 重启语义:锁心跳超过 15 分钟视为循环中断(崩溃/超时),调度器删旧锁、重新点火。
  • 调度器约束(踩过的坑,勿重复):本地调度器只支持 HOURLY 及以上粒度(DAILY/WEEKLY/MONTHLY/YEARLY),FREQ=MINUTELY / FREQ=SECONDLY 不受支持——写入后 next_run_at 会变成 NULL,首跑之后永久静默(实测 10/23–10/26 停摆三天)。因此「高频监护」不能靠加密 rrule 实现,只能靠单次唤起内的连续循环;心跳间隔 = 1 小时,循环预算 45–50 分钟,两者共同保证覆盖面。任何对自动化的改动(改 prompt、改 rrule、暂停恢复)都必须回查 next_run_at 非空,改 prompt 会把状态重置为 PAUSED,需再单独置 ACTIVE。
  • 有效性自检:每轮迭代首步除同步仓库外,检查 .ua/loop.lock 与 automation_runtime_state.last_run_at;若发现上次运行距今超过 2 小时(说明调度中断),在留痕 summary 里注明「调度中断后恢复」,便于周报统计停摆时长。

多实例错位接力

单条自动化的占空比受平台语义限制:next_run_at = 本次运行结束时刻 + INTERVAL,不是整点对齐(实测 12:46:50 结束 → 下次 13:46:50)。INTERVAL 下限 1 小时,45 分钟预算下单条仅 45/(45+60) ≈ 43% 覆盖面,即「干 45 分、歇 60 分」。因此用两条同构自动化错位 30 分钟补齐空档:

实例 锚点(错位) 角色
A 无人值守迭代循环 整点链(当前 13:46:50 → 逐轮顺延) 主循环
B …B(错位接力) A 之后 30 分钟(当前 14:16:50) 补位循环
  • 接力靠 missed 队列自动完成:到点时若另一实例仍持锁,该次被记为 missed 并保留 missedScheduledAt,待当前实例释放锁后立即补跑(实测间隔 9 秒)。无需人工干预,也不占用额外配置。
  • 抢锁失败是正常行为:看到 15 分钟内新鲜锁的实例直接回复「循环存活,未干预」退出——不计失败、不写留痕、不改 backlog。
  • 同一把锁、同一份 backlog:多实例共享 .ua/loop.lock 与 qa/* 分支流水线,任何时刻只有一个实例在写,冲突由锁而非分支解决。
  • 调整排期的方法:改 validFrom(next = max(now, validFrom) + INTERVAL),改完必须回查 next_run_at 非空且落在期望时刻;改 prompt 会把状态重置为 PAUSED,须再单独置 ACTIVE。

分支流水线

qa/probe ──门禁通过──▶ qa/stable ──人工审阅──▶ main(受保护,禁直接推送)
分支 用途 谁能写
main 稳定发布线,受 Gitea 分支保护 仅人工审阅后合并
qa/stable 集成测试线,所有通过门禁的迭代落在这里 自动化(仅 fast-forward 合并)
qa/probe 试验分支,每轮迭代的工作现场,可被强制重置 自动化

每轮迭代流程(自动化 Agent 执行)

  1. 同步:git fetch --all --prune,切到 qa/stable 并 git pull;从其最新提交强制重建 qa/probe 并切换过去。
  2. 选题:读 .ua/backlog.json,取第一条 status === "open" 的条目;若全部关闭,按《选题规则》自行补充一条新点子后继续。
  3. 实现:按 CODING.md 编码规范实现,保持低侵入,单文件 < 200 行,涉及组件需同步 manifest/docs/llms-full.txt。
  4. 门禁:跑 npm run check(build → demo → style → typecheck → smoke → index → verify)。
    • 通过:提交到 qa/probe,提交信息按 COMMITTING.md 规范(iter(<条目id>): <中文祈使句>,元数据变更用 chore(backlog): 记录 <id> 完成;commit-msg 钩子自动校验),推送 qa/probe,fast-forward 合并到 qa/stable 并推送;将 backlog 条目 status 置为 done 并随迭代提交。
    • 失败:尝试修复一次;仍失败则放弃本轮——qa/probe 直接重置回 qa/stable,backlog 条目在 notes 里追加失败原因、status 保持 open,提交并推送该元数据变更(仅改 .ua/backlog.json,不碰代码)。
  5. 留痕:在 .ua/iterations.log 追加一行 JSON,字段统一:{"ts":"本地ISO时间","id":"条目id","result":"done|aborted","commit":"短哈希","summary":"一句话"}。硬性规范:ts 必须来自 date 命令实测(本地时间,带 +08:00 偏移,禁止手写或用 UTC 换算);时长结论必须来自两次时间查询之差,禁止使用「大约/接近」等估算词;并发实例格式不得自创变体。随本轮提交。ua lint-iterations 会把每行 commit 拿到 git 历史里回查:哈希必须真实存在、主题必须指向同一条目(iter(<id>),早期无 scope 的 iter: <id> 也认),伪造或抄错哈希直接判违规。
  6. 边界:不改 main 分支保护、不删分支、不动 .workbuddy/、不重写历史、不 force push 到 qa/stable 与 main。

选题规则(自主补点子时)

  • 只从以下方向选:组件补充(皮肤包缺的常规组件)、既有组件的可用性细节、文档站与 Agent 文档完善、构建/门禁工具链改进、演示页完善。
  • 单轮改动范围可控:新增文件 + 少量既有文件修改,避免跨包大规模重构。
  • 每条点子必须写清 title / motivation / acceptance(验收标准,可被 npm run check 与人工检查验证)。

人工介入点

  • 审阅 qa/stable 的提交,确认质量后合入 main(PR 或本地 merge 后推送)。
  • 发现自动化产出质量下滑时:暂停自动化、在 backlog 中把质量要求写进条目、恢复运行。