memory: goalctl 两处口径分叉修复记录(§40)+ vibe-product 收口挂账

This commit is contained in:
admin committed 2026-10-06 08:46:08 +08:00
1 parent 1b68b1ac3f
commit 0cf981f419
1 file changed
+81
+81
View File
@@ -288,3 +288,84 @@
---
## 40、goalctl 两处口径分叉修复(用户 ⑤-2「vibe-product 最新会话反应新问题 看看如何解决」)
### 40.1 是什么问题
vibe-product 上一条会话(10-06 08:15~08:20)已诊断出两条缺陷并**修了数据侧**(换任务图、存值改 `pass`),
但它自己在记忆里登记了「**同族缺陷未修 / 技能侧缺陷未修**」⇒ 我这一轮把**技能侧**修了。
用户在 ⑤-2 里说的「新问题」,逐字对应那份 `目标执行状态.md` 的两条**阻断**:
| 阻断 | 内容 | 归属 |
|---|---|---|
| ① | `goal.json.execution_doc` 指向**前身目标的目录**(换目标漏改) | 工作区数据(前一会话已修) |
| ② | 本目标**从未建立过任务会话**(零排期)+ `NEXT.md` 是过期投影 | 工作区数据(已随目标完成自然消解) |
⇒ 但**真正跨工作区、属技能侧的根因有两处**,前一会话只**绕开**了、没修:
### 40.2 🔴 根因一:`goalctl.py:262` 判定层死板比字面值
- 原文:`if str(acc[k]) != "pass":` —— **只认英文 `pass`**。
- 而存值**真源就是中文**(`过|pid 8024 活…` / `已过|…` / `达(1440 与 390 两视口都有)`)。
- ⇒ 已通过的验收**全部被计入 why** ⇒ 恒判「未完成」⇒ 控制台打出
「未完成(验收 V1=过;V2=过;…)」这种**字面自相矛盾**的读数。
- 🔴 **病根不只是这一行**:`board.py::acc_is_pass()` 的 docstring 明写
「三处判据(`board.py` / `collabd.py::_acc_is_pass` / `board.html::accIsPass`)**必须同款**」,
而 `board.py:1618` 与 `collabd.py:3022` **都做了中文归一化**(`ACC_PASS_WORDS` + 剥完成副词)
—— **实际是四处,`goalctl` 被漏掉了** ⇒ 同一字段三套读法。
### 40.3 🔴 根因二:`goalctl.py:136` 配置落点写死技能目录
- 原文:`CFG = HERE / "collabd.config.json"`,`HERE` = **技能包目录**。
- 按定则「**技能就是技能、程序就是程序,谁用产生的文件放在他自己那里**」⇒
**技能目录里⛔ 不放生产配置** ⇒ 该文件**恒不存在** ⇒ `_load(CFG,{})` 恒 `{}`。
- ⇒ `taskgraph` 取默认 `INBOX/taskgraph.json` ⇒ **配置改了不生效**
(实测:vibe-product 配置里已改指 proto-board,`goals_open()` 仍报「任务图读不到」)。
- `collabd.py` 早有 `_cfg_candidates()` 三级解析(env → 工作区标准落点)⇒ **又是"一个技能两套读法"**。
### 40.4 处置
1. `goalctl` 新增 `_acc_is_pass()`:**复用 `collabd._acc_is_pass()`**(它自己再复用 `board` 真身);
拿不到 ⇒ **fail-closed 声明式兜底**+stderr 留痕,⛔ 绝不静默返回。
2. `CFG` 改为与 `collabd._cfg_candidates()` **同款三级**(env → 工作区标准落点 → 旧路径+告警)。
3. 修正 `:605` 误导文案(原「要 `名字=pass` 或 `名字=未过`」——`未过` 与任意中文值旧判定层同样恒判未过)。
4. 新增 2 条自检用例+`pitfalls.md` **P0-87**。
### 40.5 实测读数
| 项 | 修前 | 修后 |
|---|---|---|
| vibe-product `goalctl.goals_open()` | `{'open': True, 'why': [], 'bad': ['任务图读不到(taskgraph.json)']}` | **`{'open': False, 'why': [], 'bad': []}`** |
| vibe-product `goalctl` 状态台 | (目标判不出来) | **「目标状态 = 三路全过」** |
| 技能 `selftest` | PASS 97 / FAIL 0 | **PASS 99 / FAIL 0** |
| `--verify` | — | **rc=0 ✅** |
**变异对照**:改回 `!= "pass"` ⇒ PASS 97 / FAIL 1(**命中本用例**);还原 ⇒ 99/0 ✅
### 40.6 🔴 两处踩坑(都是"我喂错了,不是代码错")
1. **`selftest` 的 `imp()` 加载的是 `collabd`,不是 `goalctl`** —— 两者 `goals_open()` **同名但返回类型不同**
(collabd 返 `bool`、goalctl 返 `dict`)⇒ 直接用 ⇒ `TypeError: 'bool' object is not subscriptable`。
2. **两个模块的 `INBOX` 不是同一个目录**(`collabd` 来自配置、`goalctl` 硬编码 `WS/tmp/supervise-inbox`)
⇒ 夹具写错落点 ⇒ `bad=['任务图读不到']` ⇒ **用例恒红**。
⭐ **教训:用例红了先分"被测代码错"还是"我喂错了"** —— 三次都是后者,
若直接去"修代码",会把好的代码改坏。
### 40.7 🔴 又撞一次 CRLF(本轮第二次)
`goalctl.py` 工作副本被改成 **CRLF**(877 个 CR),HEAD 是 LF ⇒ `git diff` **整文件重写**
(877 增 / 672 删)⇒ 按字节归一化回 LF ⇒ 降到 **228 增 / 23 删**真内容。
**铁律:看到"整文件重写"先查行尾**(`b.count(b'\r')`)。前一次是 `board.html`。
### 40.8 挂账(未做,需用户拍板)
🔴 **vibe-product 的收口动作未做**:它的 `lifecycle` 仍是 `进行中`(前一会话只改了 `acceptance_state`,
**没走收口流程**)⇒ 常驻程序**按设计继续跑**(收工只在 `--set-life 已完成` 时触发)。
要收工=改 `lifecycle=已完成` ⇒ 会 **`supervise_stop` 停掉该工作区的常驻进程**。
⚠️ 这属「**影响面超出本平台/跨工作区状态变更**」⇒ **先报用户,⛔ 不擅自动手**。
⚠️ 另:vibe-product 常驻主循环跑的是**旧代码**(09-29 启动,配置改动需重启才生效)——
本次修的是**技能源**,其工作区副本要同步+重启才生效(这一步同样未做)。