immune-brain 4.5.0 → 5.0.0
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 +157 -39
- package/README.zh-CN.md +160 -40
- package/package.json +1 -1
- package/plugins/immune-brain/.claude-plugin/plugin.json +1 -1
- package/plugins/immune-brain/.pi-extension/imm-canary-enroll.ts +42 -45
- package/plugins/immune-brain/.pi-extension/imm-canary-work.ts +189 -476
- package/plugins/immune-brain/.pi-extension/imm-unattended-batch.ts +77 -102
- package/plugins/immune-brain/.pi-extension/pi-canary-assurance-progression.ts +7 -2
- package/plugins/immune-brain/.pi-extension/tsconfig.json +2 -2
- package/plugins/immune-brain/agents/immune-brain-advisory-reviewer.md +23 -0
- package/plugins/immune-brain/agents/immune-brain-qa.md +42 -0
- package/plugins/immune-brain/agents/immune-brain-reviewer.md +90 -1
- package/plugins/immune-brain/agents/immune-brain-ui-review.md +21 -0
- package/plugins/immune-brain/dist/BASELINE.md +4 -4
- package/plugins/immune-brain/dist/claude/mcp-server.mjs +9924 -9654
- package/plugins/immune-brain/dist/docs/reference/planning-quality-gate.md +3 -3
- package/plugins/immune-brain/dist/docs/reference/subagent-dispatch-protocol.md +30 -1
- package/plugins/immune-brain/dist/imm-brainstorm.md +1 -1
- package/plugins/immune-brain/dist/imm-doc-prune.md +2 -2
- package/plugins/immune-brain/dist/{imm-agent-doc-maintain.md → imm-doc-slim.md} +9 -9
- package/plugins/immune-brain/dist/imm-planner.md +60 -20
- package/plugins/immune-brain/dist/imm-pr-fix.md +1 -1
- package/plugins/immune-brain/dist/{imm-review-retro.md → imm-retro.md} +26 -13
- package/plugins/immune-brain/dist/{imm-loop.md → imm-run.md} +44 -11
- package/plugins/immune-brain/dist/registry.yaml +9 -9
- package/plugins/immune-brain/dist/role-prompts/code-review.md +7 -0
- package/plugins/immune-brain/dist/role-prompts/executor.md +35 -2
- package/plugins/immune-brain/runtime/assurance/coordinator.ts +138 -69
- package/plugins/immune-brain/runtime/assurance/host_port.ts +20 -0
- package/plugins/immune-brain/runtime/assurance/qa.ts +2 -2
- package/plugins/immune-brain/runtime/assurance/review_evidence.ts +4 -0
- package/plugins/immune-brain/runtime/assurance/verdict_authority.ts +347 -0
- package/plugins/immune-brain/runtime/claude/interaction.ts +1 -2
- package/plugins/immune-brain/runtime/claude/kernel_ports.ts +135 -396
- package/plugins/immune-brain/runtime/claude/mcp_server.ts +5 -4
- package/plugins/immune-brain/runtime/claude/review_host.ts +63 -16
- package/plugins/immune-brain/runtime/claude/role_agents.ts +83 -0
- package/plugins/immune-brain/runtime/commands/kernel.ts +3 -6
- package/plugins/immune-brain/runtime/github_issue_tracker.ts +738 -677
- package/plugins/immune-brain/runtime/kernel/application.ts +7 -7
- package/plugins/immune-brain/runtime/kernel/assurance_projection.ts +15 -8
- package/plugins/immune-brain/runtime/kernel/authority_port.ts +5 -14
- package/plugins/immune-brain/runtime/kernel/batch_authority.ts +30 -49
- package/plugins/immune-brain/runtime/kernel/canary_application.ts +6 -5
- package/plugins/immune-brain/runtime/kernel/canary_eligibility.ts +0 -1
- package/plugins/immune-brain/runtime/kernel/capability_registry.ts +7 -9
- package/plugins/immune-brain/runtime/kernel/enrollment.ts +170 -17
- package/plugins/immune-brain/runtime/kernel/enrollment_authority.ts +5 -11
- package/plugins/immune-brain/runtime/kernel/index.ts +3 -1
- package/plugins/immune-brain/runtime/kernel/storage.ts +170 -11
- package/plugins/immune-brain/runtime/kernel/storage_paths.ts +13 -0
- package/plugins/immune-brain/runtime/kernel/types.ts +2 -1
- package/plugins/immune-brain/runtime/kernel/validation.ts +3 -1
- package/plugins/immune-brain/runtime/loop_contract.ts +22 -22
- package/plugins/immune-brain/runtime/plugin_version.ts +1 -1
- package/plugins/immune-brain/runtime/prompts/code-review.md +7 -0
- package/plugins/immune-brain/runtime/prompts/executor.md +35 -2
- package/plugins/immune-brain/runtime/role_prompt_bridge.ts +27 -0
- package/plugins/immune-brain/runtime/unattended/batch_git.ts +66 -28
- package/plugins/immune-brain/runtime/unattended/batch_kernel_port.ts +106 -0
- package/plugins/immune-brain/runtime/unattended/batch_plan.ts +3 -9
- package/plugins/immune-brain/runtime/unattended/batch_preflight.ts +132 -45
- package/plugins/immune-brain/runtime/unattended/batch_reasons.ts +0 -6
- package/plugins/immune-brain/runtime/unattended/batch_reconfirmation.ts +40 -36
- package/plugins/immune-brain/runtime/unattended/batch_runner.ts +98 -209
- package/plugins/immune-brain/runtime/unattended/batch_state.ts +36 -14
- package/plugins/immune-brain/runtime/unattended/types.ts +0 -2
- package/plugins/immune-brain/runtime/workspace_scope.ts +78 -8
- package/plugins/immune-brain/skills/BASELINE.md +4 -4
- package/plugins/immune-brain/skills/imm-doc-prune/SKILL.md +1 -1
- package/plugins/immune-brain/skills/{imm-agent-doc-maintain → imm-doc-slim}/SKILL.md +9 -9
- package/plugins/immune-brain/skills/imm-planner/SKILL.md +4 -2
- package/plugins/immune-brain/skills/imm-pr-fix/SKILL.md +1 -1
- package/plugins/immune-brain/skills/{imm-review-retro → imm-retro}/SKILL.md +7 -7
- package/plugins/immune-brain/skills/{imm-review-retro → imm-retro}/scripts/review_retro.ts +46 -21
- package/plugins/immune-brain/skills/{imm-loop → imm-run}/SKILL.md +7 -7
- package/plugins/immune-brain/skills/registry.yaml +9 -9
- package/plugins/immune-brain/.pi-extension/runtime-stub.ts +0 -584
- package/plugins/immune-brain/runtime/unattended/confirmation_deadline.ts +0 -33
package/README.zh-CN.md
CHANGED
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
Immune-Brain 为 AI 编程工具(**Pi** 与 **Claude Code**)提供结构化的工程工作流保障:
|
|
12
12
|
|
|
13
13
|
- **日常对话零负担** — 普通问答、单点代码修改与探索性对话完全保持 Host 原生体验,不拦截、不强加流程。
|
|
14
|
-
- **需要严谨时显式启用** — 遇到复杂功能开发或高保证任务时,显式调用 `imm-brainstorm`、`imm-planner` 或 `imm-
|
|
14
|
+
- **需要严谨时显式启用** — 遇到复杂功能开发或高保证任务时,显式调用 `imm-brainstorm`、`imm-planner` 或 `imm-run`。
|
|
15
15
|
- **计划变为可追踪的任务**(`TaskIntent` + `TaskRecord`) — 进度落盘持久化(Git + `.imm/`),会话重启或上下文清理后仍可无缝恢复。
|
|
16
16
|
- **质量由代码强制保障** — 自动化 QA 验收与隔离式 Reviewer 审查必须通过,任务才会结算完成。
|
|
17
|
-
- **已就绪的 Initiative 可以整批运行** — 一次确认的 Batch Authorization 让 `imm-
|
|
17
|
+
- **已就绪的 Initiative 可以整批运行** — 一次确认的 Batch Authorization 让 `imm-run` 串行推进已发布 Initiative 的各个 child,而每个 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,7 @@ Pi 与 Claude Code 是支持的宿主。未声明的适配器仍不受支持。C
|
|
|
25
25
|
- [安装](#安装)
|
|
26
26
|
- [快速开始](#快速开始)
|
|
27
27
|
- [如何使用](#如何使用)
|
|
28
|
+
- [核心设计哲学:把“判断”变成“查表”](#核心设计哲学把判断变成查表用确定性工程驾驭多模型)
|
|
28
29
|
- [7 个 Skills](#7-个-skills)
|
|
29
30
|
- [生命周期](#生命周期)
|
|
30
31
|
- [无人值守批次运行](#无人值守批次运行)
|
|
@@ -51,7 +52,7 @@ Pi 通过 `package.json`(或全局 Pi 配置)自动发现 Skills 与扩展
|
|
|
51
52
|
}
|
|
52
53
|
```
|
|
53
54
|
|
|
54
|
-
无需额外 server 配置,通过 Pi 安装本 package 后
|
|
55
|
+
无需额外 server 配置,通过 Pi 安装本 package 后 7 个 Skill 即自动可用。
|
|
55
56
|
|
|
56
57
|
### 在 Claude Code 中使用
|
|
57
58
|
|
|
@@ -95,8 +96,8 @@ Planner 会在 `docs/plans/` 生成 `TaskIntent` 与 living Spec(锁定文件
|
|
|
95
96
|
|
|
96
97
|
检查无误并确认后,才会正式锁定范围并开放执行权限。
|
|
97
98
|
|
|
98
|
-
**3. 用 `imm-
|
|
99
|
-
输入 `/imm-
|
|
99
|
+
**3. 用 `imm-run` 自动执行与验收:**
|
|
100
|
+
输入 `/imm-run`(或 "开始 imm-run"),工作流引擎会自动:
|
|
100
101
|
- 调度 Executor 仅在锁定的 scope 范围内编写代码。
|
|
101
102
|
- 自动运行确定性 QA 验收命令。
|
|
102
103
|
- 对 material/critical 任务分发隔离的 Reviewer 子代理审查代码。
|
|
@@ -113,18 +114,18 @@ Immune-Brain 提供两种清晰的工作模式:日常轻量编码走 **Host-na
|
|
|
113
114
|
| 日常编码、快速改动、普通问答 | 正常自然语言对话("帮我改下文案"、"解释这段代码") | **Host-native**:标准 Pi / Claude Code 行为,零流程开销 |
|
|
114
115
|
| 想法模糊,需要梳理边界与风险 | `/imm-brainstorm` "帮我梳理一下通知系统的方案" | → `imm-brainstorm` 提问澄清、分析约束与风险(只读,不改代码) |
|
|
115
116
|
| 目标明确,需要正规计划与规格 | `/imm-planner` "规划一下深色模式功能" | → `imm-planner` 产出 `TaskIntent` + Spec,包含可执行验收条件 |
|
|
116
|
-
| 计划已确认,准备执行与验证 | `/imm-
|
|
117
|
-
| 会话中断或需恢复未完成任务 | `/imm-
|
|
117
|
+
| 计划已确认,准备执行与验证 | `/imm-run` | → Executor 在范围内实现 → 确定性 QA 验收 → 隔离 Review 审查 → 任务结算 |
|
|
118
|
+
| 会话中断或需恢复未完成任务 | `/imm-run` | → 从磁盘状态(`.imm/`)无缝恢复,以 Kernel projection 为准 |
|
|
118
119
|
| 已发布的 Initiative 可以整批跑了 | "把 initiative `<slug>` 无人值守跑完" | → Host 的 `start_unattended_batch`:一次原生确认绑定有序 plan digest,child 串行执行 |
|
|
119
|
-
| 跨 Host 协作(Claude 规划 + Pi 编码) | 在 Claude Code 中调 `/imm-planner`,切到 Pi 输入 `/imm-
|
|
120
|
+
| 跨 Host 协作(Claude 规划 + Pi 编码) | 在 Claude Code 中调 `/imm-planner`,切到 Pi 输入 `/imm-run` | → Spec 与 TaskIntent 共享于 Git,Pi 原生弹窗准入并执行 QA/Review 闭环 |
|
|
120
121
|
| PR 被评论 / CI 挂了 | 对该 PR 使用 `/imm-pr-fix` | → 独立修复:在当前 PR 内针对性修复,不创建新 managed 任务 |
|
|
121
122
|
| 文档过时需要清理 | `/imm-doc-prune` | → 只读审计过时文档,仅删除经哈希审批的条目 |
|
|
122
|
-
| Agent 指令文件膨胀 | `/imm-
|
|
123
|
-
| 想知道哪个模型的改动总被审查 | `/imm-
|
|
123
|
+
| Agent 指令文件膨胀 | `/imm-doc-slim` | → 将 tracked `AGENTS.md` / `CLAUDE.md` 压到最小必要上下文 |
|
|
124
|
+
| 想知道哪个模型的改动总被审查 | `/imm-retro` | → 按模型排名审查负载,并从 session logs 汇报项目使用量 |
|
|
124
125
|
|
|
125
126
|
> **核心原则:Skill 显式调用**
|
|
126
127
|
> - **普通输入保持 Host-native**:自然语言提问绝不自动绑架流程或发起 Enrollment。你完全自主决定何时开启严格工程保障。
|
|
127
|
-
> - **Managed 工作流显式启动**:需要澄清用 `imm-brainstorm`,制定计划用 `imm-planner`,执行与恢复用 `imm-
|
|
128
|
+
> - **Managed 工作流显式启动**:需要澄清用 `imm-brainstorm`,制定计划用 `imm-planner`,执行与恢复用 `imm-run`。
|
|
128
129
|
|
|
129
130
|
### 跨 Host 协作:Claude Code 规划 + Pi 编码执行
|
|
130
131
|
|
|
@@ -135,7 +136,7 @@ Immune-Brain 的核心状态与契约完全去会话化(Session-neutral),
|
|
|
135
136
|
```text
|
|
136
137
|
┌───────────────────────────────────┐ Git 追踪制品(落盘共享) ┌───────────────────────────────────┐
|
|
137
138
|
│ Claude Code 终端 │ ───────────────────────────> │ Pi 终端 │
|
|
138
|
-
│ 1. /imm-brainstorm (澄清与约束) │ docs/specs/*.spec.md │ 1. /imm-
|
|
139
|
+
│ 1. /imm-brainstorm (澄清与约束) │ docs/specs/*.spec.md │ 1. /imm-run (原生 TUI 弹窗准入) │
|
|
139
140
|
│ 2. /imm-planner (编写计划/规格) │ docs/plans/*.intent.json │ 2. Executor 编码 + QA 自动化验收 │
|
|
140
141
|
└───────────────────────────────────┘ └───────────────────────────────────┘
|
|
141
142
|
```
|
|
@@ -150,7 +151,7 @@ Immune-Brain 的核心状态与契约完全去会话化(Session-neutral),
|
|
|
150
151
|
- **暂存至 Git**:规划完成后停在 Enrollment 之前,将生成的 Spec 和 TaskIntent 加入 Git 暂存(`git add docs/`)。
|
|
151
152
|
2. **切换到 Pi 中进行代码编写与闭环执行**
|
|
152
153
|
- **启动 Pi**:在同一个项目工作区中打开 Pi。
|
|
153
|
-
- **确认准入并执行**:运行 `/imm-
|
|
154
|
+
- **确认准入并执行**:运行 `/imm-run`。Pi 会自动检测到暂存的 `TaskIntent`,并在 Pi 原生 TUI 弹窗中提示 Enrollment 确认。
|
|
154
155
|
- **自动执行与验收**:
|
|
155
156
|
- Executor 角色严格在 `scope_hint` 限定的文件内编写代码。
|
|
156
157
|
- Kernel 自动运行 acceptance 命令进行确定性 QA 验收,不依赖口头汇报。
|
|
@@ -158,7 +159,117 @@ Immune-Brain 的核心状态与契约完全去会话化(Session-neutral),
|
|
|
158
159
|
- 验证全部通过后,Kernel 原子落盘证据至 `.imm/audit/<task-id>/` 并释放工作区锁定。
|
|
159
160
|
3. **为什么可以无缝切换?**
|
|
160
161
|
- **状态落盘,解耦会话**:所有任务契约(TaskIntent)、设计规格(Spec)和执行状态(`.imm/state/kernel.sqlite`)均持久化在磁盘上,不绑定任何特定 AI 会话的上下文。
|
|
161
|
-
- **双向断点恢复**:无论在哪个 Host 暂停或关闭会话,随时可以在 Pi 或 Claude Code 中重新输入 `/imm-
|
|
162
|
+
- **双向断点恢复**:无论在哪个 Host 暂停或关闭会话,随时可以在 Pi 或 Claude Code 中重新输入 `/imm-run` 无缝恢复,Kernel projection 确保进度与证据不丢失。
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 核心设计哲学:把“判断”变成“查表”,用确定性工程驾驭多模型
|
|
167
|
+
|
|
168
|
+
大模型(尤其是轻量/高性价比的 Fast 档模型)在工程落地中最容易失败的原因,不是代码语法不过关,而是死在**语义含糊、过度发挥**与**逃避严格验证**上。
|
|
169
|
+
|
|
170
|
+
Immune-Brain 的核心假设是:**不要让弱模型做架构决策,把它变成精准执行的查表机;关键的门禁与审核则交由代码规则与强模型把关。**
|
|
171
|
+
|
|
172
|
+
```text
|
|
173
|
+
┌────────────────────────────────────────────────────────────────────────────────────────┐
|
|
174
|
+
│ 1. 方案规划 (Brainstorm) & 2. 计划制定 (Planner) │
|
|
175
|
+
│ 工具: Claude Code | 模型: 强推理旗舰模型 (Strong Tier) │
|
|
176
|
+
│ 职责: 澄清约束、架构推演,把“判断”收敛为精确到行号的 Living Spec 与可执行 TaskIntent │
|
|
177
|
+
└───────────────────────────────────────────┬────────────────────────────────────────────┘
|
|
178
|
+
│ Git 追踪制品共享 (docs/specs, docs/plans)
|
|
179
|
+
▼
|
|
180
|
+
┌────────────────────────────────────────────────────────────────────────────────────────┐
|
|
181
|
+
│ 3. 代码实现 (Executor) │
|
|
182
|
+
│ 工具: Pi | 模型: 高吞吐/经济型模型 (Fast / Mid Tier) │
|
|
183
|
+
│ 职责: 冻结 Scope 内“按图索骥”,严格镜像既有代码模式填空,无设计决策负担 │
|
|
184
|
+
└───────────────────────────────────────────┬────────────────────────────────────────────┘
|
|
185
|
+
│ 本地代码与状态交付
|
|
186
|
+
▼
|
|
187
|
+
┌────────────────────────────────────────────────────────────────────────────────────────┐
|
|
188
|
+
│ 4. QA 确认 (Deterministic QA) │
|
|
189
|
+
│ 工具: Pi / Kernel Native │
|
|
190
|
+
│ 职责: 零 LLM 干预,真机执行 Verification Descriptor v2 命令,机器判决 Pass/Fail │
|
|
191
|
+
└───────────────────────────────────────────┬────────────────────────────────────────────┘
|
|
192
|
+
│ 自动化测试真实跑通后触发
|
|
193
|
+
▼
|
|
194
|
+
┌────────────────────────────────────────────────────────────────────────────────────────┐
|
|
195
|
+
│ 5. 代码审查 (Isolated Review) │
|
|
196
|
+
│ 工具: Pi Subagent | 模型: 强推理/高智商审查模型 (Strong Tier) │
|
|
197
|
+
│ 职责: 基于不可变 Git blob 打包的 ReviewBundle,结合 Devil's Advocate 规则审查代码 │
|
|
198
|
+
└────────────────────────────────────────────────────────────────────────────────────────┘
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### 1. 把“判断”变成“查表”:挤干含糊空间,弱模型按图索骥
|
|
202
|
+
|
|
203
|
+
约束弱模型最有效的一招,是在 Spec 阶段彻底消除含糊:
|
|
204
|
+
|
|
205
|
+
- **坐标级精准定位**:在 Spec 中直接给出既有实现的参考锚点(如 `kernel.ts:1219`),明确要求 *"mirror this exact shape"* 沿用既有实现模式。
|
|
206
|
+
- **零自由度契约**:连报错文案、返回状态码与错误类型都要求照抄既有格式(如复制现有 `throw new VerificationDescriptorError(...)`,仅替换具体的命令名与字段名),不留任何自由措辞或抽象发挥的空间。
|
|
207
|
+
- **物理冻结与负向清单(Exclusion List)**:在 Spec 的 Scope 章节中明确列出 Exclude 清单(严禁改动哪些文件、特定 receipt 路径禁止复用)。弱模型不需要自行推断架构影响面,只需在限定红线内按图索骥。
|
|
208
|
+
|
|
209
|
+
### 2. “做完”的定义是可执行的,不是文字汇报
|
|
210
|
+
|
|
211
|
+
口头汇报(Text-based Promise)是幻觉与蒙混过关的温床。Immune-Brain 的 Kernel 强制要求所有完成标准全部代码化、物理化:
|
|
212
|
+
|
|
213
|
+
- **Verification Descriptor v2 强契约**:
|
|
214
|
+
`TaskIntent` 中每个验收条件(AC)都不是泛泛的自然语言,而是强类型的机器执行描述符(`assurance_kernel/verification_descriptor/v2`):
|
|
215
|
+
```json
|
|
216
|
+
{
|
|
217
|
+
"contract": "assurance_kernel/verification_descriptor/v2",
|
|
218
|
+
"command": {
|
|
219
|
+
"executable": "bun",
|
|
220
|
+
"argv": ["test", "tests/kernel-migrate-to-vnext.test.ts"],
|
|
221
|
+
"cwd": ".",
|
|
222
|
+
"timeout_ms": 30000,
|
|
223
|
+
"max_output_bytes": 262144
|
|
224
|
+
},
|
|
225
|
+
"environment": { "prepare": null, "writable_paths": [] }
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
模型无法靠“我已经实现并测试通过”的话术过关;测试必须由 Kernel 子进程在隔离沙箱中真机拉起,根据真实的 exit code、stdout 与超时时限判定胜负。
|
|
229
|
+
- **物理级 Scope 冻结**:
|
|
230
|
+
在 Enrollment 准入时,Kernel 通过 `captureGitWorkspaceSnapshot` 对 Git 树和 dirty files 进行基线快照。如果候选任务的 scope 已经变脏,或 Executor 试图修改 `scope_hint` 允许范围外的文件(`assertNoEnvelopeEscape`),Kernel 直接 fail-closed 拦截并拒绝推进。
|
|
231
|
+
- **独立 QA 与隔离 Reviewer 强制 Gate**:
|
|
232
|
+
代码修改完成后,QA 阶段由本地命令执行器严格校验;对于 `material` 和 `critical` 任务,必须经由独立的 Reviewer 子代理审计并签批。任何试图跳过门禁的幻觉行为都会被底层状态机拦下。
|
|
233
|
+
|
|
234
|
+
### 3. Devil's Advocate Audit 与代码级防御:封死偷懒路径
|
|
235
|
+
|
|
236
|
+
弱模型在面对复杂逻辑和优化压力时,极易选择走阻力最小的“偷懒捷径”。Immune-Brain 从 Spec 到代码层面构建了层层阻尼:
|
|
237
|
+
|
|
238
|
+
- **防虚荣验证(Verification Vanity)**:
|
|
239
|
+
在 Devil's Advocate Audit 中明确立规:“`--check` 跑通不等于真跑能成功”。静态检查、类型声明或空跑(dry-run)绝不能替代带断言的真实运行测试。
|
|
240
|
+
- **防规格稀释(Spec Dilution)**:
|
|
241
|
+
严禁模型因为实现困难而悄悄删减需求,例如:“不许在没有 v1 数据的环境中凭空编造虚假的 v1→v2 转换逻辑”来伪造兼容性。
|
|
242
|
+
- **代码强制的确定性风险兜底(Deterministic Risk-Tier Floor)**:
|
|
243
|
+
模型可能会自作聪明地将高危任务自评为 `routine`(常规),企图绕过代码审查。在 `kernel/intent.ts` 中,系统硬编码了底线规则:
|
|
244
|
+
> 只要 `scope_hint` 触及 `kernel/`、`assurance/`、`claude/` 或 `.pi-extension` 等核心权威路径,无论作者声明的风险多么轻微,Kernel 会强制将风险等级锁定至至少 `material`,由代码物理强制触发隔离审查。
|
|
245
|
+
- **客观反证机制(Live Counterevidence & Refuted Findings)**:
|
|
246
|
+
审查模型并非百分之百可信。当 Reviewer 提出怀疑某个 acceptance 存在缺陷的主观 finding 时,若 Kernel 拥有一份针对当前 `diff_hash` 和 `intent_hash` 真实跑通的新鲜 QA 凭证(Attestation),Kernel 会直接将该 finding 标记为 `refuted`(反证驳回),避免审查模型的幻觉阻碍任务落地;而一旦代码产生新改动使凭证过期(stale),该 finding 又会立即重新激活阻塞。
|
|
247
|
+
|
|
248
|
+
### 4. Token 经济学与成本杠杆:没有 Cost Lever,成本会复合爆炸
|
|
249
|
+
|
|
250
|
+
如果缺乏精细的成本杠杆(Cost Lever),多 Agent 系统的成本会随着任务拆解呈几何级数(Compound)激增:
|
|
251
|
+
|
|
252
|
+
- **先 Plan 后 Implement(“量两次,裁一次”)**:
|
|
253
|
+
一份几百 token 的精准 Spec 与 TaskIntent 成本,远低于一次方向做错后推倒重来、反复 debug 烧掉的上万 token。“量两次裁一次”在多 Agent 协作中是字面意义的真金白银。
|
|
254
|
+
- **冻结 Scope 掐断 Token 黑洞**:
|
|
255
|
+
弱模型最爱“顺手重构无关文件”或“格式化全工程”。在 Immune-Brain 中,每多碰一个文件不仅增加额外的 token 消耗,还会让 Reviewer 和 Git Diff 负担翻倍。基于哈希的 Scope 边界硬性杜绝了模型过度发挥。
|
|
256
|
+
- **Model Tier 分档流水线(`subagent-model-tier-pipeline`)**:
|
|
257
|
+
将模型按能力与成本精细分档:
|
|
258
|
+
- **Fast 档(如 Flash / 4o-mini)**:专跑无设计决策的机械填充、局部测试修复、固定模板编码。
|
|
259
|
+
- **Mid 档**:负责可靠性审计(`reliability-reviewer`)与常规代码审查。
|
|
260
|
+
- **Strong 档(如 Sonnet / Opus)**:仅用于前期 Brainstorming、Spec 架构推演与高危安全审计(`security-reviewer`)。
|
|
261
|
+
|
|
262
|
+
### 5. 典型协作全景:跨 Host 与多模型落地
|
|
263
|
+
|
|
264
|
+
在 Immune-Brain 的跨 Host 协作模式中,各阶段工具与模型能力得以实现最优配置:
|
|
265
|
+
|
|
266
|
+
| 阶段 | 参与工具 / 宿主 | 模型档位推荐 | 职责与确定性保障 |
|
|
267
|
+
|---|---|---|---|
|
|
268
|
+
| **1. 方案规划 (Brainstorm)** | Claude Code (`/imm-brainstorm`) | **Strong Tier** (旗舰模型) | 利用长上下文与强推理,与开发者深入讨论方案、挖掘隐性约束并排除伪需求。 |
|
|
269
|
+
| **2. 计划制定 (Planner)** | Claude Code (`/imm-planner`) | **Strong Tier** (旗舰模型) | 编写精确到文件行号的 Living Spec,生成携带 `VerificationDescriptor` 的 `TaskIntent`,完成 Devil's Advocate 预审。 |
|
|
270
|
+
| **3. 代码实现 (Executor)** | Pi (`imm-run`) | **Fast / Mid Tier** (经济模型) | 在 Pi TUI 弹窗确认冻结 Scope 后,小模型在信封内按图索骥写代码,遵守 YAGNI 极简红线。 |
|
|
271
|
+
| **4. QA 确认 (Verification)** | 本地进程 / Kernel Native | **无需模型 (零 LLM)** | 由 Kernel 直接执行测试脚本(如 `bun test`),严格依照退出码和标准输出出具不可篡改的 Attestation。 |
|
|
272
|
+
| **5. 代码审查 (Review)** | Pi Subagent (`immune-brain-reviewer`) | **Strong Tier** (高智力模型) | 调度隔离的只读审查子代理,基于不可变 Git blob 打包的 `ReviewBundle` 进行对抗性审计,通过后 Kernel 结算归档。 |
|
|
162
273
|
|
|
163
274
|
---
|
|
164
275
|
|
|
@@ -168,15 +279,15 @@ Immune-Brain 的核心状态与契约完全去会话化(Session-neutral),
|
|
|
168
279
|
|---|---|---|---|
|
|
169
280
|
| `imm-brainstorm` | Managed 入口 | 需求存在实质歧义 | 框架化问题、提出开放问题,不做实现 |
|
|
170
281
|
| `imm-planner` | Managed 入口 | 目标清晰 | 编写/修订 `TaskIntent` 与 spec,不负责 Enrollment 与构建 |
|
|
171
|
-
| `imm-
|
|
282
|
+
| `imm-run` | Managed 协调器 | 计划已验证 | 通过 foreground Tools 协调 执行 → QA → Review → 收尾 |
|
|
172
283
|
| `imm-pr-fix` | 独立 | PR 需修复 | 原地修复单个 PR,不触及 managed authority |
|
|
173
284
|
| `imm-doc-prune` | 独立 | 清理过时文档 | 仅删除哈希绑定的 manifest 条目 |
|
|
174
|
-
| `imm-
|
|
175
|
-
| `imm-
|
|
285
|
+
| `imm-doc-slim` | 独立 | Agent instruction 膨胀 | 将 tracked AGENTS/CLAUDE/GEMINI.md 压到最小必要上下文 |
|
|
286
|
+
| `imm-retro` | 独立 | 比较模型的审查负载 | 排名被审查代码的作者并汇报项目使用量 |
|
|
176
287
|
|
|
177
|
-
Executor、QA、Review、Compounder 等为 `imm-
|
|
288
|
+
Executor、QA、Review、Compounder 等为 `imm-run` 内部调度的角色,无需手动调用。
|
|
178
289
|
|
|
179
|
-
所有 7 个 Skill 均显式调用。新需求开发时:若需求含糊先调 `imm-brainstorm`,目标清晰直接调 `imm-planner`,完成确认后调 `imm-
|
|
290
|
+
所有 7 个 Skill 均显式调用。新需求开发时:若需求含糊先调 `imm-brainstorm`,目标清晰直接调 `imm-planner`,完成确认后调 `imm-run` 推进闭环。
|
|
180
291
|
|
|
181
292
|
### Managed Path 入口(brainstorm → planner → loop)
|
|
182
293
|
|
|
@@ -196,9 +307,9 @@ Executor、QA、Review、Compounder 等为 `imm-loop` 内部调度的角色,
|
|
|
196
307
|
- **边界:** 不编写业务实现代码、不经 revision 流程不覆盖已 Enrolled 的 TaskIntent,不擅自赋予执行权限 — 仅当前 Host 原生确认窗口具备授权能力。
|
|
197
308
|
- **产出:** 纳入 Git 版本控制、等待 Enrollment 确认的 `TaskIntent`。
|
|
198
309
|
|
|
199
|
-
#### `imm-
|
|
310
|
+
#### `imm-run` — Managed 执行与质量保障
|
|
200
311
|
|
|
201
|
-
- **触发方式:** 显式调用 `/imm-
|
|
312
|
+
- **触发方式:** 显式调用 `/imm-run`(启动、恢复或检查 managed 任务)。
|
|
202
313
|
- **职责:** 通过前台 Tool 驱动任务端到端闭环 — Executor 仅在冻结的 scope 内修改代码,确定性 QA 逐项运行验收条件,隔离的 Reviewer 子代理审计 material/critical 任务,最后由 Kernel 结算落盘凭证。会话中断后从磁盘状态自动恢复,以 Kernel projection 为真源。
|
|
203
314
|
- **边界:** 绝不跳过或弱化失败检查、无用户原生授权绝不执行、遇到版本或权限偏移立即 fail-closed。
|
|
204
315
|
- **Finding 证据:** 每一项 Review finding 均携带可机器核验的 provenance(`trigger`、`caller_chain`、`violated`)。若新鲜且通过的 QA 证据已证明某项 finding 声称的 acceptance 通过,则标记为 `refuted`,仅在证据过期时才会重新阻塞。
|
|
@@ -219,12 +330,12 @@ Executor、QA、Review、Compounder 等为 `imm-loop` 内部调度的角色,
|
|
|
219
330
|
- **触发方式:** 显式要求清理当前过时的文档。
|
|
220
331
|
- **职责:** 只读审计文档时效性,根据用户明确审批的哈希绑定 manifest 进行精准删除,每次修改后立即重验。
|
|
221
332
|
|
|
222
|
-
#### `imm-
|
|
333
|
+
#### `imm-doc-slim` — Agent 指令文件瘦身
|
|
223
334
|
|
|
224
335
|
- **触发方式:** 显式要求精简版本控制下的 `AGENTS.md` / `CLAUDE.md` / `GEMINI.md`。
|
|
225
336
|
- **职责:** 遵循与 `imm-doc-prune` 相同的「只读审计 + 哈希清单审批」模式,仅保留无法直接推导的必要规则。
|
|
226
337
|
|
|
227
|
-
#### `imm-
|
|
338
|
+
#### `imm-retro` — 审查负载与项目使用回顾
|
|
228
339
|
|
|
229
340
|
- **触发方式:** 显式要求跨模型审查复盘或项目使用量回顾。
|
|
230
341
|
- **职责:** 从 pi session logs 按模型排名被审查代码的作者,并汇报 sessions/turns/编辑量/工具分布。只读;不审查 diff。
|
|
@@ -245,7 +356,7 @@ flowchart TD
|
|
|
245
356
|
EG -->|确认| KS[(".imm/state/kernel.sqlite<br/>原子生成 TaskRecord<br/>独占 Workspace Claim")]
|
|
246
357
|
end
|
|
247
358
|
|
|
248
|
-
subgraph Loop ["3. 执行与验证循环 (imm-
|
|
359
|
+
subgraph Loop ["3. 执行与验证循环 (imm-run)"]
|
|
249
360
|
KS --> EX["Executor 角色<br/>在 scope_hint 范围内修改代码"]
|
|
250
361
|
EX --> FRZ["advance_assurance<br/>制品冻结 (active:frozen)"]
|
|
251
362
|
FRZ --> QA["确定性 QA 引擎<br/>原子运行 acceptance 校验命令<br/>生成 QA Attestation"]
|
|
@@ -268,25 +379,28 @@ flowchart TD
|
|
|
268
379
|
end
|
|
269
380
|
```
|
|
270
381
|
|
|
271
|
-
###
|
|
382
|
+
### 核心架构与确定性保证
|
|
272
383
|
|
|
273
384
|
1. **双轨制 (Two Paths)**
|
|
274
385
|
- **Host-native Path**:日常对话、代码检视、单点修改,不触碰 Kernel 权限,零流程开销。
|
|
275
|
-
- **Managed Path**:由 `imm-brainstorm` / `imm-planner` / `imm-
|
|
386
|
+
- **Managed Path**:由 `imm-brainstorm` / `imm-planner` / `imm-run` 显式驱动,全程受 Kernel 约束。
|
|
276
387
|
|
|
277
388
|
2. **权限与契约 (Authority & Contract)**
|
|
278
|
-
- **TaskIntent (`.intent.json`)**:机器契约本体,严格锁定 `scope_hint`(文件修改范围)、`risk`(风险层级)与 `acceptance
|
|
279
|
-
- **Native Gate (Enrollment)**:唯一一次人工介入确认,Kernel
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
-
|
|
389
|
+
- **TaskIntent (`.intent.json`)**:机器契约本体,严格锁定 `scope_hint`(文件修改范围)、`risk`(风险层级)与 `acceptance`(绑定 Verification Descriptor v2 的确定性断言)。
|
|
390
|
+
- **Native Gate (Enrollment)**:唯一一次人工介入确认,Kernel 原子抢占工作区所有权(基于 SQLite CAS),防止多任务并发冲突与范围漂移。
|
|
391
|
+
- **Git 物理基线快照 (Physical Baseline)**:准入时记录真实的 Git HEAD 与 dirty 文件状态(`enrollment-baseline.json`),任何超出 `scope_hint` 的物理逃逸(`assertNoEnvelopeEscape`)都会直接阻断执行。
|
|
392
|
+
|
|
393
|
+
3. **客观验证与不可变证据链 (Deterministic Assurance & Evidence Trail)**
|
|
394
|
+
- **QA 优先与真实进程调用**:由 Kernel 直接前台拉起子进程执行测试命令,校验退出码、标准输出并施加超时上限,不依赖 LLM 口头汇报。
|
|
395
|
+
- **按险定级与确定性兜底**:`routine` 仅需 QA;`material`/`critical` 必须追加独立只读 Reviewer 产出结构化裁决。触碰核心权威路径强制定级为 `material`。
|
|
396
|
+
- **反证机制 (Live Refutation)**:主观 Review finding 可由真实通过的新鲜 QA 证据反证驳回;代码发生改动后反证自动失效并重新阻塞。
|
|
397
|
+
- **不可变审计落盘**:任务结项时,完整的 `TaskRecord`、Git blob 打包的 `ReviewBundle`、QA Attestation 凭证原子沉淀至 `.imm/audit/<task-id>/` 并受 Git 追踪。
|
|
284
398
|
- **批处理 (Unattended Batch)**:基于 GitHub Issue / `plan_digest` 串行推进,每个子任务独立走完 Enrollment → QA → Review → Commit 闭环。
|
|
285
399
|
|
|
286
400
|
核心不变量:
|
|
287
401
|
|
|
288
402
|
- **一次仅一个活跃步骤**,编辑仅在步骤边界内。
|
|
289
|
-
- **范围(`scope_hint`)在 enrollment
|
|
403
|
+
- **范围(`scope_hint`)在 enrollment 时冻结**,范围外文件被物理忽略与拦截。
|
|
290
404
|
- **先记录证据再关闭** — 只有 QA 能关闭步骤。
|
|
291
405
|
- **Finding 必须携带证据** — 被反证的 Review finding 只在绑定它的 QA 证据对当前 revision、intent hash 与 diff 仍然新鲜时压制工作;证据过期后 finding 重新阻塞,且这个失效过程不重写任何已存状态。
|
|
292
406
|
- **批次必须显式授权且有边界** — 只有你确认 Host 的 `start_unattended_batch` 之后才存在无人值守批次;每个 child 仍各自 Enrollment、QA、Review 与结算。
|
|
@@ -298,7 +412,7 @@ flowchart TD
|
|
|
298
412
|
|
|
299
413
|
当一个 Initiative 下已经有多个就绪的 child,可以把它们作为一批串行跑完,而不用逐个任务手动推进。
|
|
300
414
|
|
|
301
|
-
- **入口显式:** Host 的 privileged tool `start_unattended_batch`(参数为 Initiative slug)。未调用之前不存在任何 batch state、分支或授权;未调用时 `imm-
|
|
415
|
+
- **入口显式:** Host 的 privileged tool `start_unattended_batch`(参数为 Initiative slug)。未调用之前不存在任何 batch state、分支或授权;未调用时 `imm-run` 行为与逐任务 Enrollment 完全一致。
|
|
302
416
|
- **一次确认、一个 digest:** 原生 gate(Pi TUI 弹窗或 Claude MCP elicitation)展示有序 child 列表与共享 plan digest,这一次 literal-user 确认就是全部 Batch Authorization。
|
|
303
417
|
- **每个 child 的 authority 不变:** 每个 child 仍由 Kernel 单独 Enrollment、冻结、QA、Review 并以自己的 `TaskRecord` 结算。批次只是一次授权的覆盖范围,不是新的授权层级。
|
|
304
418
|
- **边界:** 只跑已发布且非 `critical` 的 child,在专属 batch 分支上串行执行;一旦某个 child 需要人决策,或遇到预算/截止时间/授权/提交失败就暂停,被阻塞 child 的依赖项标记为跳过而不是调序。runner 不 push、不开 PR、不代替用户结算 decision、也不创建/切换/删除 Git worktree。
|
|
@@ -333,7 +447,7 @@ Immune-Brain **没有独立配置文件**,偏好设置写在仓库根目录下
|
|
|
333
447
|
package.json # Pi package manifest(skills + extensions)
|
|
334
448
|
plugins/immune-brain/
|
|
335
449
|
├── .pi-extension/ # Pi TUI + Kernel 扩展
|
|
336
|
-
├── skills/ #
|
|
450
|
+
├── skills/ # 7 个公开 Skills(触发 shim)
|
|
337
451
|
├── dist/ # 构建后的 skill 契约与参考文档
|
|
338
452
|
├── runtime/ # Bun + TypeScript 运行时与 Kernel
|
|
339
453
|
└── bin/ # CLI wrappers(→ runtime/v4_runtime.ts)
|
|
@@ -351,19 +465,25 @@ docs/specs/ # Living specs(原地更新)
|
|
|
351
465
|
|
|
352
466
|
## 常见问题
|
|
353
467
|
|
|
354
|
-
**需要记住所有 Skill 吗?** 不需要。日常开发核心只需两个:`/imm-planner`(规划与确认任务)和 `/imm-
|
|
468
|
+
**需要记住所有 Skill 吗?** 不需要。日常开发核心只需两个:`/imm-planner`(规划与确认任务)和 `/imm-run`(执行与验证)。需求模糊时用 `/imm-brainstorm`,维护类任务(如 `/imm-pr-fix`)按需使用。普通问答与即时小修改无需任何 Skill。
|
|
355
469
|
|
|
356
|
-
**中途关闭会话会怎样?** 状态已落盘保存(`.imm/` + TaskIntent)。在 Pi 或 Claude Code 中重新输入 `/imm-
|
|
470
|
+
**中途关闭会话会怎样?** 状态已落盘保存(`.imm/` + TaskIntent)。在 Pi 或 Claude Code 中重新输入 `/imm-run` 即可恢复,以 Kernel projection 状态为准。
|
|
357
471
|
|
|
358
472
|
**为什么 enrollment 要弹窗确认?** 所有风险等级(`routine`/`material`/`critical`)在获得执行授权前都必须经由人工显式确认。在 Pi 中是原生 TUI 对话框,在 Claude Code 中是原生 MCP elicitation 弹窗。确认界面绑定 staged digest,让你清楚看到被锁定的文件范围和验收要求。
|
|
359
473
|
|
|
360
|
-
**QA 失败怎么办?** QA 返回 `rework` 或 `replan_required`,`imm-
|
|
474
|
+
**QA 失败怎么办?** QA 返回 `rework` 或 `replan_required`,`imm-run` 会自动路由回 Executor 或 `imm-planner` 调整范围,无需手动重置。
|
|
361
475
|
|
|
362
476
|
**Review finding 突然不再阻塞了?** 它被反证了:新鲜的确定性 QA 证据表明它声称的 acceptance 是通过的。反证绑定到那份具体证据,所以证据一旦对当前 revision、intent hash 或 diff 失效,该 finding 会重新阻塞。
|
|
363
477
|
|
|
364
478
|
**能不能整个 Initiative 不用我盯着?** 只能在你授权范围内。用 Initiative slug 确认 `start_unattended_batch` 后,runner 会在一个 batch 分支上串行推进已发布且非 `critical` 的 child — 一旦某个 child 需要人决策,或遇到预算/截止时间/授权/提交失败就暂停。它不会替你 push、开 PR 或结算用户决策。
|
|
365
479
|
|
|
366
|
-
**可以在不同 Host 之间切换吗(例如 Claude Code 规划、Pi 编码)?** 可以。Immune-Brain 的契约与状态完全落盘于代码仓库,解耦了会话上下文。你可以用 Claude Code 进行深度推理与制定 Spec,再切换到 Pi 跑 `imm-
|
|
480
|
+
**可以在不同 Host 之间切换吗(例如 Claude Code 规划、Pi 编码)?** 可以。Immune-Brain 的契约与状态完全落盘于代码仓库,解耦了会话上下文。你可以用 Claude Code 进行深度推理与制定 Spec,再切换到 Pi 跑 `imm-run` 编码并完成 QA 闭环;中途随时可以用 `/imm-run` 双向恢复。
|
|
481
|
+
|
|
482
|
+
**任务执行中途发现 Scope 不够用怎么办?** Executor 遵循严格的 Fail-closed 极简红线,严禁自行越界修改范围外文件。若发现必须扩充范围,Executor 会主动停止并返回 `replan_required` 路线;随后由 `imm-planner` 修订 Spec 与 `TaskIntent` 并生成新的 diff,重新弹出原生确认窗口经由人工授权(Replan)后,方可继续执行。
|
|
483
|
+
|
|
484
|
+
**任务结算后的审计凭证(Audit Trail)保存在哪里?** 保存在仓库的 `.imm/audit/<task-id>/` 目录下,并作为 Git-tracked 资产提交。其中包含最终的 `TaskRecord`、绑定的代码 `diff_hash`、真实执行的 QA 退出码/输出 Attestation、以及 Reviewer 签署的验证凭据,保证交付全流程可追溯、可审计。
|
|
485
|
+
|
|
486
|
+
**偏好配置为什么写在 AGENTS.md / CLAUDE.md 而不是独立配置文件?** 遵循“零外部负担、宿主原生”原则。将偏好(如 Initiative 载体、交互语言)声明在项目根目录受版本控制的指令文件中,既能在不同 Host 之间透明生效,又避免了本地全局配置文件容易漂移、团队成员无法共享的痛点。
|
|
367
487
|
|
|
368
488
|
**支持哪些 AI 编程工具?** Pi 与 Claude Code 是支持的宿主(Claude Code 最低版本为 `2.1.236`)。两者共享同一套确定性 Kernel 核心、质量保障机制与工具链。
|
|
369
489
|
|
|
@@ -391,7 +511,7 @@ npm publish --access public # 需 npm login / NPM_TOKEN
|
|
|
391
511
|
# 或
|
|
392
512
|
bun run changeset:publish
|
|
393
513
|
```
|
|
394
|
-
包名为 `immune-brain`(当前版本 `
|
|
514
|
+
包名为 `immune-brain`(当前版本 `4.6.0`),已配置 `publishConfig.access=public`。首次发布后,后续所有版本均通过 changesets 管理。
|
|
395
515
|
|
|
396
516
|
详见 `CHANGELOG.md` 与 `.changeset/config.json`(changelog: `@changesets/changelog-github`,repo: `dereknex/immune-brain`)。
|
|
397
517
|
|
package/package.json
CHANGED
|
@@ -9,27 +9,24 @@ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-a
|
|
|
9
9
|
import { Type } from "typebox";
|
|
10
10
|
import { createHash, randomUUID } from "node:crypto";
|
|
11
11
|
import { resolve } from "node:path";
|
|
12
|
-
// The
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
12
|
+
// The Pi adapter imports the host-neutral runtime modules statically, exactly
|
|
13
|
+
// as the Claude adapter does. Kernel prepare is reached only through the
|
|
14
|
+
// shared Enrollment boundary (runtime/assurance/enrollment), never directly
|
|
15
|
+
// from the Kernel's own prepare module.
|
|
16
|
+
import { LITERAL_USER_ACTOR_ID } from "../runtime/kernel/actor_identity";
|
|
17
|
+
import { createEnrollmentAuthorityRegistry } from "../runtime/kernel/enrollment_authority";
|
|
18
|
+
import { preparePiCanary, revalidatePiCanary } from "../runtime/assurance/enrollment";
|
|
19
|
+
import { evaluateCanaryEligibility } from "../runtime/kernel/canary_eligibility";
|
|
20
|
+
import { enrollTask, EnrollmentRehearsalError } from "../runtime/kernel/enrollment";
|
|
21
|
+
import { reconcileKernelAuthority, withKernelStoreLock } from "../runtime/kernel/storage";
|
|
22
|
+
import { inspectStorageLayout } from "../runtime/kernel/storage_paths";
|
|
23
|
+
import { migrateLegacyLayout } from "../runtime/kernel/storage_layout_migration";
|
|
16
24
|
import {
|
|
17
|
-
LITERAL_USER_ACTOR_ID,
|
|
18
|
-
createEnrollmentAuthorityRegistry,
|
|
19
|
-
preparePiCanary,
|
|
20
|
-
revalidatePiCanary,
|
|
21
|
-
evaluateCanaryEligibility,
|
|
22
|
-
reconcileKernelAuthority,
|
|
23
|
-
readTaskIntent,
|
|
24
|
-
runEnrollmentRehearsal,
|
|
25
|
-
enrollCanaryTask,
|
|
26
|
-
withKernelStoreLock,
|
|
27
|
-
inspectStorageLayout,
|
|
28
|
-
migrateLegacyLayout,
|
|
29
25
|
inspectEnrollmentGitBase,
|
|
30
26
|
enrollmentGitBaseNotice,
|
|
31
27
|
initializeEnrollmentGitBase,
|
|
32
|
-
} from "
|
|
28
|
+
} from "../runtime/assurance/enrollment_git_base";
|
|
29
|
+
import { readTaskIntentForRecord } from "./imm-canary-work";
|
|
33
30
|
import {
|
|
34
31
|
presentTaskRail,
|
|
35
32
|
presentTaskRailResult,
|
|
@@ -253,7 +250,7 @@ async function classifyCommitFailure(
|
|
|
253
250
|
"completed",
|
|
254
251
|
"committing",
|
|
255
252
|
`Kernel enrollment committed for ${taskId}; terminal receipt was recovered from authoritative owners`,
|
|
256
|
-
"continue with imm-
|
|
253
|
+
"continue with imm-run",
|
|
257
254
|
);
|
|
258
255
|
}
|
|
259
256
|
if (
|
|
@@ -315,7 +312,7 @@ async function executeForegroundEnrollment(
|
|
|
315
312
|
signal.throwIfAborted();
|
|
316
313
|
progress("preparing", uxText(UX_LANG, `Preparing immutable Kernel owners for ${taskId}`, `正在为 ${taskId} 准备不可变 Kernel 所有者`));
|
|
317
314
|
const now = new Date().toISOString();
|
|
318
|
-
let taskIntent: Awaited<ReturnType<typeof
|
|
315
|
+
let taskIntent: Awaited<ReturnType<typeof readTaskIntentForRecord>>;
|
|
319
316
|
|
|
320
317
|
// Storage-layout gate (BR-REQ-005/006): enrollment is the stateful
|
|
321
318
|
// mutation boundary. Kernel transaction markers recover under the
|
|
@@ -387,10 +384,10 @@ async function executeForegroundEnrollment(
|
|
|
387
384
|
}
|
|
388
385
|
|
|
389
386
|
try {
|
|
390
|
-
taskIntent = await
|
|
387
|
+
taskIntent = await readTaskIntentForRecord(root, taskId);
|
|
391
388
|
} catch (error) {
|
|
392
389
|
const message = errorMessage(error);
|
|
393
|
-
// `
|
|
390
|
+
// `readTaskIntentForRecord` reports an absent sidecar semantically now, so the
|
|
394
391
|
// "missing" classification must recognise that wording as well as the raw
|
|
395
392
|
// filesystem errors; otherwise a missing file is misreported as a schema
|
|
396
393
|
// defect and the operator is told to repair fields that do not exist.
|
|
@@ -406,7 +403,7 @@ async function executeForegroundEnrollment(
|
|
|
406
403
|
"route_incumbent",
|
|
407
404
|
stage,
|
|
408
405
|
`Kernel task ${authority.owner_task_id} already owns this workspace`,
|
|
409
|
-
`continue ${authority.owner_task_id} through imm-
|
|
406
|
+
`continue ${authority.owner_task_id} through imm-run without re-enrollment`,
|
|
410
407
|
);
|
|
411
408
|
if (authority.state === "repairable_stale_claim")
|
|
412
409
|
return terminal(
|
|
@@ -518,7 +515,7 @@ async function executeForegroundEnrollment(
|
|
|
518
515
|
{
|
|
519
516
|
let liveEarly: string | null = null;
|
|
520
517
|
try {
|
|
521
|
-
liveEarly = (await
|
|
518
|
+
liveEarly = (await readTaskIntentForRecord(resolve(root), taskId)).content_hash;
|
|
522
519
|
} catch {
|
|
523
520
|
liveEarly = null;
|
|
524
521
|
}
|
|
@@ -529,7 +526,7 @@ async function executeForegroundEnrollment(
|
|
|
529
526
|
{
|
|
530
527
|
let liveContentHash: string | null = null;
|
|
531
528
|
try {
|
|
532
|
-
liveContentHash = (await
|
|
529
|
+
liveContentHash = (await readTaskIntentForRecord(resolve(root), taskId)).content_hash;
|
|
533
530
|
} catch {
|
|
534
531
|
liveContentHash = null;
|
|
535
532
|
}
|
|
@@ -557,40 +554,40 @@ async function executeForegroundEnrollment(
|
|
|
557
554
|
preparation_digest: preparation.digest,
|
|
558
555
|
actor_id: LITERAL_USER_ACTOR_ID,
|
|
559
556
|
confirmation_ref: `pi-confirm-${createHash("sha256").update(`${taskId}\0${now}\0${nonce}`).digest("hex").slice(0, 16)}`,
|
|
560
|
-
expires_at: new Date(Date.now() + 10 * 60 * 1000).toISOString(),
|
|
561
557
|
nonce,
|
|
562
558
|
};
|
|
563
|
-
const capability = registry.issue(binding);
|
|
564
|
-
const input = {
|
|
565
|
-
task_id: taskId,
|
|
566
|
-
intent_path: binding.intent_path,
|
|
567
|
-
intent_revision: binding.intent_revision,
|
|
568
|
-
preparation_digest: binding.preparation_digest,
|
|
569
|
-
capability,
|
|
570
|
-
capability_binding: binding,
|
|
571
|
-
now,
|
|
572
|
-
};
|
|
573
559
|
|
|
574
560
|
progress("rehearsing", uxText(UX_LANG, "Running the zero-write Kernel owner rehearsal", "正在执行 Kernel 所有者零写入预演"));
|
|
575
|
-
const rehearsal = await runEnrollmentRehearsal(root, input, capability, registry);
|
|
576
|
-
if (!rehearsal.rehearsed || rehearsal.evidence.outcome !== "ready")
|
|
577
|
-
return terminal(action, taskId, "failed", stage, `Kernel enrollment rehearsal failed: ${rehearsal.evidence.blockers.join("; ")}${gitBaseNote}`, "resolve the final-lock preconditions and retry");
|
|
578
|
-
if (signal.aborted) return cancelled();
|
|
579
|
-
if (!beginCommit()) return cancelled();
|
|
580
|
-
|
|
581
|
-
stage = "committing";
|
|
582
|
-
onUpdate?.(updateResult(action, taskId, stage, "Kernel enrollment commit owns settlement and is no longer cancellable"));
|
|
583
561
|
try {
|
|
584
|
-
|
|
562
|
+
// The single Enrollment entry owns issue -> rehearse -> checkpoint ->
|
|
563
|
+
// commit. The checkpoint keeps the Tool's abort/begin-commit gate
|
|
564
|
+
// between rehearsal and commit: a declined checkpoint cancels with
|
|
565
|
+
// zero writes, and once it accepts, commit is no longer cancellable.
|
|
566
|
+
const outcome = await enrollTask(root, registry, {
|
|
567
|
+
binding,
|
|
568
|
+
now,
|
|
569
|
+
checkpoint: () => {
|
|
570
|
+
if (signal.aborted) return false;
|
|
571
|
+
if (!beginCommit()) return false;
|
|
572
|
+
stage = "committing";
|
|
573
|
+
onUpdate?.(updateResult(action, taskId, stage, "Kernel enrollment commit owns settlement and is no longer cancellable"));
|
|
574
|
+
return true;
|
|
575
|
+
},
|
|
576
|
+
});
|
|
577
|
+
if (outcome.outcome === "cancelled") return cancelled();
|
|
578
|
+
const result = outcome.result;
|
|
585
579
|
return terminal(
|
|
586
580
|
action,
|
|
587
581
|
taskId,
|
|
588
582
|
"completed",
|
|
589
583
|
stage,
|
|
590
584
|
`Kernel enrollment completed: task ${result.record.task_id} state=${result.record.lifecycle}:${result.record.artifact_state} backend=${result.backend_claim.backend}`,
|
|
591
|
-
"continue with imm-
|
|
585
|
+
"continue with imm-run",
|
|
592
586
|
);
|
|
593
587
|
} catch (error) {
|
|
588
|
+
if (error instanceof EnrollmentRehearsalError)
|
|
589
|
+
return terminal(action, taskId, "failed", stage, `${error.message}${gitBaseNote}`, "resolve the final-lock preconditions and retry");
|
|
590
|
+
if (stage !== "committing") throw error;
|
|
594
591
|
const failure = await classifyCommitFailure(root, action, taskId, now, error);
|
|
595
592
|
failure.summary += gitBaseNote;
|
|
596
593
|
return failure;
|