技能包:配置与代码分家 —— 每包自建 env/ 放本机专属配置,scripts/ 不再写死本机路径

用户 2026-10-11 原话:
· 19:22「这个环境都是针对一台机器的,同步到别的机器把环境都搞坏了」
· 19:28「不用挪出 用env文件夹区分就行,重点是 脚本是脚本 配置是配置」
· 19:29「每个技能 需要环境配置的 都有自己的 env文件夹」
· 19:30「修改完成后要仔细检查 避免调整后 各技能脚本运行失败」

改动:
1、session-mechanism 新增 env/(roots.env=本机真身不入库 + roots.env.example=样例入库),
   install.py 的 ROOTS_ENV 改指 env/roots.env;全包脚本/hook 的配置定位统一为
   「向上 4 层 × env/roots.env 优先 → 包根 roots.env 兼容 → 技能库那份兜底」。
2、去硬编码:collabctl / keepalive / supervise-launch / board-launch 里的本机路径与本机工作区
   清单全清,改为 DSH_AIROOT(兜底 dirname(DSH_WS_ROOT))+ 扫 <AIROOT>/*/.workbuddy/collab/
   自动发现;保活任务名按 collabd-keepalive-<工作区名> 现推;启动器默认值改 ~/.workbuddy 形态。
3、browser-harness:bh_chrome_keepalive.py 默认值全部改 env 驱动,新增 env/bh.env.example。
4、.gitignore:env/ 下只放行 *.example(三行三种层级)+ 兜住旧位置的包根 roots.env。
5、改包纪律.md 新增「四、包结构:脚本是脚本,配置是配置」,立为全仓通用规矩。
6、文档同步:SKILL.md / deploy.md(新增 §3b 配置层级、§6 换机器必查 6 件事)/ rules.md /
   pitfalls.md / supervise-persistence.md。

验收(本机):py_compile 34 个 py 全过;selftest PASS 109 / FAIL 0;
逐文件实证 8 个 loader 命中 env/roots.env;preflight-lock.sh 同目录实测解出两个根;
install.py --manifest 77 份、语法失败 0。

异机验证(包拷成「新克隆」(只有 *.example)+ 另造假工作区 ws-alpha/ws-beta):
install.py --apply 自生成该机 env/roots.env;collabctl/keepalive 自动发现的确实是
ws-alpha/ws-beta、任务名现推(写死清单确已消除);部署副本本地无 roots.env 时靠
CODEBUDDY_CONFIG_DIR 兜底读到技能库那份;整套 selftest 有宿主库时 PASS 108 / FAIL 1
(唯一 FAIL=该区没有常驻心跳,环境所致;本机常驻在跑时同一套为 PASS 109 / FAIL 0)。
This commit is contained in:
admin committed 2026-10-11 21:49:28 +08:00
1 parent 90cc4315d5
commit d81f75f173
37 files changed
+763 -291

No files matched your search

+44 -2
View File
@@ -100,6 +100,40 @@
---
## 3b 🔴 配置层级:技能包级 `env/` vs 工作区级 `collabd.config.json`(2026-10-11 立)
> 用户令(2026-10-11):19:28「不用挪出 用env文件夹区分就行,重点是 **脚本是脚本 配置是配置**」/
> 19:29「**每个技能 需要环境配置的 都有自己的 env文件夹**」。
**两层,一层一份,各自单一真源**:
| 层 | 文件 | 装什么 | 谁读 |
|---|---|---|---|
| **L0 技能包级**(每台机器一份) | `<技能包>/env/roots.env`(真文件不入库;样例 `*.example` 入库) | 这台机器的根:`DSH_WS_ROOT`、`DSH_AIROOT`、`WB_RESULT_HOOK_WS`、`COLLABD_PROD_CONFIG`、`CODEBUDDY_CONFIG_DIR`、`DSH_DOCS_ROOT` | **包内脚本**:钩子(`scripts/hooks/*`)、`board.py`、`goalctl.py`、`collabctl.py`、`keepalive.py` |
| **L1 工作区级**(每工作区一份) | `<工作区>/.workbuddy/collab/collabd.config.json` | 这个工作区自己的东西:`workspace`/`inbox`/`live`/`taskgraph`/`host_db`(可写本机绝对路径)/`peer_workspaces` | **部署副本**:`<ws>/.workbuddy/collab/` 下的 `collabd.py`、`goalctl.py` |
**桥接(谁把两层接起来)**:`scripts/supervise-launch.py`(常驻)与 `scripts/board-launch.py`(看板)。
计划任务的动作里**没有 env 字段**,所以这两个启动器在**进程内**设
`COLLABD_CONFIG=<本区>/collabd.config.json` + `CODEBUDDY_CONFIG_DIR`,再 `runpy` 起本体。
- **常驻**:启动器装在 `<ws>/.workbuddy/collab/`(由 `deploy_code.py` 分发)⇒ `HERE` 就是本区 ⇒ 配置恒指本区。
- **看板**:启动器在技能包内,主工作区根从 L0 的 `DSH_WS_ROOT` 读;读到就用,读不到就**写日志 + 退出码 2**(⛔ 不猜路径)。
**部署副本怎么拿 L0 的配置**:从 `<ws>/.workbuddy/collab/` 跑**管理入口**(`collabctl.py`/`keepalive.py`)时,
`_sm_load_roots()` 向上找不到 `env/roots.env` ⇒ 回落到**本机技能库**那份
(`<CODEBUDDY_CONFIG_DIR>/skills/session-mechanism/env/roots.env`;`CODEBUDDY_CONFIG_DIR` 由宿主给)
⇒ 全机**只有一份** L0 配置,副本目录里**不放第二份**(避免各区分叉)。
🔴 而 `collabd.py` 的副本**不读 L0 的 `DSH_WS_ROOT`**(那会把别的区认成自己 —— P0-85 静默错归属族):
它靠**启动器设的 `COLLABD_CONFIG`** 定位自己。
**日常该改哪一层**:
- 换机器 / 换工作区根 / 换文档库 ⇒ 改 **L0**(重跑 `install.py --apply`,或手改 `env/roots.env`)
- 换本区配置(inbox 名、端口、`host_db`、peer 列表)⇒ 改 **L1**
- 两层都**不把**「别台机器才成立的值」写进入库代码(依据:用户 19:22「这个环境都是针对一台机器的,同步到别的机器把环境都搞坏了」)
---
## 4 旧副本退役(⛔ 否则"代码在 A、钩子在 B")
症状:改了 skill 里的程序却没生效;或 `advance.md` 等产物由**另一个副本**写出(内容与你预期不同)。
@@ -167,13 +201,21 @@ curl -s --noproxy '*' -o /dev/null -w "%{http_code}\n" http://127.0.0.1:20090/
**⚠️ 遗留单点(如实登记)**:这两条后台任务**挂在"起它的那个会话"名下** ⇒ **起它的会话被回收 / WorkBuddy 退出 ⇒ 链路断**。
⇒ 起它们的会话**在那段时间内不要关**;断了就按上面"② 不在才起"重起一次。
## 6 换机器后必查的 5 件事
## 6 换机器后必查的 6 件事
1. `--where` 的三个路径是否都对;
2. 钩子接线是否指向 skill(§4);
3. 宿主库能否只读打开(`sessions` / `automation_runs` / `automations` 三张表读得到);
4. 有没有**别的实现**在抢同一个 inbox(§4);
5. `guard.py` 是否真的起来了(`--status`)+ 它是否会随开机自启。
5. `guard.py` 是否真的起来了(`--status`)+ 它是否会随开机自启;
6. 🔴 **计划任务里有没有指向不存在路径的项**(2026-10-11 加)。判据:逐条取出动作里的脚本路径
`Test-Path` 一遍;指向已删目录的(例:老工作区改名、`tmp/selftest/…` 这类一次性沙箱)=**静默死任务**。
处置:`Disable-ScheduledTask`(`collabctl.py` 的旧任务清单已含本机这几条)——
**禁用不删**,可逆。
```
Get-ScheduledTask | ForEach-Object { $t=$_; $t.Actions | ForEach-Object { "$($t.TaskName)|$($t.State)|$($_.Execute)|$($_.Arguments)" } }
```
⚠️ 判存在性时先**展开 `%windir%`/`%SystemRoot%`**,否则系统自带任务会被误报成缺失。
---