immune-brain 4.2.0 → 4.4.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 CHANGED
@@ -116,6 +116,7 @@ Immune-Brain provides two clean modes: **Host-native** for daily coding, and **M
116
116
  | Plan confirmed, ready to build & verify | `/imm-loop` | → Executor builds within scope → deterministic QA verifies → isolated Review checks → task settles |
117
117
  | Session interrupted or resuming a task | `/imm-loop` | → Resumes existing task seamlessly from on-disk state (`.imm/`) |
118
118
  | Ready Initiative to run unattended | "Run initiative `<slug>` unattended" | → Host's `start_unattended_batch`: one native confirmation covers ordered plan digest, children run serially |
119
+ | Cross-host workflow (Claude plan + Pi code) | Run `/imm-planner` in Claude Code, switch to Pi and run `/imm-loop` | → Staged Spec & TaskIntent are shared on disk; Pi confirms via native TUI and executes loop |
119
120
  | PR has review comments or failing CI | `/imm-pr-fix` on that PR | → Standalone repair: minimal scoped fix in place, no managed task created |
120
121
  | Project docs out of date | `/imm-doc-prune` | → Read-only audit; deletes only user-approved stale docs from manifest |
121
122
  | Agent instructions bloated | `/imm-agent-doc-maintain` | → Minimizes tracked `AGENTS.md` / `CLAUDE.md` to essential non-discoverable rules |
@@ -125,6 +126,40 @@ Immune-Brain provides two clean modes: **Host-native** for daily coding, and **M
125
126
  > - **Ordinary input stays host-native**: Natural language queries never automatically start planning or task enrollment. You choose when to turn on engineering rigor.
126
127
  > - **Managed work starts with explicit skills**: Use `imm-brainstorm` to clarify, `imm-planner` to plan, and `imm-loop` to execute and resume.
127
128
 
129
+ ### Cross-Host Workflow: Plan in Claude Code, Build in Pi
130
+
131
+ Immune-Brain is architected to be completely session-neutral. All task contracts, specifications, and assurance evidence live on disk in Git-tracked files (`docs/plans/`, `docs/specs/`) and `.imm/`. Pi and Claude Code share the exact same deterministic Kernel authority and state machine.
132
+
133
+ This enables a best-of-both-worlds workflow: **leverage Claude Code's deep reasoning and large context window for requirement analysis and Spec planning, then switch to Pi for fast, focused foreground coding and execution loops**.
134
+
135
+ ```text
136
+ ┌───────────────────────────────────┐ Git-Tracked Artifacts on Disk ┌───────────────────────────────────┐
137
+ │ Claude Code │ ─────────────────────────────────> │ Pi │
138
+ │ 1. /imm-brainstorm (Clarify) │ docs/specs/*.spec.md │ 1. /imm-loop (Native TUI Modal) │
139
+ │ 2. /imm-planner (Spec/Intent) │ docs/plans/*.intent.json │ 2. Executor (Code) + QA Engine │
140
+ └───────────────────────────────────┘ └───────────────────────────────────┘
141
+ ```
142
+
143
+ #### Recommended Workflow
144
+
145
+ 1. **Phase 1: Spec Authoring & Planning in Claude Code**
146
+ - **Clarify requirements (optional)**: If the problem is fuzzy or has unknown boundaries, run `/imm-brainstorm` in Claude Code to frame goals, constraints, and architecture risks.
147
+ - **Author the plan and spec**: Run `/imm-planner "Plan <feature>"`. Planner generates:
148
+ - Living Spec (`docs/specs/<name>.spec.md`): records the technical design and architectural trade-offs.
149
+ - `TaskIntent` (`docs/plans/<task-id>.intent.json`): strictly locks down the editable file boundary (`scope_hint`), risk tier (`routine` / `material` / `critical`), and deterministic test verification commands (`acceptance`).
150
+ - **Stage in Git**: Stage the generated artifacts (`git add docs/`). You can stop before Enrollment without executing.
151
+ 2. **Phase 2: Code Implementation & Execution in Pi**
152
+ - **Launch Pi**: Open Pi in the same repository workspace.
153
+ - **Enroll & run**: Enter `/imm-loop`. Pi discovers the staged `TaskIntent` and opens its native TUI modal confirmation for Enrollment.
154
+ - **Automated loop**:
155
+ - **Executor** writes implementation code strictly inside `scope_hint`.
156
+ - **Deterministic QA engine** directly runs acceptance commands against exit codes.
157
+ - For `material` or `critical` tasks, Pi foreground Reviewer audits changes.
158
+ - Upon pass, Kernel atomically settles terminal audit records in `.imm/audit/<task-id>/` and releases the workspace claim.
159
+ 3. **Why Cross-Host Switching Works Seamlessly**
160
+ - **Session-neutral state**: All contracts and authority records live in the repository and local SQLite CAS, completely independent of any individual AI chat session.
161
+ - **Bidirectional resumption**: Interrupted tasks can be resumed at any point in either Pi or Claude Code with `/imm-loop`.
162
+
128
163
  ---
