immune-brain 5.0.0 → 5.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +223 -12
- package/README.zh-CN.md +228 -11
- package/package.json +2 -1
- package/plugins/immune-brain/.claude-plugin/plugin.json +1 -1
- package/plugins/immune-brain/.pi-extension/imm-canary-work.ts +18 -5
- package/plugins/immune-brain/.pi-extension/imm-unattended-batch.ts +189 -3
- package/plugins/immune-brain/.pi-extension/pi-canary-assurance-progression.ts +66 -3
- package/plugins/immune-brain/agents/immune-brain-reviewer.md +11 -1
- package/plugins/immune-brain/dist/claude/mcp-server.mjs +1885 -149
- package/plugins/immune-brain/dist/docs/reference/immune-brain-config.md +27 -0
- package/plugins/immune-brain/dist/docs/reference/subagent-dispatch-protocol.md +8 -6
- package/plugins/immune-brain/dist/imm-planner.md +4 -1
- package/plugins/immune-brain/dist/imm-run.md +198 -3
- package/plugins/immune-brain/dist/role-prompts/code-review.md +10 -0
- package/plugins/immune-brain/dist/role-prompts/lane-steward.md +44 -0
- package/plugins/immune-brain/runtime/assurance/coordinator.ts +22 -4
- package/plugins/immune-brain/runtime/assurance/review_mediation.ts +107 -0
- package/plugins/immune-brain/runtime/assurance/verdict_authority.ts +3 -0
- package/plugins/immune-brain/runtime/claude/interaction.ts +16 -0
- package/plugins/immune-brain/runtime/claude/kernel_ports.ts +105 -58
- package/plugins/immune-brain/runtime/claude/mcp_server.ts +89 -16
- package/plugins/immune-brain/runtime/claude/role_agents.ts +4 -3
- package/plugins/immune-brain/runtime/kernel/assurance_projection.ts +4 -1
- package/plugins/immune-brain/runtime/kernel/canary_application.ts +9 -2
- package/plugins/immune-brain/runtime/kernel/completion.ts +24 -1
- package/plugins/immune-brain/runtime/kernel/reducer.ts +15 -2
- package/plugins/immune-brain/runtime/kernel/spec_binding.ts +6 -0
- package/plugins/immune-brain/runtime/kernel/storage.ts +20 -4
- package/plugins/immune-brain/runtime/kernel/storage_paths.ts +33 -3
- package/plugins/immune-brain/runtime/kernel/types.ts +7 -0
- package/plugins/immune-brain/runtime/kernel/validation.ts +13 -2
- package/plugins/immune-brain/runtime/local_initiative.ts +94 -0
- package/plugins/immune-brain/runtime/loop_contract.ts +55 -2
- package/plugins/immune-brain/runtime/plugin_version.ts +1 -1
- package/plugins/immune-brain/runtime/prompts/code-review.md +10 -0
- package/plugins/immune-brain/runtime/prompts/lane-steward.md +44 -0
- package/plugins/immune-brain/runtime/role_prompt_bridge.ts +16 -3
- package/plugins/immune-brain/runtime/unattended/batch_disposition.ts +222 -0
- package/plugins/immune-brain/runtime/unattended/batch_integration.ts +387 -0
- package/plugins/immune-brain/runtime/unattended/batch_kernel_port.ts +2 -2
- package/plugins/immune-brain/runtime/unattended/batch_lanes.ts +946 -0
- package/plugins/immune-brain/runtime/unattended/batch_plan.ts +36 -11
- package/plugins/immune-brain/runtime/unattended/batch_preflight.ts +48 -33
- package/plugins/immune-brain/runtime/unattended/batch_reasons.ts +13 -1
- package/plugins/immune-brain/runtime/unattended/batch_runner.ts +22 -1
- package/plugins/immune-brain/runtime/unattended/batch_schedule.ts +162 -0
- package/plugins/immune-brain/runtime/unattended/batch_state.ts +398 -12
- package/plugins/immune-brain/runtime/unattended/types.ts +21 -2
- package/plugins/immune-brain/skills/imm-run/SKILL.md +4 -0
package/README.zh-CN.md
CHANGED
|
@@ -14,7 +14,7 @@ Immune-Brain 为 AI 编程工具(**Pi** 与 **Claude Code**)提供结构化
|
|
|
14
14
|
- **需要严谨时显式启用** — 遇到复杂功能开发或高保证任务时,显式调用 `imm-brainstorm`、`imm-planner` 或 `imm-run`。
|
|
15
15
|
- **计划变为可追踪的任务**(`TaskIntent` + `TaskRecord`) — 进度落盘持久化(Git + `.imm/`),会话重启或上下文清理后仍可无缝恢复。
|
|
16
16
|
- **质量由代码强制保障** — 自动化 QA 验收与隔离式 Reviewer 审查必须通过,任务才会结算完成。
|
|
17
|
-
- **已就绪的 Initiative
|
|
17
|
+
- **已就绪的 Initiative 可以整批运行(串行或多 Lane 并行)** — 一次确认的 Batch Authorization 即可无人值守推进整批子任务;支持默认单工作区串行推进,或显式开启多 Lane 并行(按 Scope 互斥拓扑调度独立 Git worktree 并发执行,辅以集成守卫与强故障隔离),每个 child 依然保持独立的 Enrollment、QA、Review 与结算。
|
|
18
18
|
|
|
19
19
|
Pi 与 Claude Code 是支持的宿主。未声明的适配器仍不受支持。Claude Code 最低版本为 `2.1.236`,这是已通过交互式 server-initiated MCP elicitation 验证的最低版本。当前真实 Host 证据见 `docs/verification/claude-native-elicitation-authority-conformance.md`;历史报告归档于 `docs/verification/archive/`。
|
|
20
20
|
|
|
@@ -25,6 +25,8 @@ Pi 与 Claude Code 是支持的宿主。未声明的适配器仍不受支持。C
|
|
|
25
25
|
- [安装](#安装)
|
|
26
26
|
- [快速开始](#快速开始)
|
|
27
27
|
- [如何使用](#如何使用)
|
|
28
|
+
- [推荐工作流:与 mattpocock/skills 组合使用](#推荐工作流与-mattpocockskills-组合使用)
|
|
29
|
+
- [实战案例](#实战案例)
|
|
28
30
|
- [核心设计哲学:把“判断”变成“查表”](#核心设计哲学把判断变成查表用确定性工程驾驭多模型)
|
|
29
31
|
- [7 个 Skills](#7-个-skills)
|
|
30
32
|
- [生命周期](#生命周期)
|
|
@@ -84,7 +86,7 @@ mise run check-dist-sync # 校验生成文档同步
|
|
|
84
86
|
Immune-Brain 遵循 **显式 Skill 触发(Skill-explicit)** 模型:日常对话就是轻量自然的 AI 编程,只有显式调用对应 Skill 时才会开启严格工程管理。
|
|
85
87
|
|
|
86
88
|
**1. 当你需要严谨工程流程时,显式调用 Skill:**
|
|
87
|
-
-
|
|
89
|
+
- 需求模糊、重大架构设计或高保证任务想先敲定方案?输入 `/grill-me`(来自 `mattpocock/skills`,强烈推荐)进行苏格拉底式高压追问与决策确认,或输入 `/imm-brainstorm`(内置极简梳理)。
|
|
88
90
|
- 目标明确准备制定方案?输入 `/imm-planner`(或对 Agent 说 "用 imm-planner 规划深色模式功能")。
|
|
89
91
|
|
|
90
92
|
*(日常提问如 "这个函数什么意思"、"改个 typo" 保持完全原生,没有任何流程弹窗和开销。)*
|
|
@@ -112,11 +114,11 @@ Immune-Brain 提供两种清晰的工作模式:日常轻量编码走 **Host-na
|
|
|
112
114
|
| 你的情况 | 你做什么 / 说什么 | 会发生什么 |
|
|
113
115
|
|---|---|---|
|
|
114
116
|
| 日常编码、快速改动、普通问答 | 正常自然语言对话("帮我改下文案"、"解释这段代码") | **Host-native**:标准 Pi / Claude Code 行为,零流程开销 |
|
|
115
|
-
|
|
|
117
|
+
| 想法模糊,需要架构拷问、边界与决策确认 | `/grill-me`(推荐)或 `/imm-brainstorm` | → `/grill-me` 针对设计树逐项穷追猛打敲定决策;`/imm-brainstorm` 进行内置只读需求框架梳理 |
|
|
116
118
|
| 目标明确,需要正规计划与规格 | `/imm-planner` "规划一下深色模式功能" | → `imm-planner` 产出 `TaskIntent` + Spec,包含可执行验收条件 |
|
|
117
119
|
| 计划已确认,准备执行与验证 | `/imm-run` | → Executor 在范围内实现 → 确定性 QA 验收 → 隔离 Review 审查 → 任务结算 |
|
|
118
120
|
| 会话中断或需恢复未完成任务 | `/imm-run` | → 从磁盘状态(`.imm/`)无缝恢复,以 Kernel projection 为准 |
|
|
119
|
-
| 已发布的 Initiative
|
|
121
|
+
| 已发布的 Initiative 批次推进(串行 / 多 Lane 并行) | "无人值守跑完 initiative `<slug>`"(可指定 `--max-parallel 4` 或配置 `Lane max parallel`) | → Host 的 `start_unattended_batch`:一次原生确认绑定 plan digest。无配置时单工作区串行推进;配置并行度时开启多 Lane Git worktree 物理隔离并发执行 |
|
|
120
122
|
| 跨 Host 协作(Claude 规划 + Pi 编码) | 在 Claude Code 中调 `/imm-planner`,切到 Pi 输入 `/imm-run` | → Spec 与 TaskIntent 共享于 Git,Pi 原生弹窗准入并执行 QA/Review 闭环 |
|
|
121
123
|
| PR 被评论 / CI 挂了 | 对该 PR 使用 `/imm-pr-fix` | → 独立修复:在当前 PR 内针对性修复,不创建新 managed 任务 |
|
|
122
124
|
| 文档过时需要清理 | `/imm-doc-prune` | → 只读审计过时文档,仅删除经哈希审批的条目 |
|
|
@@ -125,7 +127,7 @@ Immune-Brain 提供两种清晰的工作模式:日常轻量编码走 **Host-na
|
|
|
125
127
|
|
|
126
128
|
> **核心原则:Skill 显式调用**
|
|
127
129
|
> - **普通输入保持 Host-native**:自然语言提问绝不自动绑架流程或发起 Enrollment。你完全自主决定何时开启严格工程保障。
|
|
128
|
-
> - **Managed
|
|
130
|
+
> - **Managed 工作流显式启动**:需要澄清决策用 `/grill-me`(或 `imm-brainstorm`),制定计划用 `imm-planner`,执行与恢复用 `imm-run`。
|
|
129
131
|
|
|
130
132
|
### 跨 Host 协作:Claude Code 规划 + Pi 编码执行
|
|
131
133
|
|
|
@@ -163,6 +165,146 @@ Immune-Brain 的核心状态与契约完全去会话化(Session-neutral),
|
|
|
163
165
|
|
|
164
166
|
---
|
|
165
167
|
|
|
168
|
+
## 推荐工作流:与 mattpocock/skills 组合使用
|
|
169
|
+
|
|
170
|
+
Immune-Brain 能够在工程进入实施阶段后提供坚不可摧的确定性闭环与质量约束,但在实际软件研发中,绝大多数失败早在编码前就已注定:**大模型在尚未充分遍历设计树、评估技术折中并推演边界条件时,就匆忙上手编码。**
|
|
171
|
+
|
|
172
|
+
为了彻底杜绝盲目开工与范式漂移,生产环境中最推荐的最佳实践组合是将 Matt Pocock 的 **`mattpocock/skills`** 作为上游,与 **Immune-Brain** 构筑的下游确定性引擎组合使用:
|
|
173
|
+
|
|
174
|
+
> **双引擎协同哲学**
|
|
175
|
+
> - **上游苏格拉底式充分摩擦(`grill-me`)**:主动放慢思考节奏。AI 化身为苛刻的技术面试官,在落实任何代码与规格之前,对设计树的每一个分支、技术选型与隐性假设进行穷追猛打,逐一敲定决策。
|
|
176
|
+
> - **下游确定性工程闭环(`imm-planner` + `imm-run`)**:将敲定的共识翻译为不可篡改的机器契约(`TaskIntent` + living Spec),通过宿主原生弹窗由人授权,严格冻结文件边界(`scope_hint`),并由沙箱子进程 QA 真实跑通与隔离审查子代理把关交付。
|
|
177
|
+
|
|
178
|
+
```text
|
|
179
|
+
┌────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
180
|
+
│ 1. 上游苏格拉底式决策对齐 (mattpocock/skills /grill-me) │
|
|
181
|
+
│ 职责: 沿设计树每一个分支进行高压追问,梳理技术权衡与隐性假设,达成架构共识 │
|
|
182
|
+
└───────────────────────────────────────────────────┬────────────────────────────────────────────────────┘
|
|
183
|
+
│ 敲定的决策分支与架构设计共识
|
|
184
|
+
▼
|
|
185
|
+
┌────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
186
|
+
│ 2. 正式机器契约与方案规划 (Immune-Brain /imm-planner) │
|
|
187
|
+
│ 职责: 编写 Living Spec 与 TaskIntent (.intent.json);锁定 scope_hint 与 VerificationDescriptor v2 │
|
|
188
|
+
└───────────────────────────────────────────────────┬────────────────────────────────────────────────────┘
|
|
189
|
+
│ Git 追踪的机器契约制品
|
|
190
|
+
▼
|
|
191
|
+
┌────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
192
|
+
│ 3. 宿主原生人工准入确认 (Native Host Enrollment) │
|
|
193
|
+
│ 职责: 开发者在原生 TUI / MCP 弹窗中核对范围并授权;Kernel 原子记录 Git 基线并获取 SQLite CAS 锁 │
|
|
194
|
+
└───────────────────────────────────────────────────┬────────────────────────────────────────────────────┘
|
|
195
|
+
│ 工作区独占租约
|
|
196
|
+
▼
|
|
197
|
+
┌────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
198
|
+
│ 4. 确定性执行与凭证结算 (Immune-Brain /imm-run) │
|
|
199
|
+
│ 职责: 冻结 Scope 内 Executor 编码 -> 真实子进程 QA (bun test) -> 隔离 Subagent Review -> CAS 凭证结算 │
|
|
200
|
+
└────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### 为什么推荐用 `grill-me` 代替 `imm-brainstorm` 进行决策确认
|
|
204
|
+
|
|
205
|
+
虽然 Immune-Brain 内置了轻量的 `imm-brainstorm` 技能,但面对非平凡业务功能、重大架构调整或安全敏感边界时,**强烈推荐使用 `/grill-me` 作为前置决策工具**:
|
|
206
|
+
|
|
207
|
+
| 维度 | 内置 `imm-brainstorm` | 上游 `/grill-me` (`mattpocock/skills`) | 组合推荐姿态 |
|
|
208
|
+
|---|---|---|---|
|
|
209
|
+
| **生态与安装** | 内置于 Immune-Brain(开箱即用,零依赖) | 来自 `mattpocock/skills` 生态(`npx skills@latest add mattpocock/skills --skill grill-me`) | 由 `/grill-me` 担任上游思想对齐者,Immune-Brain 掌管下游确定性工程闭环 |
|
|
210
|
+
| **交互模式** | 结构化问题框架梳理;批量发问;只读概览 | 单轮迭代式、高压苏格拉底式追问;沿设计树逐项穷尽推演 | `/grill-me` 主动质疑开发者的盲目假设,拒绝模糊妥协 |
|
|
211
|
+
| **推演纪律** | 优先查阅仓库代码,提炼顶层目标与约束风险 | 优先查阅仓库代码,针对每个决策点主动提供带倾向的推荐方案 | 彻底消除“氛围感盲写”(vibe coding),在上游将设计决策压成确定性共识 |
|
|
212
|
+
| **产出形态** | 只读的 `brainstorm_framing` 总结块 | 遍历并收敛完成的完整设计树决策集合 | 将确认后的决策清单无缝输入给 `/imm-planner` 转化为机器契约 |
|
|
213
|
+
| **适用场景** | 轻量需求梳理、离线无网络环境或简单任务 | 复杂业务系统、核心架构重构、多服务联动与高危门禁功能 | 严肃工程研发与生产级任务的**首选推荐标准** |
|
|
214
|
+
|
|
215
|
+
### 安装与配置
|
|
216
|
+
|
|
217
|
+
使用官方 Skills 安装器将 `grill-me` 添加到当前项目或全局环境:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
# 仅添加 mattpocock/skills 中的 grill-me
|
|
221
|
+
npx skills@latest add mattpocock/skills --skill grill-me
|
|
222
|
+
|
|
223
|
+
# 或安装完整套件
|
|
224
|
+
npx skills@latest add mattpocock/skills
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### 典型端到端流水线:`grill-me` → `imm-planner` → `imm-run`
|
|
228
|
+
|
|
229
|
+
1. **第一步:苏格拉底式设计拷问(`/grill-me`)**
|
|
230
|
+
- 执行 `/grill-me "实现多租户 Webhook 分发系统,包含重试退避与防重放机制"`。
|
|
231
|
+
- Agent 会先阅读工程现有代码模式,随后针对设计树展开单点追问(存储选型、幂等方案、退避曲线、错误捕获),并在每个问题后给出明确的推荐选项与权衡说明。
|
|
232
|
+
- 开发者逐一确认直至全部分支收敛:“*决策树已全部收敛,准备开始制定工程计划。*”
|
|
233
|
+
2. **第二步:机器契约与规格规划(`/imm-planner`)**
|
|
234
|
+
- 执行 `/imm-planner "基于刚才 grill-me 敲定的决策方案规划 Webhook 分发功能"`。
|
|
235
|
+
- `imm-planner` 吸收已确认的架构决策并生成:
|
|
236
|
+
- **Living Spec**(`docs/specs/webhook-dispatcher.spec.md`):锁定参考坐标、架构权衡与明确的禁止越界边界(Negative Scope)。
|
|
237
|
+
- **TaskIntent**(`docs/plans/webhook-dispatcher.intent.json`):锁定文件范围 `scope_hint`、风险等级(`material`)与自动化验收命令 `VerificationDescriptor v2`。
|
|
238
|
+
3. **第三步:原生弹窗准入授权(Enrollment Gate)**
|
|
239
|
+
- 将生成的 Spec 与 Plan 纳入 Git 暂存(`git add docs/`)。
|
|
240
|
+
- 执行 `/imm-run`。弹出当前宿主的原生确认界面(Pi TUI 弹窗 / Claude Code MCP 交互弹窗)。
|
|
241
|
+
- 人工点击确认后,Kernel 原子生成 Git 基线快照(`enrollment-baseline.json`)并加持 SQLite CAS 工作区排他锁。
|
|
242
|
+
4. **第四步:物理冻结执行与客观验证(`/imm-run`)**
|
|
243
|
+
- **Executor**:严格在 `scope_hint` 文件信封内编写代码,任何物理逃逸直接 fail-closed 阻断。
|
|
244
|
+
- **确定性 QA 引擎**:Kernel 直接前台拉起子进程执行 `bun test`,以真实退出码 0 判定胜负,拒绝口头汇报。
|
|
245
|
+
- **隔离 Reviewer 审查**:针对 `material`/`critical` 任务,调度独立的只读审查子代理基于 Git blob 制品严格审计。
|
|
246
|
+
- **结算归档**:Kernel 原子落盘证据至 `.imm/audit/<task-id>/` 并释放工作区锁。
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## 实战案例
|
|
251
|
+
|
|
252
|
+
### 案例 1:全新功能从零开发 — 多租户 Webhook 分发系统
|
|
253
|
+
|
|
254
|
+
- **目标**:实现一套生产级多租户 Webhook 分发引擎,具备 HMAC 密钥签名、指数退避重试与防重放攻击能力。
|
|
255
|
+
- **不使用本工作流的常见缺陷**:AI 拿到需求后立即动手写文件,随意引入未经评估的外部三方库,忘记校验时间戳导致重放漏洞,留下内存泄漏的定时器,并且在未做超时中断验证的情况下直接宣称“开发完成”。
|
|
256
|
+
- **实战流程**:
|
|
257
|
+
1. **上游高压对齐(`/grill-me`)**:
|
|
258
|
+
- *问题 1(持久化选型)*:SQLite 还是外部队列?*推荐方案*:复用工程现有的 SQLite CAS 表,避免引入额外基础设施依赖。
|
|
259
|
+
- *问题 2(安全规范)*:如何防御重放攻击?*推荐方案*:强制要求 `X-Webhook-Timestamp` 请求头,允许最大 5 分钟时钟容差,使用 HMAC-SHA256 签名。
|
|
260
|
+
- *问题 3(韧性保障)*:重试策略与超时机制?*推荐方案*:采用 Full Jitter 指数退避,最多重试 5 次,单次请求通过 `AbortController` 施加 10 秒硬超时。
|
|
261
|
+
- *成果*:全套架构权衡在 3 分钟人机对话内全部锁定。
|
|
262
|
+
2. **机器契约规划(`/imm-planner`)**:
|
|
263
|
+
- Planner 编写 `docs/specs/webhook-dispatcher.spec.md`,明确标记 Negative Scope(`src/auth/` 与 `src/billing/` 严禁改动)。
|
|
264
|
+
- 生成 `docs/plans/task-webhook-dispatcher.intent.json`,定级为 `material` 风险,配置验收命令真机运行 `bun test tests/webhook-dispatcher.test.ts`。
|
|
265
|
+
3. **原生弹窗准入确认**:
|
|
266
|
+
- 开发者在 Git 中检视 diff,并在 Pi TUI / Claude Code 弹窗中授权。
|
|
267
|
+
4. **执行、QA 验证与审查(`/imm-run`)**:
|
|
268
|
+
- Executor 在 `scope_hint` 限定范围内编写代码。
|
|
269
|
+
- Kernel 真机拉起沙箱执行 `bun test tests/webhook-dispatcher.test.ts`,验证退出码为 `0`。
|
|
270
|
+
- 隔离的 Reviewer 子代理审计 Git blob,核实无任何越界改动并检查异常处理规范。
|
|
271
|
+
- Kernel 原子落盘凭据至 `.imm/audit/<task-id>/`。
|
|
272
|
+
|
|
273
|
+
### 案例 2:关键架构重构 — CAS 状态机存储引擎迁移(v1 → v2)
|
|
274
|
+
|
|
275
|
+
- **目标**:将持久化层从历史遗留的 JSON 文件平滑迁移为基于 SQLite 的原子 CAS 引擎,并保持零停机回滚和历史只读审计能力。
|
|
276
|
+
- **不使用本工作流的常见缺陷**:模型在底层存储重构时极易造成静默数据损坏、擅自删除历史兼容路径,并通过篡改断言在假测试中制造“通过”。
|
|
277
|
+
- **实战流程**:
|
|
278
|
+
1. **上游高压对齐(`/grill-me`)**:
|
|
279
|
+
- *拷问焦点*:“迁移期间若有正在运行的 v1 任务该如何处理?推荐方案:实施严格的排空检查(`drain_required`),拒绝双写,存在活跃任务时立即中断拒绝迁移。”
|
|
280
|
+
- *拷问焦点*:“回滚时如何保证 WAL 不损坏?推荐方案:采用单文件事务、操作系统级排他文件锁与不可变 Git 快照。”
|
|
281
|
+
2. **代码强制兜底规划(`/imm-planner`)**:
|
|
282
|
+
- 由于改动触碰了 `runtime/kernel/storage.ts`,Kernel 规则强制将风险等级锁定至 `critical` 底线。
|
|
283
|
+
- Planner 精准锚定代码坐标(`storage.ts:120`),并配置包含真实历史迁移固件的验收测试。
|
|
284
|
+
3. **原生准入确认**:开发者在宿主原生弹窗中看到被强制锁定的 `critical` 风险与基线快照,点击授权。
|
|
285
|
+
4. **确定性 QA 与对抗性审查(`/imm-run`)**:
|
|
286
|
+
- 真机执行全量回归套件与真实历史固件迁移测试。
|
|
287
|
+
- 独立的 Devil's Advocate Reviewer 子代理针对不可变 Git blob 展开对抗性审计,重点核验向后兼容逻辑。
|
|
288
|
+
- 原子结项并写入不可篡改的审计记录。
|
|
289
|
+
|
|
290
|
+
### 案例 3:跨 Host 协同开发 — Claude Code(深度追问与方案规划)+ Pi(极速前台执行与真机验收)
|
|
291
|
+
|
|
292
|
+
- **目标**:最大化利用桌面端旗舰模型的深度推理进行架构推演,同时在极速本地/远程终端中执行代码,大幅节省 Token 成本并提升交付速度。
|
|
293
|
+
- **实战流程**:
|
|
294
|
+
1. **在 Claude Code(桌面端)中**:
|
|
295
|
+
- 运行 `/grill-me`(来自 `mattpocock/skills`),利用 Claude 旗舰推理能力充分拷问架构方案。
|
|
296
|
+
- 运行 `/imm-planner`,生成精准定位到代码行号的 Living Spec 与 `TaskIntent` 机器契约。
|
|
297
|
+
- 将制品提交或暂存到 Git(`git add docs/ && git commit -m "docs: webhook spec and plan"`)。
|
|
298
|
+
2. **切换到 Pi(本地或远程终端)中**:
|
|
299
|
+
- 在同一工作区中打开 Pi。
|
|
300
|
+
- 输入 `/imm-run`。Pi 自动识别到暂存的 `TaskIntent`,弹出原生 TUI 弹窗提示准入。
|
|
301
|
+
- Pi 的 Executor 角色调度高吞吐、高性价比模型(Fast / Mid Tier)在锁定的文件边界内写代码。
|
|
302
|
+
- 本地进程直接执行 `bun test` 产出真实退出码凭证。
|
|
303
|
+
- 审查通过后 Kernel 结算结项。
|
|
304
|
+
3. **成果**:跨 Host 状态零损失无缝衔接,同时节约 60%~70% 的旗舰推理 Token 支出。
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
166
308
|
## 核心设计哲学:把“判断”变成“查表”,用确定性工程驾驭多模型
|
|
167
309
|
|
|
168
310
|
大模型(尤其是轻量/高性价比的 Fast 档模型)在工程落地中最容易失败的原因,不是代码语法不过关,而是死在**语义含糊、过度发挥**与**逃避严格验证**上。
|
|
@@ -395,7 +537,7 @@ flowchart TD
|
|
|
395
537
|
- **按险定级与确定性兜底**:`routine` 仅需 QA;`material`/`critical` 必须追加独立只读 Reviewer 产出结构化裁决。触碰核心权威路径强制定级为 `material`。
|
|
396
538
|
- **反证机制 (Live Refutation)**:主观 Review finding 可由真实通过的新鲜 QA 证据反证驳回;代码发生改动后反证自动失效并重新阻塞。
|
|
397
539
|
- **不可变审计落盘**:任务结项时,完整的 `TaskRecord`、Git blob 打包的 `ReviewBundle`、QA Attestation 凭证原子沉淀至 `.imm/audit/<task-id>/` 并受 Git 追踪。
|
|
398
|
-
-
|
|
540
|
+
- **批处理与多 Lane 并行 (Unattended Batch & Parallel Lanes)**:基于 GitHub Issue / `plan_digest` 推进。支持默认单分支串行或多 Lane 物理并行模式;并行时协调者基于 `scope_hint` 互斥拓扑调度独立 Git worktree 并发执行,结算时通过集成守卫(Integration Guard)在候选提交上重跑确定性验收命令再 fast-forward 主分支,杜绝并发污染。
|
|
399
541
|
|
|
400
542
|
核心不变量:
|
|
401
543
|
|
|
@@ -410,12 +552,75 @@ flowchart TD
|
|
|
410
552
|
|
|
411
553
|
## 无人值守批次运行
|
|
412
554
|
|
|
413
|
-
当一个 Initiative
|
|
555
|
+
当一个 Initiative 下包含多个已就绪的 child 任务时,开发者无需逐个手动触发 `imm-run`,可通过 Host 原生 privileged tool `start_unattended_batch` 进行整批无人值守推进。
|
|
556
|
+
|
|
557
|
+
系统支持两种批次运行形态:**默认串行模式** 与 **多 Lane 并行模式(Parallel Batch Lanes)**。
|
|
558
|
+
|
|
559
|
+
### 1. 批次运行模式概览
|
|
560
|
+
|
|
561
|
+
| 维度 | 串行批次 (Serial Batch,默认) | 多 Lane 并行批次 (Parallel Batch Lanes) |
|
|
562
|
+
|---|---|---|
|
|
563
|
+
| **开启方式** | 调用 `start_unattended_batch(slug)` | 显式传入 `max_parallel` 或在配置中设定 `Lane max parallel: <n>` |
|
|
564
|
+
| **工作区拓扑** | 共享唯一的专属批次分支(`imm-batch/<slug>`) | Coordinator 维护主批次分支;各并发任务独占独立 Git worktree(`imm-lane/<task-id>` 分支) |
|
|
565
|
+
| **调度策略** | 严格按依赖拓扑层级单任务逐个串行推进 | 互不依赖且物理修改范围(`scope_hint`)**完全不重叠(Scope-disjoint)**的任务并发执行 |
|
|
566
|
+
| **Authority 边界** | 协调者按序推进单个任务的本地 Authority Store | 每个 Lane 拥有完全隔离的本地 Authority Store,各自独立加锁,零全局 CAS 竞争 |
|
|
567
|
+
| **集成机制** | 任务验证完成直接在批次分支提交 1 个 commit | Lane 结算后通过 Git plumbing 校验变更等价性,并在候选提交上重跑集成守卫(Integration Guard)再 fast-forward |
|
|
568
|
+
| **适用场景** | 任务数少、前后改动文件强耦合、单核/受限环境 | 大中型 Initiative、多模块解耦子任务、多核或多 Host 算力充裕场景 |
|
|
569
|
+
|
|
570
|
+
### 2. 批次授权与运行红线
|
|
571
|
+
|
|
572
|
+
- **入口显式且单一授权:** 未调用 `start_unattended_batch` 之前不存在任何批次状态或分支;未调用时 `imm-run` 行为与逐任务 Enrollment 完全一致。调用时由原生 gate(Pi TUI 弹窗或 Claude MCP elicitation)一次性展示有序任务清单与全局 `plan_digest`,用户的单次确认即为整批执行提供完备授权。
|
|
573
|
+
- **Child Authority 守恒:** 批次仅代表授权范围的聚合,绝非降低工程标准。每个 child 依然由 Kernel 单独执行 Enrollment、物理 Scope 冻结、真实子进程 QA、隔离 Review 与独立的 `TaskRecord` 结算。批次只是一次授权的覆盖范围,不是新的授权层级。
|
|
574
|
+
- **确定性执行边界:** 仅推进已发布且非 `critical` 的 child 任务;遇到人工决策挂起(`needs_human`)、预算/超时中断或提交异常时立即安全暂停批次,被阻断任务的下游依赖标记为跳过(`skipped_blocked`)而非无序推进。批次运行器不擅自 push、不开 PR、不代替用户结算决策。
|
|
575
|
+
|
|
576
|
+
### 3. 多 Lane 并行流水线与架构(Parallel Batch Lanes)
|
|
577
|
+
|
|
578
|
+
在多 Lane 并行模式下,系统通过 Coordinator(Parent Host)、`lane-steward`(工作区管家)与 Lane Executor Host(执行宿主)的严密协作,实现物理级并发隔离:
|
|
579
|
+
|
|
580
|
+
```mermaid
|
|
581
|
+
sequenceDiagram
|
|
582
|
+
participant P as Coordinator (Parent Host)
|
|
583
|
+
participant B as Batch Runtime
|
|
584
|
+
participant S as lane-steward 角色
|
|
585
|
+
participant L as Lane Executor Host (Pi / Claude)
|
|
586
|
+
participant K as Lane Kernel (独立 Store)
|
|
587
|
+
|
|
588
|
+
Note over P,B: 1. 拓扑分析与并发调度 (Schedule)
|
|
589
|
+
P->>B: start_unattended_batch(slug, max_parallel)
|
|
590
|
+
B-->>P: handoffs: 调度准备 (provision Lane A, Lane B)
|
|
591
|
+
|
|
592
|
+
Note over P,S: 2. 物理隔离 Worktree 分配 (Provision & Admit)
|
|
593
|
+
P->>S: 调度创建 worktree (分支 imm-lane/..., 基线 batch base)
|
|
594
|
+
S-->>P: 返回独立 worktree 路径
|
|
595
|
+
P->>B: 提交 lane_offers 准入校验 (无重叠/干净度/基线校验)
|
|
596
|
+
|
|
597
|
+
Note over P,L: 3. 监督式并行执行 (Supervised Execution)
|
|
598
|
+
B-->>P: handoffs: 启动 Executor A, Executor B
|
|
599
|
+
P->>L: 拉起独立后台会话执行 imm-run (支持配置不同 Host/模型)
|
|
600
|
+
L->>K: 独立运行: Scope 冻结 -> 确定性 QA -> 隔离 Review -> 结算
|
|
601
|
+
|
|
602
|
+
Note over P,B: 4. 集成守卫与主分支快进 (Integration Guard & Fast-Forward)
|
|
603
|
+
L-->>P: 某个 Lane 结束通知
|
|
604
|
+
P->>B: 协调者推进 (reconcile)
|
|
605
|
+
B->>K: 读取 Lane 结算凭证与 commit
|
|
606
|
+
B->>B: 构建候选 commit + 重跑集成守卫 (自身与已集成兄弟描述符)
|
|
607
|
+
B->>B: Fast-forward 主批次分支 (1 child 1 commit)
|
|
608
|
+
B-->>P: handoffs: release Lane A / provision 新就绪 Lane C
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
#### 并行执行的核心机制:
|
|
612
|
+
|
|
613
|
+
1. **按 Scope 互斥拓扑调度 (Scope-Disjoint Scheduling)**:
|
|
614
|
+
Coordinator 实时计算任务依赖图与路径重叠度。仅当任务的前置依赖已全部集成,且其 `scope_hint` 与当前所有进行中(in-flight)Lane 的路径集合**在物理上完全无交集**时,才允许并发派发;存在路径重叠的任务自动排队,直到前序冲突 Lane 集成完毕。
|
|
615
|
+
2. **监督式会话生命周期 (Supervised Host Sessions)**:
|
|
616
|
+
Parent Host 为每个 Lane 拉起独立的 Executor Host 进程(支持跨 Host 与模型档位配置,如 Pi 或 Claude Code)。Parent 监控会话退出事件,会话结束即触发下一轮协调;Parent 不轮询、不猜测终端输出。当 Parent 运行在 Herdr 内时,会为每个 Lane 的 Executor Host 开一个独立 tab,且绝不会替开发者回答其中的信任、登录或权限对话框。
|
|
617
|
+
3. **集成守卫与候选验证 (Integration Guard)**:
|
|
618
|
+
为防止并发修改产生隐式冲突,Lane 结算后不会盲目合入主分支。Coordinator 在 Git plumbing 层面构建候选提交,并在候选树上**重跑当前任务以及自其分叉以来所有已合入兄弟任务的确定性验收描述符**。只有全部再次跑通,才通过 fast-forward 原子合入主批次分支。
|
|
619
|
+
4. **强故障隔离 (Fault Isolation)**:
|
|
620
|
+
若某个 Lane 出现测试失败、评审驳回或集成冲突,主批次分支保持零写入(Zero-write),仅该任务被置为 `needs_human`,其后续依赖标记为 `skipped_blocked`;其他无冲突的并行 Lane 继续正常推进。
|
|
621
|
+
5. **安全回收纪律 (Agents Only Create)**:
|
|
622
|
+
Parent 与 `lane-steward` 角色仅负责创建 Lane(worktree)和终端 tab,绝不擅自关闭 tab、不终止外部会话、不自动删除用户磁盘上的 worktree。任务集成完成后,系统明确告知开发者哪些 Lane 已可安全回收,由开发者自主清理。
|
|
414
623
|
|
|
415
|
-
- **入口显式:** Host 的 privileged tool `start_unattended_batch`(参数为 Initiative slug)。未调用之前不存在任何 batch state、分支或授权;未调用时 `imm-run` 行为与逐任务 Enrollment 完全一致。
|
|
416
|
-
- **一次确认、一个 digest:** 原生 gate(Pi TUI 弹窗或 Claude MCP elicitation)展示有序 child 列表与共享 plan digest,这一次 literal-user 确认就是全部 Batch Authorization。
|
|
417
|
-
- **每个 child 的 authority 不变:** 每个 child 仍由 Kernel 单独 Enrollment、冻结、QA、Review 并以自己的 `TaskRecord` 结算。批次只是一次授权的覆盖范围,不是新的授权层级。
|
|
418
|
-
- **边界:** 只跑已发布且非 `critical` 的 child,在专属 batch 分支上串行执行;一旦某个 child 需要人决策,或遇到预算/截止时间/授权/提交失败就暂停,被阻塞 child 的依赖项标记为跳过而不是调序。runner 不 push、不开 PR、不代替用户结算 decision、也不创建/切换/删除 Git worktree。
|
|
419
624
|
|
|
420
625
|
---
|
|
421
626
|
|
|
@@ -427,6 +632,10 @@ Immune-Brain **没有独立配置文件**,偏好设置写在仓库根目录下
|
|
|
427
632
|
## Immune-Brain Preferences
|
|
428
633
|
|
|
429
634
|
- Initiative carrier default: github # 或 local
|
|
635
|
+
- Lane max parallel: 4 # 可选;开启 lane mode
|
|
636
|
+
- Lane Executor Host: claude-code # 可选;或 pi
|
|
637
|
+
- Lane Executor model: <model id> # 可选;需同时配置 Lane Executor Host
|
|
638
|
+
- Lane Executor effort: high # 可选;需同时配置 Lane Executor Host
|
|
430
639
|
```
|
|
431
640
|
|
|
432
641
|
| 偏好 | 选项 | 默认 | 说明 |
|
|
@@ -434,6 +643,10 @@ Immune-Brain **没有独立配置文件**,偏好设置写在仓库根目录下
|
|
|
434
643
|
| 回复语言 | 任意自然语言 | 仓库 `AGENTS.md` | 机器契约/路径/标识符保持原文 |
|
|
435
644
|
| Initiative 载体 | `local` / `github` | 无默认,Planner 询问 | 仅当提案拆分为多个 TaskIntent 时生效 |
|
|
436
645
|
| Advisory subagent | 允许 / 单人 | 允许 | 受 Pi host 策略与用户显式指令约束 |
|
|
646
|
+
| Lane max parallel | ≥ 1 的整数 | 无默认,批次保持串行 | 启动批次时作为 `max_parallel` 传入;续跑沿用批次记录的值 |
|
|
647
|
+
| Lane Executor Host | `claude-code` / `pi` | 无默认,优先用 Parent 同类 Host | 所有 Lane 都用该 Host,不回退到另一个 |
|
|
648
|
+
| Lane Executor model | 该 Host 的 model ID | 无默认,用 Executor Host 自己的默认 | 仅在配置了 `Lane Executor Host` 时生效 |
|
|
649
|
+
| Lane Executor effort | 该 Host 的强度档位 | 无默认,用 Executor Host 自己的默认 | 仅在配置了 `Lane Executor Host` 时生效;Claude Code 传 `--effort`,Pi 传 `--thinking` |
|
|
437
650
|
|
|
438
651
|
优先级:**当前消息 > 仓库 agent 指令文件 > 用户级 agent 指令文件 > 询问**。Skill 会直接读取这些文件,因此即使 Host 不自动加载该文件,偏好依然生效。
|
|
439
652
|
|
|
@@ -485,6 +698,10 @@ docs/specs/ # Living specs(原地更新)
|
|
|
485
698
|
|
|
486
699
|
**偏好配置为什么写在 AGENTS.md / CLAUDE.md 而不是独立配置文件?** 遵循“零外部负担、宿主原生”原则。将偏好(如 Initiative 载体、交互语言)声明在项目根目录受版本控制的指令文件中,既能在不同 Host 之间透明生效,又避免了本地全局配置文件容易漂移、团队成员无法共享的痛点。
|
|
487
700
|
|
|
701
|
+
**为什么在复杂任务中推荐用 `grill-me` 替代 `imm-brainstorm` 进行决策确认?** `imm-brainstorm` 是轻量内置的免安装工具,用于快速对齐顶层问题框架。而来自 `mattpocock/skills` 的 `grill-me` 则具备极具侵略性的苏格拉底式发问机制,能够沿着设计树分支主动提供带偏好的推荐方案并穷追猛打,促使开发者做出明确抉择。对于非平凡功能开发、重大架构重构或安全门禁边界,在上游先用 `grill-me` 彻底敲定决策树再输入给 `imm-planner`,能产出颗粒度极高、无后顾之忧的 Living Spec,从根源上杜绝下游返工。
|
|
702
|
+
|
|
703
|
+
**我是否必须安装 `mattpocock/skills` 才能使用 Immune-Brain?** 不是。Immune-Brain 本身是完全独立自闭环的,内置的 `imm-brainstorm` 可以零配置直接使用。与 `mattpocock/skills` 的组合属于强烈推荐的工程进阶工作流,旨在为严谨团队提供更极致的决策防线。
|
|
704
|
+
|
|
488
705
|
**支持哪些 AI 编程工具?** Pi 与 Claude Code 是支持的宿主(Claude Code 最低版本为 `2.1.236`)。两者共享同一套确定性 Kernel 核心、质量保障机制与工具链。
|
|
489
706
|
|
|
490
707
|
---
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "immune-brain",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.1.1",
|
|
4
4
|
"description": "Immune-Brain agent skill system",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"plugins/immune-brain/runtime/workspace_scope.ts",
|
|
79
79
|
"plugins/immune-brain/runtime/managed_task_routing_policy.ts",
|
|
80
80
|
"plugins/immune-brain/runtime/github_issue_tracker.ts",
|
|
81
|
+
"plugins/immune-brain/runtime/local_initiative.ts",
|
|
81
82
|
"plugins/immune-brain/runtime/verification_descriptor.ts",
|
|
82
83
|
"plugins/immune-brain/runtime/role_prompt_bridge.ts",
|
|
83
84
|
"plugins/immune-brain/runtime/loop_contract.ts",
|
|
@@ -139,6 +139,7 @@ const LOOP_TARGETS = [
|
|
|
139
139
|
"architecture-exploration",
|
|
140
140
|
"advisory-review",
|
|
141
141
|
"compounder",
|
|
142
|
+
"lane-supply",
|
|
142
143
|
] as const;
|
|
143
144
|
const LOOP_DIRECT_ROLES = ["qa", "code-review", "ui-review"] as const;
|
|
144
145
|
const KERNEL_OPERATIONS = [
|
|
@@ -370,8 +371,12 @@ export default function (
|
|
|
370
371
|
if (ctx.mode !== "tui") return;
|
|
371
372
|
await refreshTaskRail(ctx);
|
|
372
373
|
});
|
|
373
|
-
pi.on("tool_call", (event: { toolName?: string; input?: unknown }, ctx?: ExtensionContext) => {
|
|
374
|
+
pi.on("tool_call", (event: { toolName?: string; input?: unknown; toolCallId?: string }, ctx?: ExtensionContext) => {
|
|
374
375
|
if (ctx) railContext = ctx;
|
|
376
|
+
if (event.toolName === "Agent") {
|
|
377
|
+
// ADR 0017: correlate a reserved reviewer dispatch to its reservation.
|
|
378
|
+
progression.piReviewHost.observeReviewDispatch(event.input as { prompt?: unknown; subagent_type?: unknown } | undefined, event.toolCallId);
|
|
379
|
+
}
|
|
375
380
|
if (event.toolName === "imm_canary_enrollment" && ctx) {
|
|
376
381
|
const input = event.input as { task_id?: string } | undefined;
|
|
377
382
|
if (input?.task_id) presentTaskRail(ctx, {
|
|
@@ -384,7 +389,14 @@ export default function (
|
|
|
384
389
|
});
|
|
385
390
|
pi.on("tool_result", (event: unknown, ctx?: ExtensionContext) => {
|
|
386
391
|
if (ctx) railContext = ctx;
|
|
387
|
-
const result = event as { toolName?: string; details?: Record<string, unknown> };
|
|
392
|
+
const result = event as { toolName?: string; details?: Record<string, unknown>; toolCallId?: string; content?: Array<{ type?: string; text?: string }> };
|
|
393
|
+
if (result.toolName === "Agent" && result.toolCallId) {
|
|
394
|
+
// ADR 0017: record the reviewer's own result bytes for receipt-bound submission.
|
|
395
|
+
const text = Array.isArray(result.content)
|
|
396
|
+
? result.content.filter((part) => typeof part?.text === "string").map((part) => part.text as string).join("\n")
|
|
397
|
+
: "";
|
|
398
|
+
progression.piReviewHost.observeReviewResult(result.toolCallId, text);
|
|
399
|
+
}
|
|
388
400
|
if (result.toolName === "imm_canary_enrollment" && ctx) {
|
|
389
401
|
const taskId = typeof result.details?.task_id === "string" ? result.details.task_id : undefined;
|
|
390
402
|
if (taskId) presentTaskRailResult(ctx, taskId, result.details);
|
|
@@ -405,7 +417,7 @@ export default function (
|
|
|
405
417
|
promptGuidelines: [
|
|
406
418
|
"Only the exact enrolled canary task is routable; verify the active backend claim first via status.",
|
|
407
419
|
"After implementation and focused verification, freeze the artifacts, call advance_assurance, and consume its direct terminal result; do not poll or create a detached job.",
|
|
408
|
-
"When advance_assurance returns review_ready, invoke the foreground Agent from agent_params once, then
|
|
420
|
+
"When advance_assurance returns review_ready, invoke the foreground Agent from agent_params once, then call submit_review: omit the verdict to apply the observed reviewer result, or relay its structured verdict exactly.",
|
|
409
421
|
"For a complete breaking revision, call approve_breaking_intent_revision with the complete next_intent directly; do not ask for chat pre-confirmation because the host opens the single native confirmation before applying it.",
|
|
410
422
|
"For a proven stale authority claim, call repair_authority_state directly; the Kernel revalidates and removes only the redundant claim without user interaction.",
|
|
411
423
|
"After awaiting_user, call request_authorization directly so the host opens the single native confirmation; do not ask for chat pre-confirmation or ask the user to copy or report a command.",
|
|
@@ -415,7 +427,7 @@ export default function (
|
|
|
415
427
|
action: Type.Union([
|
|
416
428
|
Type.Object({ op: Type.Literal("status") }),
|
|
417
429
|
Type.Object({ op: Type.Literal("advance_assurance") }),
|
|
418
|
-
Type.Object({ op: Type.Literal("submit_review"), verdict: Type.Unknown() }),
|
|
430
|
+
Type.Object({ op: Type.Literal("submit_review"), verdict: Type.Optional(Type.Unknown()) }),
|
|
419
431
|
Type.Object({ op: Type.Literal("request_authorization") }),
|
|
420
432
|
Type.Object({ op: Type.Literal("request_stop") }),
|
|
421
433
|
Type.Object({ op: Type.Literal("repair_authority_state") }),
|
|
@@ -548,7 +560,7 @@ export default function (
|
|
|
548
560
|
presentTaskRailResult(ctx, taskId, update.details as Record<string, unknown> | undefined);
|
|
549
561
|
})
|
|
550
562
|
: action.op === "submit_review"
|
|
551
|
-
? await progression.
|
|
563
|
+
? await progression.submitMediated(taskId, ctx, action.verdict)
|
|
552
564
|
: action.op === "approve_breaking_intent_revision"
|
|
553
565
|
? await authorizeExactOperation(
|
|
554
566
|
taskId,
|
|
@@ -1508,6 +1520,7 @@ async function enrichAssuranceResult(
|
|
|
1508
1520
|
function nextActionForAssuranceResult(result: Record<string, unknown>, taskState: AssuranceTaskState): string {
|
|
1509
1521
|
const derived = result.recovery as { next_action: string } | undefined;
|
|
1510
1522
|
if (derived) return derived.next_action;
|
|
1523
|
+
if (typeof result.recovery_action === "string") return result.recovery_action;
|
|
1511
1524
|
const recovery = recoveryActionForAssuranceFailure(
|
|
1512
1525
|
"error" in taskState ? taskState.error : result.reason,
|
|
1513
1526
|
);
|