Files
workbuddy_skills/session-mechanism/graph/README.md
T
admin 4866ad8d37 feat(session-mechanism): 图模式补全自动化测试并接入技能入口
- graph/test_graphctl.py:新增 49 个用例,覆盖建图 / 校验硬错与警告 / 就绪集 /
  状态流转 / 非法操作 / 边界 / 写入范围隔离;实跑 Ran 49 tests OK(27.5s)
- graph/graphctl.py:修测试暴露的问题(+50/-10)
- graph/README.md:补「怎么跑测试」一节(+27 行)
- SKILL.md:目录树与入口指针登记 graph/(新增 4 行文档,机制行为零改动)
- 隔离性核对:collabd.py / goalctl.py / 两个看板 / 全部钩子 diff 为空;
  state.py 闸门读数绿、常驻心跳 7 秒、看板 20100 在听
2026-10-19 08:18:57 +08:00

6.3 KiB
Raw Blame History

图模式(独立功能)

2026-10-18 新增。这一套与现有「项目机制」完全并列:不读写 goal.json、tasks.json、collabd-state.json,不参与六道闸,不接管常驻循环,不改变现有任何会话的行为。 停用方式:不调用它就行;它没有常驻进程、没有注册任何钩子、没有改任何现有文件。

一、它解决什么

现有机制是「一棒干一堆、由会话读摘要决定下一棒」。图模式把这层换成:

  • 节点:一块独立的活,带自己的域(允许写哪些目录)和判据。
  • 边:节点之间的依赖;依赖全 done 才放行。
  • 状态:写在一份图上,跨会话共享,不依赖任何会话的上下文。

于是可以做到:一批就绪节点同时干、干完各自回报、下一批自动放行。

二、怎么用

工作区参数 --ws 指向要被推进的工作区根目录。图落在 <ws>/.workbuddy/graph/<gid>/。

1、建图

按判据建(每条判据一个节点,默认无依赖、无域):

python graph/graphctl.py init --ws "<ws>" --title "目标名" --kpi "判据A;判据B;判据C"

按节点定义建(要并行、要依赖、要域,就用这个):

python graph/graphctl.py init --ws "<ws>" --title "目标名" --nodes-json - <<'JSON'
{
  "max_parallel": 3,
  "nodes": [
    {"id": "A", "title": "改界面", "domain": ["ui/"],      "accepts": ["页面能打开"], "deps": []},
    {"id": "B", "title": "改文档", "domain": ["docs/"],    "accepts": ["索引已登记"], "deps": []},
    {"id": "C", "title": "改服务", "domain": ["server/"],  "accepts": ["本地能起"],   "deps": ["A"]},
    {"id": "D", "title": "汇总",   "domain": ["docs/index/"], "accepts": ["三处齐"],  "deps": ["A","B","C"]}
  ]
}
JSON

2、校验

python graph/graphctl.py check --ws "<ws>" --gid "<gid>"

报三件硬错(环、依赖指向不存在的节点、状态非法)和三类警告(没有域、没有判据、两个节点域重叠)。

3、算这一批派谁

python graph/graphctl.py ready --ws "<ws>" --gid "<gid>"

输出 ready(这一批可以同时开工的节点)、backlog(就绪但被并发上限挡住)、waiting(还差什么)。

4、开一个节点、回报

python graph/graphctl.py start  --ws "<ws>" --gid "<gid>" --node A --by "执行会话-xxx"
python graph/graphctl.py report --ws "<ws>" --gid "<gid>" --node A --state done --evidence "页面 1440 宽截图在 ui/shot.png"

回报 done 后会立刻返回下一批的 ready,这就是图在往前走的信号。

5、看状态

python graph/graphctl.py list  --ws "<ws>"
python graph/graphctl.py show  --ws "<ws>" --gid "<gid>"

三、就绪的四个条件

  1. 依赖全部 done。
  2. 节点自己是 pending。
  3. 域不与任何 running 节点重叠(docs/ 与 docs/ui/ 算重叠)。
  4. 加上在跑的节点后,不超过 max_parallel(默认 3)。

四、与现有机制的关系

事项 现有机制 图模式
目标定义 goal.json 图文件里的 title / nodes
任务台账 tasks.json 图里每个节点的 status + events.jsonl
派活决策 检查会话读摘要判断 ready 按图算
触发 常驻 + 六道闸 + 静默 2 分钟 调用方驱动(人或会话),无后台进程
会话创建 自动化排期 由调用方决定(图不管怎么开会话)
域锁 开工时声明 同左,节点的 domain 直接喂给开工命令

两套可以同时存在:图模式不读也不改现有那三份文件,现有机制也永远不会看到 graph/ 目录。

五、怎么跑测试

python graph/test_graphctl.py -v

全绿应看到 Ran 49 tests ... OK,用时 20 秒上下(每条用例起一次子进程)。

测试只往临时目录写:<GRAPH_TEST_TMP>/graph-test-<pid>/<用例名>,默认 GRAPH_TEST_TMP = AIProject/ai1net-dsh-server/tmp,由每条用例的 tearDown + 进程退出的 atexit 兜底删除。想换落点就设环境变量 GRAPH_TEST_TMP。

清残留在本机是常态:跑完后 tmp/ 下偶尔还能看到 graph-test-<pid>/(进程内已确认删空,是本机沙箱在进程退出后把删除路径又放回来了,与测试代码无关)。一条命令清掉:

rm -rf "E:/ProgramData/AIProject/ai1net-dsh-server/tmp"/graph-test-*

八个用例类各管一摊:

1、T1_Init —— 建图:--kpi 按条数生成节点(全角分号也认)、--nodes-json 带依赖与域、重复 id 报错、自动编号避让、max_parallel。 2、T2_CheckErrors —— 硬错三条:环(含自环)、依赖指向不存在的节点、状态非法。 3、T3_CheckWarnings —— 警告三类:无域、无判据、域重叠(docs/ 与 docs/ui/ 双向都算)。 4、T4_Ready —— 就绪集:依赖未满足、域与在跑冲突、超 max_parallel(running 占名额)、两个域重叠的节点不进同一批。 5、T5_Flow —— 流转:pending→running→done、events.jsonl 只追加、blocked 累加 attempts、回报后回带 next_ready。 6、T6_Illegal —— 非法操作:running/done 再 start 拒绝,blocked 可重开;--state 只认 done / blocked;不存在的节点/图报错。 7、T7_Edge —— 边界:单节点图、空节点图、gid 含中文(显式与自动生成各一条)、list 统计与空工作区。 8、T8_Isolation —— 独立性:工作区里预埋的 goal.json / tasks.json / collabd-state.json 跑完字节不变,且不新建这类文件,写入范围只有 <ws>/.workbuddy/graph/。

测试对 graphctl.py 的唯一要求是「能当命令行跑」,不 import 它的内部函数 —— 所以改内部实现不会连带改测试。

六、还没做的(下一步)

  • 自动派活:读 ready 后自动建排期(要复用现有排期硬规则:cwds 正斜杠、workspace_scope、next_run_at 毫秒、scheduled_at ISO)。
  • 判定节点完成:现在靠回报 --state done,还没有「看证据够不够」的自动判定。
  • 回退边:attempts 已经在记,还没有「判不过回到哪个节点」的字段与规则。

这三件都只在本目录内加,不影响现有机制。