129
164
 
130
165
  ## The 7 Skills
@@ -328,6 +363,8 @@ docs/specs/ # Living specs (updated in place)
328
363
 
329
364
  **Can it run a whole Initiative without me?** Only as far as you authorize. Confirm `start_unattended_batch` with the Initiative slug and the runner works through the published, non-`critical` children serially on one batch branch — parking as soon as a child needs a human decision or the run hits a budget, deadline, authorization, or commit failure. It never pushes, opens PRs, or settles user decisions for you.
330
365
 
366
+ **Can I switch between hosts (e.g. plan in Claude Code, code in Pi)?** Yes. Immune-Brain's contracts and state live entirely on disk in the repository, decoupled from conversation sessions. You can leverage Claude Code for deep architectural thinking and Spec planning, then switch to Pi to run `imm-loop` for code execution and deterministic QA. Interrupted tasks can be resumed in either host at any time.
367
+
331
368
  **Which AI coding assistants are supported?** Pi and Claude Code are the supported hosts (Claude Code version >= `2.1.236`). Both hosts run on the exact same Kernel authority, assurance guarantees, and multi-skill pipeline.
332
369
 
333
370
  ---
package/README.zh-CN.md CHANGED
@@ -116,6 +116,7 @@ Immune-Brain 提供两种清晰的工作模式:日常轻量编码走 **Host-na
116
116
  | 计划已确认,准备执行与验证 | `/imm-loop` | → Executor 在范围内实现 → 确定性 QA 验收 → 隔离 Review 审查 → 任务结算 |
117
117
  | 会话中断或需恢复未完成任务 | `/imm-loop` | → 从磁盘状态(`.imm/`)无缝恢复,以 Kernel projection 为准 |
118
118
  | 已发布的 Initiative 可以整批跑了 | "把 initiative `<slug>` 无人值守跑完" | → Host 的 `start_unattended_batch`:一次原生确认绑定有序 plan digest,child 串行执行 |
119
+ | 跨 Host 协作(Claude 规划 + Pi 编码) | 在 Claude Code 中调 `/imm-planner`,切到 Pi 输入 `/imm-loop` | → Spec 与 TaskIntent 共享于 Git,Pi 原生弹窗准入并执行 QA/Review 闭环 |
119
120
  | PR 被评论 / CI 挂了 | 对该 PR 使用 `/imm-pr-fix` | → 独立修复:在当前 PR 内针对性修复,不创建新 managed 任务 |
120
121
  | 文档过时需要清理 | `/imm-doc-prune` | → 只读审计过时文档,仅删除经哈希审批的条目 |
121
122
  | Agent 指令文件膨胀 | `/imm-agent-doc-maintain` | → 将 tracked `AGENTS.md` / `CLAUDE.md` 压到最小必要上下文 |
