onlyne-swarm 0.4.0

Reactive multi-agent directed cyclic graph workflow scheduler derived from Onlyne
# Swarm 正文协议头(PROTOCOL,修订一 2026-09-06)

onlyne 本体零侵入的上层协议:swarm 元数据夹带在消息正文首部,外加一层解析器。
传输层(Envelope、FIFO、socket 事件)完全复用现有 onlyne 通道。

射后不理:`transfer_send_to` 是转派血缘(本任务由哪个任务激发而来),只用于
TUI 家族视图、cancel 级联、ledger 关联。零等待语义、零路由语义。

## 1. 线格式

```text
---swarm
task_id: 550e8400-e29b-41d1-a716-446655440000
from: planner
transfer_send_to: 11111111-2222-3333-4444-555555555555
attempt: 1
---
## role: planner

<人类可读 Markdown 载荷>
```

- 首行必须恰为 `---swarm`,末分隔行必须恰为 `---`- 头部为 YAML 映射,四字段必填:
  - `task_id`:UUID v4,调度器在 submit 与 in 监听入口生成。复用为 session id。
    swarm.db 内唯一索引,重复投递直接丢弃并记日志。
  - `from`:发起方树相对路径,root 为 `.`(如 `planner``a/b`)。
  - `transfer_send_to`:生成本任务的那个 task_id。顶层任务为空字符串或缺省。
  - `attempt`:整数,首次为 1。调度器不重放,attempt 主要用于 out 去重与 TUI 展示。
- 分隔行之后为 Markdown 载荷。调度器投递时在载荷前前置 `## role: <name>`  (role 文取自合并后的模板 `role` 字段)。
-`reply_to` 头不再识别:带 `reply_to` 的消息按头解析失败处理(普通消息)。

## 2. 解析规则

1. 正文不以 `---swarm\n` 开头 → 非 swarm 消息,按普通消息处理(不建 session)。
2.`---` 闭合行 → 解析失败,按普通消息处理,不报错中断管线。
3. 头部 YAML 解析失败或缺必填字段 → 解析失败,按普通消息处理,并在 daemon 日志记 `warn`4. `task_id` 非法(非 UUID)→ 按普通消息处理。
5. 带旧 `reply_to` 字段 → 按普通消息处理(新旧字段名互不识别)。
6. 头解析成功 → swarm 任务消息,进入优先级链(见 SPEC §5)。

## 3. out 格式

目标 session 经 out 写出结果时,正文同样携带 swarm 头:`task_id` 为本任务 id,
`from` 为本 workspace 路径,`transfer_send_to` 原值返回,`attempt` 原值返回。
out 即成功信号(done),调度器记台账并回收 terminal,不做任何转发。

失败与取消不写消息体:早停记 failed 台账行,cancel 记 cancelled 台账行。
`swarm-failed:` / `swarm-cancelled:` 前缀只出现在 ledger `reason` 字段。

## 3b. 回收控制线(`---swarm-ctl`

调度器回收 terminal 时先向下行 loopback 写一条纯头部控制线:

```text
---swarm-ctl
op: recycle
task_id: 550e8400-e29b-41d1-a716-446655440000
reason: done
---
```

- `task_id` 可填 `*`:表示该 workspace 当前占用的 hop 一律回收。
- `reason``done` / `failed` / `cancel` / `operator`- 上行 ack:session 调 `swarm_recycled` IPC op,body JSON
  `{workspace, terminal_handle, task_id, reason}`;daemon 原样广播
  `workspace_state_changed`- session 收到控制线后自行 `process.exit`,调度器随后 `orca terminal close`  调度器向不再存活的进程注入 shell kill 被明确禁止。
- 控制线对模型不可见:pi-onlyne 在投递前拦截,任务 catchup 扫描也排除
  `---swarm-ctl` 前缀。

## 4. 示例

顶层提交:

```text
---swarm
task_id: aaaabbbb-cccc-dddd-eeee-ffffffffffff
from: .
transfer_send_to:
attempt: 1
---
## role: planner

请产出三阶段拆解。
```

子任务激发(planner 激发的新任务):

```text
---swarm
task_id: ccccdddd-eeee-ffff-0000-111111111111
from: planner
transfer_send_to: aaaabbbb-cccc-dddd-eeee-ffffffffffff
attempt: 1
---
## role: reviewer

请评审上述拆解。
```

planner 自己的 out(交活即退,不等 reviewer):

```text
---swarm
task_id: aaaabbbb-cccc-dddd-eeee-ffffffffffff
from: planner
transfer_send_to:
attempt: 1
---
已激发评审任务 ccccdddd…,本跳产物见 runs/…。
```

## 5. 与 Envelope 的关系

不扩展 `MessageEnvelope` 结构体。swarm 头只活在 `text` 字段内。
`platform_metadata` 不写 swarm 键,保持旧代码反序列化零改动。
需要结构化查询时由调度器解析正文后写入 swarm.db。