diff --git a/WORKMEMORY/PROTOCOL.md b/WORKMEMORY/PROTOCOL.md index 19f68295..e1d8622d 100644 --- a/WORKMEMORY/PROTOCOL.md +++ b/WORKMEMORY/PROTOCOL.md @@ -16,6 +16,11 @@ 5. **UTF-8 写入**:所有 WORKMEMORY 文件一律 UTF-8;Windows 下禁止依赖控制台默认编码(GBK 陷阱)。 6. **禁止敏感信息**:work.log / handoff / NOTES 禁止 API key、token、密码字面量(引用名称即可);pre-commit 密钥扫描兜底。 7. **协议靠约定维持**:某 agent 漏写事件不是灾难——下一个 agent 读 tail 发现缺口时补一条 `NOTE` 说明即可,不回改历史。 +8. **实现任务 MUST 在独立分支 / worktree 上做**:开工前先判分支 —— 实现 / 多步任务走分支 + PR 合入 `master`; + 仅发版类操作(bump / tag / Release 文案 / 发版文档)允许直推 `master`(须用户批准)。 + 本条于 2026-10-14 补入:此前它只存在于 `dfs-pipeline` skill 与一条记忆里,本仓文档零命中 + ⇒ 2026-10-13 那批 9 个含生产源码与 CI 定义的提交全程直推 `master`、零 PR。完整复盘见 + `docs/agents/ops.md`「Agent 工作惯例」第 9 条与 work.log 同日 NOTE。 ## 2. 事件 Schema(work.log) diff --git a/WORKMEMORY/work.log b/WORKMEMORY/work.log index 5d353b99..77c0e1a2 100644 --- a/WORKMEMORY/work.log +++ b/WORKMEMORY/work.log @@ -644,3 +644,13 @@ Caps: filesystem-read, filesystem-write, shell-exec - **门禁(本机实测)**:全量 **1814 passed + 2 skipped**(= 1800 + Task5 12 + 黄牌 2);ruff 0;mypy `--strict tools` 24 files / `--platform win32 --strict` 4 files 零错误。RED 收据均以**临时 git worktree 在改动前 HEAD 上跑新测试**取得(不污染主工作区)。 - **两条值得记的坑(都真实发生)**:① `Path.read_text()/write_text()` 默认通用换行翻译(CRLF↔`\n`)——子代理修 MUTATION 表时用 `write_text` 把测试文件写成 CRCRLF,靠 `git show HEAD:` 取原字节二进制写回才复原;**动 CRLF 文件必须 `open(newline="")`,写完必须验 `CRCRLF==0`**(这与 10-12 那次自伤同族,今天第二次)。② 测试名/docstring **不许过度承诺**:`..._before_window_creation` 曾声称"挪到建窗之后会转红"却无顺序断言(虚报)⇒ 改为"隔离调用用例去时机承诺 + 位置无关 AST 顺序断言"双轨,变异矩阵证明"删/晚挪"红、"建窗前换函数"仍绿 ⇒ 调时机不会被迫删断言。 - **仍待办**:① **真机双击验收**(HITL,只能用户做):无黑框 / 品牌图标 / 冷启动 splash / 故意制造启动失败时有弹窗;若任务栏仍归 Python 组 ⇒ 调 AppUserModelID 时机。② **CI 首次真跑 no-console 步**(run 38430807173):必须去日志确认四行 `[PASS]` 而非 `[SKIP]`(本机无 dist/ 产物,该步①–④ 未在真实产物上执行过)。③ 本计划按「成果已发版」判据留待下一版发布后再归档。 + +### 2026-10-14 | codebuddy | NOTE 流程缺陷:2026-10-13 那批实现提交全程直推 master、零 PR +Caps: filesystem-read, filesystem-write, shell-exec +事件:用户指出「这次更新没有按要求开分支,直接在 master 上操作了」⇒ 复盘定因 + 补规则。 +- **事实**:`0f7b80f`…`b05a367` 共 **9 个提交全在 `master`**,`git branch` 只有 master,**0 个 PR**;改动面含生产源码(`desktop.py` / `start.py`)、打包面(`package_windows.py`)、CI 定义(`ci.yml` / `build-release.yml` / `tools/verify_windows_portable.py`)。**实际损失 0**(CI 全绿、未产生红 master),但风险与「红 master 事故」(PR #117 在 CI 未跑完时被合并)同族:一旦 CI 红,红提交会**直接留在 master 历史里**。 +- **根因三层(不是"忘了")**:① **规则不可见**——grep `AGENTS.md` / `docs/agents/ops.md` / `WORKMEMORY/PROTOCOL.md` / `PROJECT_OVERVIEW.md` **零命中**;规矩只存在于两处:`dfs-pipeline` 的 *Worktree Isolation Invariant*(本轮走 grill→plan→exec,**没调用 dfs-pipeline**)与一条**未打开的记忆 topic 文件** ⇒ 按 AGENTS.md 路由 bootstrap 的 agent 读不到它。② **流程缺环**——`dfs-plan` / `dfs-exec` / `plan-schema` 均**无任何 branch/worktree 步骤**;唯一带隔离不变量的是 `dfs-pipeline`。③ **上下文惯性 + 无机械闸**——会话由发版流程延续(发版在 master 上做且是用户批准的),切到实现任务未重新判定;分支纪律**没有机械闸**(对比:发版门 `tag == v+APP_VERSION` 是机械闸,同轮就抓到过一条写死旧 tag 名的测试)。**靠人记的规矩没有机械闸,必漏。** +- **我自己两点直接失误**:写计划(`0f7b80f`)时没把分支写进 Global Constraints;第一次 push 前没核分支。**且讽刺的是**——中途确实用过临时 worktree(`/tmp/del-red`,为 RED 取证据),工具在手却只当验证手段,没当成"工作发生的地方"。 +- **修复(本次提交)**:`docs/agents/ops.md`「Agent 工作惯例」**第 12 条** + `WORKMEMORY/PROTOCOL.md` 铁律**第 8 条**写明——**实现 / 多步任务 MUST 走独立分支(或 worktree)+ PR 合入 master;仅发版类操作(bump / tag / Release 文案 / 发版文档)允许直推 master 且须用户批准**。**本次补规则的改动本身走分支 `docs/branch-discipline-rule` + PR**(否则"改规矩不守规矩",规则当场失效)。 +- **暂缓**:给 `dfs-plan` / `dfs-exec` 补「分支隔离」步骤(全局 skill + 发布仓两侧同步)——用户指示 skill 先不动。 +- **未做**:不回滚那 9 个提交(CI 全绿、历史已推送,重写收益低且风险高)。 diff --git a/docs/agents/ops.md b/docs/agents/ops.md index 2743698c..c7c86d32 100644 --- a/docs/agents/ops.md +++ b/docs/agents/ops.md @@ -199,6 +199,15 @@ TTS 链路(真机判定层):`AndroidNativeTTS.speak`(系统 TTS,免网 - 判别法(先给用户做,不先改码):F12 → 右键刷新按钮 →「清空缓存并硬性重新加载」; 或开**无痕窗口**访问(无痕无缓存/SW = 服务器磁盘真实文件)。无痕正常 ⇒ 用户侧缓存,代码不用动。 - 教训:别在 `setupPWA`/`#sw-source` 上花时间"增强"离线——那段 SW 从没注册成功过。 +12. **开工前先判分支(MUST)**:**实现 / 多步任务一律在独立分支(或 worktree)上做,再走 PR 合入 `master`**; + 只有**发版类操作**(版本 bump / 打 tag / Release 文案 / 发版文档回填)允许直接在 `master` 上推,且推送前须用户显式批准。 + 为什么把这条写在这里:2026-10-13「去控制台 + 桌面化观感」那批 **9 个提交**(含生产源码 `desktop.py` / `start.py`、 + 打包面 `package_windows.py` 与 CI 定义 `ci.yml` / `build-release.yml` / `tools/verify_windows_portable.py`)**全程直推 + `master`、零 PR**。事后复盘的根因**不是"忘了"**,而是这条规矩此前只存在于两处不可见的地方 —— + `dfs-pipeline` 的 Worktree Isolation Invariant(那轮没调用该 skill)与一条未打开的记忆文件 —— + 而**本仓文档里一行都没有** ⇒ 按 `AGENTS.md` 路由做 bootstrap 的 agent 根本读不到它。 + **机械对照**:发版门(`tag == v+APP_VERSION`)是机械闸,所以那类错误会被构建当场抓住(同轮就抓到过一条 + 写死旧 tag 名的测试);分支纪律**没有机械闸** ⇒ 只能靠"写进可见文档" + 推送前自问一句「我现在在哪个分支」。 ---