@@ -125,6 +126,40 @@ Immune-Brain 提供两种清晰的工作模式:日常轻量编码走 **Host-na
125
126
  > - **普通输入保持 Host-native**:自然语言提问绝不自动绑架流程或发起 Enrollment。你完全自主决定何时开启严格工程保障。
126
127
  > - **Managed 工作流显式启动**:需要澄清用 `imm-brainstorm`,制定计划用 `imm-planner`,执行与恢复用 `imm-loop`。
127
128
 
129
+ ### 跨 Host 协作:Claude Code 规划 + Pi 编码执行
130
+
131
+ Immune-Brain 的核心状态与契约完全去会话化(Session-neutral),所有规划与审计证据均落盘在 Git 仓库(`docs/plans/`、`docs/specs/`)与 `.imm/` 中。Pi 与 Claude Code 共享完全一致的确定性 Kernel 核心与状态机。
132
+
133
+ 你可以自由组合两个宿主的优势:**利用 Claude Code 的深度推理与长上下文能力进行需求澄清、Spec 撰写与任务规划,切换到 Pi 中进行极速的前台编码、确定性 QA 验收与审查闭环**。
134
+
135
+ ```text
136
+ ┌───────────────────────────────────┐ Git 追踪制品(落盘共享) ┌───────────────────────────────────┐
137
+ │ Claude Code 终端 │ ───────────────────────────> │ Pi 终端 │
138
+ │ 1. /imm-brainstorm (澄清与约束) │ docs/specs/*.spec.md │ 1. /imm-loop (原生 TUI 弹窗准入) │
139
+ │ 2. /imm-planner (编写计划/规格) │ docs/plans/*.intent.json │ 2. Executor 编码 + QA 自动化验收 │
140
+ └───────────────────────────────────┘ └───────────────────────────────────┘
141
+ ```
142
+
143
+ #### 推荐协作步骤
144
+
145
+ 1. **在 Claude Code 中制定 Spec 与任务规划**
146
+ - **需求澄清(可选)**:若需求复杂或边界模糊,先在 Claude Code 中运行 `/imm-brainstorm`,梳理目标、约束与架构风险。
147
+ - **编写计划与规格**:运行 `/imm-planner "规划 <需求名称>"`。Planner 会生成:
148
+ - Living Spec(`docs/specs/<name>.spec.md`):记录设计方案、架构决策与模块边界。
149
+ - `TaskIntent`(`docs/plans/<task-id>.intent.json`):严格锁定可修改的文件范围(`scope_hint`)、风险等级(`routine` / `material` / `critical`)以及可执行的自动化验收命令(`acceptance`)。
150
+ - **暂存至 Git**:规划完成后停在 Enrollment 之前,将生成的 Spec 和 TaskIntent 加入 Git 暂存(`git add docs/`)。
151
+ 2. **切换到 Pi 中进行代码编写与闭环执行**
152
+ - **启动 Pi**:在同一个项目工作区中打开 Pi。
153
+ - **确认准入并执行**:运行 `/imm-loop`。Pi 会自动检测到暂存的 `TaskIntent`,并在 Pi 原生 TUI 弹窗中提示 Enrollment 确认。
154
+ - **自动执行与验收**:
155
+ - Executor 角色严格在 `scope_hint` 限定的文件内编写代码。
156
+ - Kernel 自动运行 acceptance 命令进行确定性 QA 验收,不依赖口头汇报。
157
+ - 若为 `material` 或 `critical` 任务,自动调度前台 Reviewer 审查。
158
+ - 验证全部通过后,Kernel 原子落盘证据至 `.imm/audit/<task-id>/` 并释放工作区锁定。
159
+ 3. **为什么可以无缝切换?**
160
+ - **状态落盘,解耦会话**:所有任务契约(TaskIntent)、设计规格(Spec)和执行状态(`.imm/state/kernel.sqlite`)均持久化在磁盘上,不绑定任何特定 AI 会话的上下文。
161
+ - **双向断点恢复**:无论在哪个 Host 暂停或关闭会话,随时可以在 Pi 或 Claude Code 中重新输入 `/imm-loop` 无缝恢复,Kernel projection 确保进度与证据不丢失。
162
+
128
163
  ---
129
164
 
130
165
  ## 7 个 Skills
@@ -328,6 +363,8 @@ docs/specs/ # Living specs(原地更新)
328
363
 
329
364
  **能不能整个 Initiative 不用我盯着?** 只能在你授权范围内。用 Initiative slug 确认 `start_unattended_batch` 后,runner 会在一个 batch 分支上串行推进已发布且非 `critical` 的 child — 一旦某个 child 需要人决策,或遇到预算/截止时间/授权/提交失败就暂停。它不会替你 push、开 PR 或结算用户决策。
330
365
 
366
+ **可以在不同 Host 之间切换吗(例如 Claude Code 规划、Pi 编码)?** 可以。Immune-Brain 的契约与状态完全落盘于代码仓库,解耦了会话上下文。你可以用 Claude Code 进行深度推理与制定 Spec,再切换到 Pi 跑 `imm-loop` 编码并完成 QA 闭环;中途随时可以用 `/imm-loop` 双向恢复。
367
+
331
368
  **支持哪些 AI 编程工具?** Pi 与 Claude Code 是支持的宿主(Claude Code 最低版本为 `2.1.236`)。两者共享同一套确定性 Kernel 核心、质量保障机制与工具链。
332
369
 
333
370
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "immune-brain",
3
- "version": "4.2.0",
3
+ "version": "4.4.0",
4
4
  "description": "Immune-Brain agent skill system",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "immune-brain",
3
- "version": "4.2.0",
3
+ "version": "4.4.0",
4
4
  "description": "Immune-Brain Claude Code Host: native Enrollment, QA, Review, and Kernel settlement.",
5
5
  "author": {
6
6
  "name": "Immune-Brain Team"
@@ -26,6 +26,9 @@ import {
26
26
  withKernelStoreLock,
27
27
  inspectStorageLayout,
28
28
  migrateLegacyLayout,
29
+ inspectEnrollmentGitBase,
30
+ enrollmentGitBaseNotice,
31
+ initializeEnrollmentGitBase,
29
32
  } from "./runtime-stub";
30
33
  import {
31
34
  presentTaskRail,
@@ -292,6 +295,7 @@ async function executeForegroundEnrollment(
292
295
  pi: Pick<ExtensionAPI, "events">,
293
296
  ): Promise<EnrollmentTerminal> {
294
297
  let stage = "preparing";
298
+ let gitBaseNote = "";
295
299
  const progress = (nextStage: string, summary: string) => {
296
300
  stage = nextStage;
297
301
  const update = updateResult(action, taskId, nextStage, summary);
@@ -303,7 +307,7 @@ async function executeForegroundEnrollment(
303
307
  taskId,
304
308
  "cancelled",
305
309
  stage,
306
- `Foreground enrollment cancelled during ${stage}; zero authority writes were requested`,
310
+ `Foreground enrollment cancelled during ${stage}; zero authority writes were requested${gitBaseNote}`,
307
311
  "retry by invoking the launcher again",
308
312
  );
309
313
 
@@ -437,7 +441,7 @@ async function executeForegroundEnrollment(
437
441
  `task ${taskId} is terminal in this worktree`,
438
442
  "inspect authority state; do not retry enrollment",
439
443
  );
440
- const preparation = await preparePiCanary(root, { task_id: taskId, now });
444
+ let preparation = await preparePiCanary(root, { task_id: taskId, now });
441
445
  signal.throwIfAborted();
442
446
  if (!preparation.intent)
443
447
  return terminal(action, taskId, "blocked", stage, "A Git-tracked TaskIntent is required for Kernel enrollment", "author and stage the canonical TaskIntent");
@@ -468,6 +472,8 @@ async function executeForegroundEnrollment(
468
472
  return terminal(action, taskId, "blocked", stage, `Enrollment is ineligible: ${reasons}`, "resolve the eligibility blockers");
469
473
  }
470
474
 
475
+ const gitBase = await inspectEnrollmentGitBase(root);
476
+ const gitNotice = await enrollmentGitBaseNotice(gitBase);
471
477
  const acceptanceDetails = taskIntent.intent.acceptance.length === 0
472
478
  ? "(none)"
473
479
  : taskIntent.intent.acceptance
@@ -483,6 +489,7 @@ async function executeForegroundEnrollment(
483
489
  `Risk: ${taskIntent.intent.risk}`,
484
490
  `Scope: ${taskIntent.intent.scope_hint.length > 0 ? taskIntent.intent.scope_hint.join(", ") : "(none)"}`,
485
491
  `Acceptance: ${taskIntent.intent.acceptance.length} descriptor(s)`,
492
+ ...(gitNotice ? [gitNotice] : []),
486
493
  ].join("\n");
487
494
  const confirmationDetails = [
488
495
  `Acceptance descriptors:`,
@@ -536,6 +543,11 @@ async function executeForegroundEnrollment(
536
543
  return terminal(action, taskId, "blocked", stage, "Workspace changed after confirmation; enrollment aborted before authority", "restore the intended snapshot and rerun enrollment");
537
544
  signal.throwIfAborted();
538
545
 
546
+ preparation = await initializeEnrollmentGitBase(root, { task_id: taskId, now }, preparation, gitBase, signal);
547
+ if (gitBase.state === "unborn") gitBaseNote = `; empty initial commit ${preparation.git_base_head} remains`;
548
+ if (!preparation.intent) throw new Error("Enrollment requires a readable TaskIntent");
549
+ signal.throwIfAborted();
550
+
539
551
  const nonce = randomUUID();
540
552
  const binding = {
541
553
  task_id: taskId,
@@ -562,7 +574,7 @@ async function executeForegroundEnrollment(
562
574
  progress("rehearsing", uxText(UX_LANG, "Running the zero-write Kernel owner rehearsal", "正在执行 Kernel 所有者零写入预演"));
563
575
  const rehearsal = await runEnrollmentRehearsal(root, input, capability, registry);
564
576
  if (!rehearsal.rehearsed || rehearsal.evidence.outcome !== "ready")
565
- return terminal(action, taskId, "failed", stage, `Kernel enrollment rehearsal failed: ${rehearsal.evidence.blockers.join("; ")}`, "resolve the final-lock preconditions and retry");
577
+ return terminal(action, taskId, "failed", stage, `Kernel enrollment rehearsal failed: ${rehearsal.evidence.blockers.join("; ")}${gitBaseNote}`, "resolve the final-lock preconditions and retry");
566
578
  if (signal.aborted) return cancelled();
567
579
  if (!beginCommit()) return cancelled();
568
580
 
@@ -579,11 +591,13 @@ async function executeForegroundEnrollment(
579
591
  "continue with imm-loop",
580
592
  );
581
593
  } catch (error) {
582
- return classifyCommitFailure(root, action, taskId, now, error);
594
+ const failure = await classifyCommitFailure(root, action, taskId, now, error);
595
+ failure.summary += gitBaseNote;
596
+ return failure;
583
597
  }
584
598
  } catch (error) {
585
599
  if (signal.aborted) return cancelled();
586
- return terminal(action, taskId, "failed", stage, `Foreground enrollment failed during ${stage}: ${errorMessage(error)}`, "correct the reported failure and retry");
600
+ return terminal(action, taskId, "failed", stage, `Foreground enrollment failed during ${stage}: ${errorMessage(error)}${gitBaseNote}`, "correct the reported failure and retry");
587
601
  }
588
602
  }
589
603
 
@@ -43,18 +43,8 @@ export interface PiCanaryPrepareInput {
43
43
  task_id: string;
44
44
  now: string;
45
45
  }
46
- export interface PiCanaryPreparation {
47
- contract: "assurance_kernel/pi_canary_preparation/v1";
48
- task_id: string;
49
- generated_at: string;
50
- root_state_path: string;
51
- intent: { path: string; revision: number; content_hash: string } | null;
52
- backend_claim: { present: boolean; task_id: string | null; lifecycle_status: string | null };
53
- task_tombstone: { present: boolean; terminal_lifecycle: string | null };
54
- task_record_v3: { present: boolean; lifecycle: string | null; artifact_state: string | null } | null;
55
- workspace: { current_working: string | null };
56
- digest: string;
57
- }
46
+ export type PiCanaryPreparation = import("../runtime/kernel/pi_canary_prepare").PiCanaryPreparation;
47
+ export type EnrollmentGitBase = import("../runtime/assurance/enrollment_git_base").EnrollmentGitBase;
58
48
  export interface EnrollCanaryInput {
59
49
  task_id: string;
60
50
  intent_path: string;
@@ -242,6 +232,18 @@ export async function createEnrollmentAuthorityRegistry(): Promise<EnrollmentAut
242
232
  const mod = await import(/* @vite-ignore */ kernelPath("enrollment_authority"));
243
233
  return mod.createEnrollmentAuthorityRegistry();
244
234
  }
235
+ export async function inspectEnrollmentGitBase(root: string): Promise<EnrollmentGitBase> {
236
+ const mod = await import(/* @vite-ignore */ runtimePath("assurance/enrollment_git_base"));
237
+ return mod.inspectEnrollmentGitBase(root);
238
+ }
239
+ export async function enrollmentGitBaseNotice(base: EnrollmentGitBase): Promise<string | undefined> {
240
+ const mod = await import(/* @vite-ignore */ runtimePath("assurance/enrollment_git_base"));
241
+ return mod.enrollmentGitBaseNotice(base);
242
+ }
243
+ export async function initializeEnrollmentGitBase(root: string, input: PiCanaryPrepareInput, previous: PiCanaryPreparation, base: EnrollmentGitBase, signal?: AbortSignal): Promise<PiCanaryPreparation> {
244
+ const mod = await import(/* @vite-ignore */ runtimePath("assurance/enrollment_git_base"));
245
+ return mod.initializeEnrollmentGitBase(root, input, previous, base, signal);
246
+ }
245
247
  export async function preparePiCanary(
246
248
  root: string,
247
249
  input: PiCanaryPrepareInput,
@@ -93,6 +93,8 @@ Privileged effects include:
93
93
 
94
94
  Routine Managed enrollment uses one current-Host native confirmation bound to the TaskIntent content hash after Planner validation. Explicit Plan-only requests stop with candidate artifacts and do not invoke Enrollment; execution-bearing requests open the native gate directly without chat pre-confirmation. Enrollment validates intent, Git ownership, scope, workspace claim, and final authority preconditions without executing acceptance descriptors; deterministic QA executes them after implementation. The routine task proceeds from that single confirmation through enrollment, execution, and QA without a second human stop. Do not request confirmation for local in-scope edits, local verification, ordinary Direct rework, scoped diff review, or completion reporting. Managed evidence, QA, Review, and completion authority remain governed by their Managed contracts; R2 does not weaken them. Managed native-authority failures fail closed with one stable reason and exactly one same-Host recovery action; never offer a Pi, Direct Path, cross-Host/worktree, unmanaged, or automatic-retry fallback.
95
95
 
96
+ For an unborn symbolic Git HEAD, the same Enrollment confirmation discloses an empty root commit. After approval, the Host creates that commit without staging project content or changing the index/worktree, then revalidates ownership and rehearses Enrollment against the new base. Git identity uses existing environment/config values with an explicit automation fallback, never config writes. Decline or pre-initialization cancellation leaves HEAD unborn; if later Enrollment fails or is cancelled, report the remaining commit. Invalid Git refs are errors, not initialization candidates.
97
+
96
98
  ## Parallel Read-Only Dispatch
97
99
 
98
100
  State mutations, step activations, QA decisions, and plan switches remain