immune-brain 4.0.1 → 4.2.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 +48 -22
- package/README.zh-CN.md +48 -22
- 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 +12 -8
- package/plugins/immune-brain/.pi-extension/imm-canary-work.ts +31 -11
- package/plugins/immune-brain/.pi-extension/ux-language.ts +28 -0
- package/plugins/immune-brain/dist/BASELINE.md +17 -2
- package/plugins/immune-brain/dist/claude/mcp-server.mjs +12 -1
- package/plugins/immune-brain/dist/imm-loop.md +14 -1
- package/plugins/immune-brain/dist/imm-planner.md +58 -4
- package/plugins/immune-brain/runtime/plugin_version.ts +1 -1
- package/plugins/immune-brain/runtime/role_prompt_bridge.ts +21 -0
- package/plugins/immune-brain/skills/BASELINE.md +17 -2
package/README.md
CHANGED
|
@@ -198,29 +198,55 @@ The three repair/maintenance skills are host-native: they never create a managed
|
|
|
198
198
|
|
|
199
199
|
## Lifecycle
|
|
200
200
|
|
|
201
|
+
```mermaid
|
|
202
|
+
flowchart TD
|
|
203
|
+
subgraph Planning ["1. Planning Phase"]
|
|
204
|
+
B["imm-brainstorm<br/>Clarify Requirements & Constraints"] --> P["imm-planner<br/>Author Spec & TaskIntent"]
|
|
205
|
+
P --> TI["TaskIntent (.intent.json)<br/>• goal / scope_hint<br/>• risk tier<br/>• acceptance descriptors"]
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
subgraph Enrollment ["2. Enrollment Gate"]
|
|
209
|
+
TI --> EG{"Native User Gate<br/>Host Modal Confirmation"}
|
|
210
|
+
EG -->|Confirm| KS[(".imm/state/kernel.sqlite<br/>Atomic TaskRecord<br/>Exclusive Workspace Claim")]
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
subgraph Loop ["3. Execution & Assurance Loop (imm-loop)"]
|
|
214
|
+
KS --> EX["Executor Role<br/>Edit code strictly inside scope_hint"]
|
|
215
|
+
EX --> FRZ["advance_assurance<br/>Artifacts frozen (active:frozen)"]
|
|
216
|
+
FRZ --> QA["Deterministic QA Engine<br/>Run acceptance verification commands<br/>Generate QA Attestation"]
|
|
217
|
+
|
|
218
|
+
QA -->|Fail| RW1["Rework / Fix"]
|
|
219
|
+
RW1 --> EX
|
|
220
|
+
|
|
221
|
+
QA -->|Pass| RK{"Risk Tier?"}
|
|
222
|
+
RK -->|routine| ST["Settlement"]
|
|
223
|
+
RK -->|material / critical| RV["Review Role<br/>Structured verdict (Pass / Rework)"]
|
|
224
|
+
|
|
225
|
+
RV -->|Rework| RW2["Rework"]
|
|
226
|
+
RW2 --> EX
|
|
227
|
+
RV -->|Pass| ST
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
subgraph Settlement ["4. Settlement & Learnings"]
|
|
231
|
+
ST --> CLS["Atomic Closure<br/>• Lifecycle: done<br/>• Audit evidence in .imm/audit/<br/>• Release Workspace Claim"]
|
|
232
|
+
CLS -.-> CP["Compounder Role<br/>Extract Learnings to docs/solutions/"]
|
|
233
|
+
end
|
|
201
234
|
```
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
▼
|
|
218
|
-
imm-loop
|
|
219
|
-
├── Executor (edits strictly inside scope)
|
|
220
|
-
├── Deterministic QA (runs all acceptance checks)
|
|
221
|
-
├── Isolated Review (independent subagent audit)
|
|
222
|
-
└── Settled (.imm/audit/<task-id>/)
|
|
223
|
-
```
|
|
235
|
+
|
|
236
|
+
### Core Logic: Three Pillars
|
|
237
|
+
|
|
238
|
+
1. **Two Paths**
|
|
239
|
+
- **Host-native Path**: Daily conversation, code inspections, and ad-hoc fixes stay 100% native with zero workflow overhead.
|
|
240
|
+
- **Managed Path**: Explicitly entered via `imm-brainstorm`, `imm-planner`, or `imm-loop`, strictly governed by the Assurance Kernel.
|
|
241
|
+
|
|
242
|
+
2. **Authority & Contract**
|
|
243
|
+
- **TaskIntent (`.intent.json`)**: Machine-readable behavioral contract locking `scope_hint` (file boundaries), `risk` tier, and `acceptance` descriptors.
|
|
244
|
+
- **Native Gate (Enrollment)**: The single human-authority confirmation gate; Kernel atomically acquires exclusive workspace ownership (`.imm/state/kernel.sqlite` CAS) to prevent concurrency conflicts and scope drift.
|
|
245
|
+
|
|
246
|
+
3. **Deterministic Assurance**
|
|
247
|
+
- **QA-First**: The Kernel directly runs verification commands and checks exit codes/byte bounds; never relies on conversational claims.
|
|
248
|
+
- **Risk-Tiered Gates**: `routine` tasks complete upon QA pass; `material` and `critical` tasks require an isolated Review subagent to issue a structured verdict.
|
|
249
|
+
- **Unattended Batch**: Serial execution driven by GitHub Issues and bound by `plan_digest`, where each child independently completes its own Enrollment → QA → Review → Commit cycle.
|
|
224
250
|
|
|
225
251
|
Key invariants:
|
|
226
252
|
|
package/README.zh-CN.md
CHANGED
|
@@ -198,29 +198,55 @@ Executor、QA、Review、Compounder 等为 `imm-loop` 内部调度的角色,
|
|
|
198
198
|
|
|
199
199
|
## 生命周期
|
|
200
200
|
|
|
201
|
+
```mermaid
|
|
202
|
+
flowchart TD
|
|
203
|
+
subgraph Planning ["1. 规划阶段"]
|
|
204
|
+
B["imm-brainstorm<br/>需求澄清/约束"] --> P["imm-planner<br/>编写 Spec & TaskIntent"]
|
|
205
|
+
P --> TI["TaskIntent (.intent.json)<br/>• goal / scope_hint<br/>• risk tier<br/>• acceptance descriptors"]
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
subgraph Enrollment ["2. 准入登记"]
|
|
209
|
+
TI --> EG{"Native User Gate<br/>当前 Host 弹窗确认"}
|
|
210
|
+
EG -->|确认| KS[(".imm/state/kernel.sqlite<br/>原子生成 TaskRecord<br/>独占 Workspace Claim")]
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
subgraph Loop ["3. 执行与验证循环 (imm-loop)"]
|
|
214
|
+
KS --> EX["Executor 角色<br/>在 scope_hint 范围内修改代码"]
|
|
215
|
+
EX --> FRZ["advance_assurance<br/>制品冻结 (active:frozen)"]
|
|
216
|
+
FRZ --> QA["确定性 QA 引擎<br/>原子运行 acceptance 校验命令<br/>生成 QA Attestation"]
|
|
217
|
+
|
|
218
|
+
QA -->|失败| RW1["Rework 返工修正"]
|
|
219
|
+
RW1 --> EX
|
|
220
|
+
|
|
221
|
+
QA -->|通过| RK{"Risk 等级?"}
|
|
222
|
+
RK -->|routine| ST["Settlement 结算"]
|
|
223
|
+
RK -->|material / critical| RV["Review 审查角色<br/>结构化裁决 (Pass / Rework)"]
|
|
224
|
+
|
|
225
|
+
RV -->|Rework| RW2["Rework 驳回"]
|
|
226
|
+
RW2 --> EX
|
|
227
|
+
RV -->|Pass| ST
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
subgraph Settlement ["4. 结算与沉淀"]
|
|
231
|
+
ST --> CLS["原子结项<br/>• Lifecycle: done<br/>• 写入审计日志 .imm/audit/<br/>• 释放 Workspace Claim"]
|
|
232
|
+
CLS -.-> CP["Compounder 角色<br/>提取经验至 docs/solutions/"]
|
|
233
|
+
end
|
|
201
234
|
```
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
▼
|
|
218
|
-
imm-loop
|
|
219
|
-
├── Executor(严格在 scope 内修改代码)
|
|
220
|
-
├── 确定性 QA(前台逐项执行验收命令)
|
|
221
|
-
├── 隔离式 Review(独立 subagent 审查代码)
|
|
222
|
-
└── 落盘结算(.imm/audit/<task-id>/)
|
|
223
|
-
```
|
|
235
|
+
|
|
236
|
+
### 核心逻辑三要素
|
|
237
|
+
|
|
238
|
+
1. **双轨制 (Two Paths)**
|
|
239
|
+
- **Host-native Path**:日常对话、代码检视、单点修改,不触碰 Kernel 权限,零流程开销。
|
|
240
|
+
- **Managed Path**:由 `imm-brainstorm` / `imm-planner` / `imm-loop` 显式驱动,全程受 Kernel 约束。
|
|
241
|
+
|
|
242
|
+
2. **权限与契约 (Authority & Contract)**
|
|
243
|
+
- **TaskIntent (`.intent.json`)**:机器契约本体,严格锁定 `scope_hint`(文件修改范围)、`risk`(风险层级)与 `acceptance`(确定性断言)。
|
|
244
|
+
- **Native Gate (Enrollment)**:唯一一次人工介入确认,Kernel 原子抢占工作区所有权(SQLite CAS),防止多任务并发冲突与范围漂移。
|
|
245
|
+
|
|
246
|
+
3. **客观验证 (Deterministic Assurance)**
|
|
247
|
+
- **QA 优先**:由 Kernel 直接前台执行命令并校验退出码/输出,不依赖 LLM 口头汇报。
|
|
248
|
+
- **按险定级**:`routine` 仅需 QA;`material`/`critical` 必须追加独立只读 Reviewer 产出结构化裁决。
|
|
249
|
+
- **批处理 (Unattended Batch)**:基于 GitHub Issue / `plan_digest` 串行推进,每个子任务独立走完 Enrollment → QA → Review → Commit 闭环。
|
|
224
250
|
|
|
225
251
|
核心不变量:
|
|
226
252
|
|
package/package.json
CHANGED
|
@@ -37,6 +37,10 @@ import {
|
|
|
37
37
|
type UserAttentionReason,
|
|
38
38
|
} from "./pi-canary-interaction";
|
|
39
39
|
import { isToolFailureState, throwToolFailure } from "./pi-canary-tool-failure";
|
|
40
|
+
import { resolveUxLanguage, uxText } from "./ux-language";
|
|
41
|
+
|
|
42
|
+
/** Host-native UI language; see ux-language.ts. Resolved once per process. */
|
|
43
|
+
const UX_LANG = resolveUxLanguage();
|
|
40
44
|
|
|
41
45
|
const TASK_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
42
46
|
|
|
@@ -62,7 +66,7 @@ async function requestEnrollmentConfirmation(
|
|
|
62
66
|
task_id: taskId,
|
|
63
67
|
state: "Approval required",
|
|
64
68
|
result: title,
|
|
65
|
-
next: "Review enrollment evidence",
|
|
69
|
+
next: uxText(UX_LANG, "Review enrollment evidence", "请审查 Enrollment 证据"),
|
|
66
70
|
});
|
|
67
71
|
const selected = await requestAuthorityDialog(pi, ctx, {
|
|
68
72
|
attention_id: randomUUID(),
|
|
@@ -75,8 +79,8 @@ async function requestEnrollmentConfirmation(
|
|
|
75
79
|
details,
|
|
76
80
|
signal,
|
|
77
81
|
actions: [
|
|
78
|
-
{ value: "confirm", label: "Confirm enrollment", description: "Create the Kernel-managed task" },
|
|
79
|
-
{ value: "cancel", label: "Cancel", description: "Leave planning artifacts and authority unchanged" },
|
|
82
|
+
{ value: "confirm", label: uxText(UX_LANG, "Confirm enrollment", "确认 Enrollment"), description: uxText(UX_LANG, "Create the Kernel-managed task", "创建 Kernel 托管任务") },
|
|
83
|
+
{ value: "cancel", label: uxText(UX_LANG, "Cancel", "取消"), description: uxText(UX_LANG, "Leave planning artifacts and authority unchanged", "不改动规划产物与权限状态") },
|
|
80
84
|
],
|
|
81
85
|
});
|
|
82
86
|
return selected === "confirm";
|
|
@@ -305,7 +309,7 @@ async function executeForegroundEnrollment(
|
|
|
305
309
|
|
|
306
310
|
try {
|
|
307
311
|
signal.throwIfAborted();
|
|
308
|
-
progress("preparing", `Preparing immutable Kernel owners for ${taskId}
|
|
312
|
+
progress("preparing", uxText(UX_LANG, `Preparing immutable Kernel owners for ${taskId}`, `正在为 ${taskId} 准备不可变 Kernel 所有者`));
|
|
309
313
|
const now = new Date().toISOString();
|
|
310
314
|
let taskIntent: Awaited<ReturnType<typeof readTaskIntent>>;
|
|
311
315
|
|
|
@@ -489,13 +493,13 @@ async function executeForegroundEnrollment(
|
|
|
489
493
|
`Owners: intent+workspace+claim+record checked`,
|
|
490
494
|
`Route: Kernel enrollment`,
|
|
491
495
|
].join("\n");
|
|
492
|
-
progress("awaiting_confirmation", "Waiting for exact literal-user confirmation");
|
|
496
|
+
progress("awaiting_confirmation", uxText(UX_LANG, "Waiting for exact literal-user confirmation", "等待本人确认"));
|
|
493
497
|
const confirmed = await requestEnrollmentConfirmation(
|
|
494
498
|
pi,
|
|
495
499
|
ctx,
|
|
496
500
|
taskId,
|
|
497
501
|
"enrollment",
|
|
498
|
-
"Create Kernel-managed task?",
|
|
502
|
+
uxText(UX_LANG, "Create Kernel-managed task?", "创建 Kernel 托管任务?"),
|
|
499
503
|
confirmationSummary,
|
|
500
504
|
confirmationDetails,
|
|
501
505
|
signal,
|
|
@@ -526,7 +530,7 @@ async function executeForegroundEnrollment(
|
|
|
526
530
|
return terminal(action, taskId, "blocked", stage, "Intent changed after confirmation; enrollment aborted before authority", "restore the intended snapshot and rerun enrollment");
|
|
527
531
|
}
|
|
528
532
|
|
|
529
|
-
progress("revalidating", "Revalidating immutable owners and the confirmed TaskIntent");
|
|
533
|
+
progress("revalidating", uxText(UX_LANG, "Revalidating immutable owners and the confirmed TaskIntent", "正在重新校验不可变所有者与已确认的 TaskIntent"));
|
|
530
534
|
const { unchanged } = await revalidatePiCanary(root, { task_id: taskId, now }, preparation);
|
|
531
535
|
if (!unchanged)
|
|
532
536
|
return terminal(action, taskId, "blocked", stage, "Workspace changed after confirmation; enrollment aborted before authority", "restore the intended snapshot and rerun enrollment");
|
|
@@ -555,7 +559,7 @@ async function executeForegroundEnrollment(
|
|
|
555
559
|
now,
|
|
556
560
|
};
|
|
557
561
|
|
|
558
|
-
progress("rehearsing", "Running the zero-write Kernel owner rehearsal");
|
|
562
|
+
progress("rehearsing", uxText(UX_LANG, "Running the zero-write Kernel owner rehearsal", "正在执行 Kernel 所有者零写入预演"));
|
|
559
563
|
const rehearsal = await runEnrollmentRehearsal(root, input, capability, registry);
|
|
560
564
|
if (!rehearsal.rehearsed || rehearsal.evidence.outcome !== "ready")
|
|
561
565
|
return terminal(action, taskId, "failed", stage, `Kernel enrollment rehearsal failed: ${rehearsal.evidence.blockers.join("; ")}`, "resolve the final-lock preconditions and retry");
|
|
@@ -65,6 +65,10 @@ import {
|
|
|
65
65
|
type UserAttentionReason,
|
|
66
66
|
} from "./pi-canary-interaction";
|
|
67
67
|
import { isToolFailureState, throwToolFailure, type ToolFailureV1 } from "./pi-canary-tool-failure";
|
|
68
|
+
import { resolveUxLanguage, uxText } from "./ux-language";
|
|
69
|
+
|
|
70
|
+
/** Host-native UI language; see ux-language.ts. Resolved once per process. */
|
|
71
|
+
const UX_LANG = resolveUxLanguage();
|
|
68
72
|
import { taskDiffIdentity, taskRevisionIdentity, captureGitTaskSnapshot } from "../runtime/workspace_scope";
|
|
69
73
|
import { reviewAdvisoryRecords, reviewReworkFindings } from "../runtime/assurance/coordinator";
|
|
70
74
|
import {
|
|
@@ -323,7 +327,7 @@ export default function (
|
|
|
323
327
|
task_id: claim.task_id,
|
|
324
328
|
state: "Blocked",
|
|
325
329
|
result: projection.error,
|
|
326
|
-
next: "Inspect authority state",
|
|
330
|
+
next: uxText(UX_LANG, "Inspect authority state", "检查权限状态"),
|
|
327
331
|
});
|
|
328
332
|
return;
|
|
329
333
|
}
|
|
@@ -395,8 +399,8 @@ export default function (
|
|
|
395
399
|
if (input?.task_id) presentTaskRail(ctx, {
|
|
396
400
|
task_id: input.task_id,
|
|
397
401
|
state: "Planning",
|
|
398
|
-
result: "Preparing enrollment",
|
|
399
|
-
next: "Review the native enrollment decision",
|
|
402
|
+
result: uxText(UX_LANG, "Preparing enrollment", "正在准备 Enrollment"),
|
|
403
|
+
next: uxText(UX_LANG, "Review the native enrollment decision", "请审查原生 Enrollment 决策"),
|
|
400
404
|
});
|
|
401
405
|
}
|
|
402
406
|
});
|
|
@@ -584,11 +588,12 @@ export default function (
|
|
|
584
588
|
}
|
|
585
589
|
const projection = await projectAssuranceState(ctx.cwd, taskId);
|
|
586
590
|
if (projection.error) {
|
|
591
|
+
const nextAction = recoveryActionForAssuranceFailure(projection.error) ?? "inspect authority state";
|
|
587
592
|
const details = {
|
|
588
593
|
state: "blocked",
|
|
589
594
|
operation: action.op,
|
|
590
595
|
result: projection.error,
|
|
591
|
-
next_action:
|
|
596
|
+
next_action: nextAction,
|
|
592
597
|
};
|
|
593
598
|
presentTaskRailResult(ctx, taskId, details);
|
|
594
599
|
return failCanaryTool(taskId, action.op, "blocked", "projection_unavailable", projection.error, details.next_action);
|
|
@@ -871,24 +876,24 @@ export default function (
|
|
|
871
876
|
presentTaskRail(ctx, {
|
|
872
877
|
task_id: taskId,
|
|
873
878
|
state: "Approval required",
|
|
874
|
-
result: `${operation} requires your confirmation`,
|
|
875
|
-
next: `Decide ${operation}`,
|
|
879
|
+
result: uxText(UX_LANG, `${operation} requires your confirmation`, `${operation} 需要您的确认`),
|
|
880
|
+
next: uxText(UX_LANG, `Decide ${operation}`, `请决策 ${operation}`),
|
|
876
881
|
});
|
|
877
882
|
const attention = {
|
|
878
883
|
attention_id: randomUUID(),
|
|
879
884
|
task_id: taskId,
|
|
880
885
|
reason: attentionReason,
|
|
881
|
-
label: `${operation} approval required`,
|
|
886
|
+
label: uxText(UX_LANG, `${operation} approval required`, `${operation} 待您批准`),
|
|
882
887
|
};
|
|
883
888
|
try {
|
|
884
889
|
const selected = await requestAuthorityDialog(pi, ctx, attention, {
|
|
885
|
-
title: `Authorize ${operation}?`,
|
|
890
|
+
title: uxText(UX_LANG, `Authorize ${operation}?`, `是否批准 ${operation}?`),
|
|
886
891
|
summary: dialogSummary,
|
|
887
892
|
details: dialogDetails,
|
|
888
893
|
signal: ctx.signal,
|
|
889
894
|
actions: [
|
|
890
|
-
{ value: "authorize", label: "Authorize", description: `Apply ${operation} after re-checking state` },
|
|
891
|
-
{ value: "cancel", label: "Cancel", description: "Leave managed authority unchanged" },
|
|
895
|
+
{ value: "authorize", label: uxText(UX_LANG, "Authorize", "批准"), description: uxText(UX_LANG, `Apply ${operation} after re-checking state`, `重新校验状态后应用 ${operation}`) },
|
|
896
|
+
{ value: "cancel", label: uxText(UX_LANG, "Cancel", "取消"), description: uxText(UX_LANG, "Leave managed authority unchanged", "保持托管权限状态不变") },
|
|
892
897
|
],
|
|
893
898
|
});
|
|
894
899
|
confirmed = selected === "authorize";
|
|
@@ -1532,7 +1537,7 @@ async function buildAssuranceSnapshot(
|
|
|
1532
1537
|
})
|
|
1533
1538
|
: null;
|
|
1534
1539
|
const taskSnapshot = !reviewBundle && !reviewManifest
|
|
1535
|
-
? captureGitTaskSnapshot(root, intent.scope_hint)
|
|
1540
|
+
? captureGitTaskSnapshot(root, intent.scope_hint, taskId)
|
|
1536
1541
|
: null;
|
|
1537
1542
|
const dirtyFiles = reviewManifest
|
|
1538
1543
|
? Object.keys(reviewManifest.changed_paths)
|
|
@@ -1756,6 +1761,10 @@ async function enrichAssuranceResult(
|
|
|
1756
1761
|
}
|
|
1757
1762
|
|
|
1758
1763
|
function nextActionForAssuranceResult(result: Record<string, unknown>, taskState: AssuranceTaskState): string {
|
|
1764
|
+
const recovery = recoveryActionForAssuranceFailure(
|
|
1765
|
+
"error" in taskState ? taskState.error : result.reason,
|
|
1766
|
+
);
|
|
1767
|
+
if (recovery) return recovery;
|
|
1759
1768
|
if ("error" in taskState) return "inspect authority state";
|
|
1760
1769
|
if (result.state === "review_preparation_failed") return "repair Review preparation, then retry advance_assurance; QA is already committed";
|
|
1761
1770
|
if (result.code === "verdict_invalid") return "fix the verdict payload and resubmit submit_review; the Review reservation remains active; do not re-dispatch the reviewer";
|
|
@@ -1775,6 +1784,17 @@ function nextActionForAssuranceResult(result: Record<string, unknown>, taskState
|
|
|
1775
1784
|
}
|
|
1776
1785
|
}
|
|
1777
1786
|
|
|
1787
|
+
function recoveryActionForAssuranceFailure(reason: unknown): string | null {
|
|
1788
|
+
if (typeof reason !== "string") return null;
|
|
1789
|
+
if (reason.includes("task scope contains unstaged or untracked changes:"))
|
|
1790
|
+
return "stage only the listed task-owned paths, then retry the blocked operation";
|
|
1791
|
+
if (reason.includes("QA resolution failed ("))
|
|
1792
|
+
return "repair the verification command or delivery environment, then retry advance_assurance";
|
|
1793
|
+
if (reason.includes("task delivery contains paths outside the authorization envelope:"))
|
|
1794
|
+
return "reconcile the listed paths: unstage unrelated paths or revise TaskIntent scope for task-owned paths, then retry advance_assurance";
|
|
1795
|
+
return null;
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1778
1798
|
function toolResult(text: string, details?: Record<string, unknown>) {
|
|
1779
1799
|
return { content: [{ type: "text" as const, text }], details };
|
|
1780
1800
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-native UI language for Immune-Brain TUI text (Task Rail sentences,
|
|
3
|
+
* authority dialog titles/actions, progress summaries). This layer is
|
|
4
|
+
* deterministic extension code, so conversational AGENTS.md reply-language
|
|
5
|
+
* rules cannot reach it; users opt in with IMM_UX_LANGUAGE (for example
|
|
6
|
+
* `zh`). Anything unrecognized keeps English, the published default.
|
|
7
|
+
*
|
|
8
|
+
* Boundary: only sentence-level interaction text follows this setting.
|
|
9
|
+
* Machine contracts and domain terms (state enums, operation ids, Task /
|
|
10
|
+
* Intent / Claim / Acceptance field labels, hashes, paths, CLI commands)
|
|
11
|
+
* always stay literal, as do agent-facing Tool result reasons and
|
|
12
|
+
* diagnostic notifications.
|
|
13
|
+
*/
|
|
14
|
+
export type UxLanguage = "en" | "zh";
|
|
15
|
+
|
|
16
|
+
export function resolveUxLanguage(
|
|
17
|
+
env: Readonly<Record<string, string | undefined>> = process.env,
|
|
18
|
+
): UxLanguage {
|
|
19
|
+
const raw = env.IMM_UX_LANGUAGE?.trim().toLowerCase();
|
|
20
|
+
if (raw === "zh" || raw === "zh-cn" || raw === "zh-tw" || raw === "chinese" || raw === "中文")
|
|
21
|
+
return "zh";
|
|
22
|
+
return "en";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Pick the interaction sentence for the resolved language. */
|
|
26
|
+
export function uxText(lang: UxLanguage, en: string, zh: string): string {
|
|
27
|
+
return lang === "zh" ? zh : en;
|
|
28
|
+
}
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
from `dist/`; nested modes, examples, recovery, and references load on demand.
|
|
7
7
|
- Ask only when missing information would change the goal, scope, observable behavior, compatibility, risk acceptance, a protected effect, or a fact only the user can supply. Resolve repository facts and delegated technical choices with bounded evidence instead of asking.
|
|
8
8
|
- Keep edits inside the user-requested Direct scope or the enrolled TaskIntent acceptance and `scope_hint`.
|
|
9
|
-
- Stage only explicit task-owned paths.
|
|
9
|
+
- Stage only explicit task-owned paths. This staging authority does not grant
|
|
10
|
+
commit, push, broad staging, or authority over pre-existing user changes.
|
|
11
|
+
Never use `git add .` or `git add -A` in a dirty worktree.
|
|
10
12
|
- Do not create, switch, or delete Git worktrees; operate only in the Host launch directory.
|
|
11
13
|
- Record reproducible evidence before reporting closure.
|
|
12
14
|
- Required verification must pass before reporting completion; disclosing a gap is not a substitute. Autonomously diagnose, repair, and rerun failing conventional local checks within the authorized scope; never delete, skip, or weaken a valid check to manufacture a pass. If a required check remains failing or cannot run, report the work as incomplete with the concrete blocker.
|
|
@@ -46,7 +48,9 @@ routing. A new Managed workflow starts only from explicit `imm-brainstorm`,
|
|
|
46
48
|
Managed owner remains authoritative; the user resumes it with `imm-loop`.
|
|
47
49
|
2. **Start explicitly**: the selected Immune-Brain Skill owns its planning or
|
|
48
50
|
coordination work. It creates only requested artifacts and their required
|
|
49
|
-
parent directories
|
|
51
|
+
parent directories. Explicit Planner entry also owns absent routing-policy
|
|
52
|
+
activation under Planner's Kernel TaskIntent Routing section;
|
|
53
|
+
it does not otherwise install project-wide contract files.
|
|
50
54
|
3. **Preserve authority**: Planner output is a candidate for later literal-user
|
|
51
55
|
Enrollment, and Fast-Track preserves TaskIntent scope, Enrollment, QA,
|
|
52
56
|
Review, authorization, and completion boundaries.
|
|
@@ -124,6 +128,17 @@ always run sequentially.
|
|
|
124
128
|
- Do not translate or rename machine contracts: schema fields, enum values,
|
|
125
129
|
CLI flags, JSON keys, file paths, tool names, API names,
|
|
126
130
|
and code identifiers stay literal.
|
|
131
|
+
- Host-native UI text (Task Rail sentences, authority dialog titles and
|
|
132
|
+
actions, enrollment progress summaries) is deterministic extension code and
|
|
133
|
+
cannot follow conversational rules; users localize it with the
|
|
134
|
+
`IMM_UX_LANGUAGE` environment variable (for example `IMM_UX_LANGUAGE=zh`).
|
|
135
|
+
Only sentence-level interaction text follows it; machine contracts, domain
|
|
136
|
+
field labels, and agent-facing Tool result reasons stay literal English.
|
|
137
|
+
- Internal role dispatches (`dispatch_role` and routed role contexts) carry
|
|
138
|
+
the user-facing interaction language as `interaction_language` in the
|
|
139
|
+
delegation context, so QA/Review/Explorer roles report in the user's
|
|
140
|
+
language while keeping machine contracts literal. Omit it to keep English
|
|
141
|
+
role output.
|
|
127
142
|
- Preserve `CONTEXT.md` canonical terms such as `Step`, `Plan`, `Spec`,
|
|
128
143
|
`Skill`, `Brainstorm`, `Executor`, `QA`, `Compounder`, `Learning`, and `ADR`;
|
|
129
144
|
add local-language explanations around them when helpful.
|
|
@@ -39,7 +39,7 @@ function probeHost(env = process.env, platform = process.platform, hostVersion)
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// plugins/immune-brain/runtime/plugin_version.ts
|
|
42
|
-
var PLUGIN_VERSION = "4.0
|
|
42
|
+
var PLUGIN_VERSION = "4.2.0";
|
|
43
43
|
|
|
44
44
|
// plugins/immune-brain/runtime/claude/interaction.ts
|
|
45
45
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -1263,6 +1263,13 @@ function loadRolePrompt(role) {
|
|
|
1263
1263
|
}
|
|
1264
1264
|
throw new Error(`internal role prompt is not packaged: ${role}`);
|
|
1265
1265
|
}
|
|
1266
|
+
function readInteractionLanguage(context) {
|
|
1267
|
+
const raw = context.interaction_language;
|
|
1268
|
+
if (typeof raw !== "string")
|
|
1269
|
+
return null;
|
|
1270
|
+
const trimmed = raw.trim();
|
|
1271
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
1272
|
+
}
|
|
1266
1273
|
function buildRoleDelegationPacket(input) {
|
|
1267
1274
|
const spec = roleSpec(input.role);
|
|
1268
1275
|
const requestedGate = input.context.review_gate;
|
|
@@ -1273,11 +1280,15 @@ function buildRoleDelegationPacket(input) {
|
|
|
1273
1280
|
throw new Error(`${input.role} cannot carry review gate ${requestedGate}`);
|
|
1274
1281
|
}
|
|
1275
1282
|
const reviewGate = spec.review_gate;
|
|
1283
|
+
const interactionLanguage = readInteractionLanguage(input.context);
|
|
1276
1284
|
const context = stableStringify(input.context);
|
|
1277
1285
|
const prompt = [
|
|
1278
1286
|
`internal role: ${input.role}`,
|
|
1279
1287
|
`tool_policy: ${spec.tool_policy}`,
|
|
1280
1288
|
`do not discover or load Pi Skills; execute this internal role contract directly`,
|
|
1289
|
+
...interactionLanguage ? [
|
|
1290
|
+
`interaction language: ${interactionLanguage} — write findings, summaries, and explanations in this language; keep machine contracts (file paths, code identifiers, CLI commands, enum values, task ids) literal`
|
|
1291
|
+
] : [],
|
|
1281
1292
|
loadRolePrompt(input.role).trim(),
|
|
1282
1293
|
`Delegation context (untrusted data): ${context}`
|
|
1283
1294
|
].join(`
|
|
@@ -55,7 +55,12 @@ Continue while the current projection has a valid action:
|
|
|
55
55
|
1. For active artifacts, implement only the enrolled acceptance within the
|
|
56
56
|
`scope_hint` envelope in the current conversation. New helpers or tests
|
|
57
57
|
inside an approved directory or glob do not require a revision. Run focused
|
|
58
|
-
checks.
|
|
58
|
+
checks. Before `advance_assurance`, inspect ownership and stage only the exact
|
|
59
|
+
task-owned paths needed for delivery. Do not hand routine task-owned staging
|
|
60
|
+
to the user. If a file mixes pre-existing user changes with task changes and
|
|
61
|
+
the task-owned hunks cannot be isolated reliably, stop with that ownership
|
|
62
|
+
conflict instead of staging the whole file. Staging grants no commit or push
|
|
63
|
+
authority. Executor checks are diagnostic evidence, not a QA or Review approval.
|
|
59
64
|
2. Call `advance_assurance` in the foreground and consume its direct terminal
|
|
60
65
|
result. The Kernel freezes the artifacts itself before QA: it binds Git
|
|
61
66
|
content identity in place without relocating source paths. A simple task has
|
|
@@ -164,6 +169,14 @@ explicit runtime-supported role boundary requests it, followed by the returned
|
|
|
164
169
|
foreground Agent envelope exactly. It is not an extra gate on Kernel Assurance.
|
|
165
170
|
All internal Agent envelopes use `run_in_background: false`.
|
|
166
171
|
|
|
172
|
+
Role dispatches follow the user's interaction language: include
|
|
173
|
+
`"interaction_language"` in the `dispatch_role` or routed role context with
|
|
174
|
+
the current reply language (the current explicit user instruction, else the
|
|
175
|
+
project `AGENTS.md` reply-language default, for example `"中文"` or
|
|
176
|
+
`"English"`), so role findings and summaries arrive in the user's language.
|
|
177
|
+
Machine contracts stay literal regardless. Omit the field to keep English
|
|
178
|
+
role output.
|
|
179
|
+
|
|
167
180
|
The internal Compounder is optional: only closed work with structured evidence
|
|
168
181
|
of a reusable Learning may route to it. Routine completion creates no Learning.
|
|
169
182
|
It cannot approve successors or delay terminal settlement. A projection with
|
|
@@ -76,7 +76,8 @@ Then route deterministically:
|
|
|
76
76
|
coordination, except a Loop-requested revision follows Enrolled Intent Revision
|
|
77
77
|
below to prepare a non-authoritative proposal for that same owner;
|
|
78
78
|
- an active or otherwise nonterminal v3 Plan remains on its existing v3 route;
|
|
79
|
-
- no routing policy
|
|
79
|
+
- no routing policy on an otherwise unowned workspace triggers automatic policy
|
|
80
|
+
activation below before producing any planning artifact;
|
|
80
81
|
- a valid `kernel_task_intent` retirement policy produces one TaskIntent draft
|
|
81
82
|
through the current Host's explicit `imm-planner`;
|
|
82
83
|
- an invalid, unreadable, untracked, or tracked-deleted policy rejects new
|
|
@@ -107,6 +108,46 @@ workspace claim, and final authority preconditions without executing acceptance
|
|
|
107
108
|
descriptors. A routine task proceeds from that single confirmation through
|
|
108
109
|
enrollment, execution and QA without a second human stop.
|
|
109
110
|
|
|
111
|
+
**Automatic policy activation**
|
|
112
|
+
|
|
113
|
+
Explicit `imm-planner` entry includes local routing setup, including for plan-only
|
|
114
|
+
requests. When the routing projection reports `policy_status: legacy_v3` and
|
|
115
|
+
`ownership: absent`, and neither Kernel nor nonterminal v3 ownership exists,
|
|
116
|
+
perform these steps without a separate enablement question:
|
|
117
|
+
|
|
118
|
+
1. Create `docs/plans/` if needed. Require real directories without symlink
|
|
119
|
+
components; create `docs/plans/managed-task-routing-policy.json` exclusively
|
|
120
|
+
(fail if it already exists), using exactly the JSON below with two-space
|
|
121
|
+
indentation, the shown field order, and one trailing newline.
|
|
122
|
+
2. Run `git add -- docs/plans/managed-task-routing-policy.json` only for the file
|
|
123
|
+
created in this activation. Preserve all other worktree and index changes;
|
|
124
|
+
do not commit, force-add an ignored file, or alter Git configuration.
|
|
125
|
+
3. Re-run `imm-plan --routing-status --json` through the resolved wrapper.
|
|
126
|
+
Continue canonical TaskIntent authoring only when `policy_status: active`,
|
|
127
|
+
`route: kernel_task_intent`, and `ownership: tracked_clean` all hold. Report
|
|
128
|
+
automatic activation briefly and continue planning in the same turn.
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"contract": "immune_brain/managed_task_routing_policy/v1",
|
|
133
|
+
"revision": 1,
|
|
134
|
+
"new_task_route": "kernel_task_intent",
|
|
135
|
+
"v3_new_plan_sync": "retired",
|
|
136
|
+
"legacy_v3_mode": "drain_read_only",
|
|
137
|
+
"terminal_import": "disabled"
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
An already active policy needs no write or staging. An existing invalid,
|
|
142
|
+
untracked, unreadable, tracked-deleted, or divergent policy is not an activation
|
|
143
|
+
candidate: preserve it and report `routing_policy_invalid`. If creation,
|
|
144
|
+
staging, or verification fails, report the concrete blocker and retain any
|
|
145
|
+
created file; stop before authoring, without overwriting existing bytes or
|
|
146
|
+
falling back to v3. A repository/user prohibition on policy setup or staging
|
|
147
|
+
blocks only this dependent planning step. Activation grants no execution
|
|
148
|
+
authority; the native Enrollment gate remains required. Read-only routing
|
|
149
|
+
queries and the canonical author command retain their existing runtime behavior.
|
|
150
|
+
|
|
110
151
|
## Candidate Authoring
|
|
111
152
|
|
|
112
153
|
Read this section before creating new candidate artifacts, after request routing
|
|
@@ -133,6 +174,12 @@ file creation; then it validates the created artifact with
|
|
|
133
174
|
continue through Kernel `revise_intent` authority and are not a Planner
|
|
134
175
|
overwrite path.
|
|
135
176
|
|
|
177
|
+
After authoring, inspect ownership and stage only the exact Planner-produced
|
|
178
|
+
Spec and TaskIntent paths before validation and handoff. Do not hand routine
|
|
179
|
+
Planner-owned staging to the user. This grants no commit, push, broad staging,
|
|
180
|
+
or authority over pre-existing user changes; a mixed-change ownership conflict
|
|
181
|
+
stops only the affected handoff.
|
|
182
|
+
|
|
136
183
|
Before authoring a TaskIntent that adds a field or verdict branch to a state
|
|
137
184
|
machine, enumerate every consumer of that value and of the version gates around
|
|
138
185
|
it: the producing side, each branch or switch that reads it, and any migration or
|
|
@@ -263,7 +310,12 @@ script or host tool through its literal `command`; do not infer a language,
|
|
|
263
310
|
package manager, or runner. Add `environment.prepare` only when the check needs
|
|
264
311
|
explicit setup, and declare only the generated directories it needs in
|
|
265
312
|
`environment.writable_paths`. Never hide package installation inside an
|
|
266
|
-
acceptance command.
|
|
313
|
+
acceptance command. For every descriptor, identify whether its executable is
|
|
314
|
+
provided by the QA host or by tracked delivery content, where every dependency
|
|
315
|
+
comes from in the disposable delivery, what explicit setup is required, and
|
|
316
|
+
which declared writable paths that setup or check creates. A dependency found
|
|
317
|
+
only in the Planner's live worktree, including an absolute local `node_modules`
|
|
318
|
+
path, is not delivery provenance. Prefer the highest existing observable behavioral test seam
|
|
267
319
|
and the fewest sufficient seams; never use the full test suite, a build, network
|
|
268
320
|
access, or redundant heavyweight checks as acceptance. Cite relevant test prior
|
|
269
321
|
art and explain how the selected seam catches the intended regression. This is
|
|
@@ -271,7 +323,9 @@ a planning heuristic: it must not weaken acceptance-specific focused
|
|
|
271
323
|
verification descriptors or add a mandatory user confirmation. Use the smallest
|
|
272
324
|
`timeout_ms` and `max_output_bytes` that cover deterministic post-implementation
|
|
273
325
|
QA. A v1 descriptor is historical-only and requires explicit Intent revision
|
|
274
|
-
before execution.
|
|
326
|
+
before execution. Report `valid` and `enrollment_ready` only as structural and
|
|
327
|
+
Enrollment readiness; only a completed deterministic QA result proves that a
|
|
328
|
+
descriptor executed and passed.
|
|
275
329
|
|
|
276
330
|
## Core Responsibilities
|
|
277
331
|
|
|
@@ -410,7 +464,7 @@ optional advisory dispatch fails, continue inline and record the reason.
|
|
|
410
464
|
|
|
411
465
|
## Boundary
|
|
412
466
|
|
|
413
|
-
- **Allowed**: Write a TaskIntent. Add a Spec only for complex work. Initiative planning carriers and necessary domain vocabulary.
|
|
467
|
+
- **Allowed**: Write a TaskIntent. Add a Spec only for complex work. Activate an absent routing policy under Kernel TaskIntent Routing. Initiative planning carriers and necessary domain vocabulary.
|
|
414
468
|
- **Blocked**: Implementation edits, direct Kernel-store writes, enrolled intent overwrites, and QA/Review decisions.
|
|
415
469
|
- **Workflow guard**: Execution continues through native Enrollment and explicit `imm-loop`. Planner owns design and decomposition, not execution authority.
|
|
416
470
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by scripts/plugin_versioning.ts from the root package.json.
|
|
2
|
-
export const PLUGIN_VERSION = "4.0
|
|
2
|
+
export const PLUGIN_VERSION = "4.2.0" as const;
|
|
@@ -89,6 +89,14 @@ export interface RoleDelegationContext {
|
|
|
89
89
|
target_id?: string;
|
|
90
90
|
review_gate?: StableReviewGate;
|
|
91
91
|
changed_files_signature?: string;
|
|
92
|
+
/**
|
|
93
|
+
* Optional user-facing interaction language (for example "中文" or
|
|
94
|
+
* "English"). The Parent sets it from the current explicit user
|
|
95
|
+
* instruction or the project reply-language default; when present the
|
|
96
|
+
* delegation prompt asks the role to report in that language while
|
|
97
|
+
* keeping machine contracts literal. Omitted keeps English role output.
|
|
98
|
+
*/
|
|
99
|
+
interaction_language?: string;
|
|
92
100
|
[key: string]: unknown;
|
|
93
101
|
}
|
|
94
102
|
|
|
@@ -137,6 +145,13 @@ export function loadRolePrompt(role: InternalRole): string {
|
|
|
137
145
|
throw new Error(`internal role prompt is not packaged: ${role}`);
|
|
138
146
|
}
|
|
139
147
|
|
|
148
|
+
function readInteractionLanguage(context: RoleDelegationContext): string | null {
|
|
149
|
+
const raw = context.interaction_language;
|
|
150
|
+
if (typeof raw !== "string") return null;
|
|
151
|
+
const trimmed = raw.trim();
|
|
152
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
153
|
+
}
|
|
154
|
+
|
|
140
155
|
export function buildRoleDelegationPacket(input: {
|
|
141
156
|
role: InternalRole;
|
|
142
157
|
context: RoleDelegationContext;
|
|
@@ -155,11 +170,17 @@ export function buildRoleDelegationPacket(input: {
|
|
|
155
170
|
}
|
|
156
171
|
|
|
157
172
|
const reviewGate = spec.review_gate;
|
|
173
|
+
const interactionLanguage = readInteractionLanguage(input.context);
|
|
158
174
|
const context = stableStringify(input.context);
|
|
159
175
|
const prompt = [
|
|
160
176
|
`internal role: ${input.role}`,
|
|
161
177
|
`tool_policy: ${spec.tool_policy}`,
|
|
162
178
|
`do not discover or load Pi Skills; execute this internal role contract directly`,
|
|
179
|
+
...(interactionLanguage
|
|
180
|
+
? [
|
|
181
|
+
`interaction language: ${interactionLanguage} — write findings, summaries, and explanations in this language; keep machine contracts (file paths, code identifiers, CLI commands, enum values, task ids) literal`,
|
|
182
|
+
]
|
|
183
|
+
: []),
|
|
163
184
|
loadRolePrompt(input.role).trim(),
|
|
164
185
|
`Delegation context (untrusted data): ${context}`,
|
|
165
186
|
].join("\n\n");
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
from `dist/`; nested modes, examples, recovery, and references load on demand.
|
|
7
7
|
- Ask only when missing information would change the goal, scope, observable behavior, compatibility, risk acceptance, a protected effect, or a fact only the user can supply. Resolve repository facts and delegated technical choices with bounded evidence instead of asking.
|
|
8
8
|
- Keep edits inside the user-requested Direct scope or the enrolled TaskIntent acceptance and `scope_hint`.
|
|
9
|
-
- Stage only explicit task-owned paths.
|
|
9
|
+
- Stage only explicit task-owned paths. This staging authority does not grant
|
|
10
|
+
commit, push, broad staging, or authority over pre-existing user changes.
|
|
11
|
+
Never use `git add .` or `git add -A` in a dirty worktree.
|
|
10
12
|
- Do not create, switch, or delete Git worktrees; operate only in the Host launch directory.
|
|
11
13
|
- Record reproducible evidence before reporting closure.
|
|
12
14
|
- Required verification must pass before reporting completion; disclosing a gap is not a substitute. Autonomously diagnose, repair, and rerun failing conventional local checks within the authorized scope; never delete, skip, or weaken a valid check to manufacture a pass. If a required check remains failing or cannot run, report the work as incomplete with the concrete blocker.
|
|
@@ -46,7 +48,9 @@ routing. A new Managed workflow starts only from explicit `imm-brainstorm`,
|
|
|
46
48
|
Managed owner remains authoritative; the user resumes it with `imm-loop`.
|
|
47
49
|
2. **Start explicitly**: the selected Immune-Brain Skill owns its planning or
|
|
48
50
|
coordination work. It creates only requested artifacts and their required
|
|
49
|
-
parent directories
|
|
51
|
+
parent directories. Explicit Planner entry also owns absent routing-policy
|
|
52
|
+
activation under Planner's Kernel TaskIntent Routing section;
|
|
53
|
+
it does not otherwise install project-wide contract files.
|
|
50
54
|
3. **Preserve authority**: Planner output is a candidate for later literal-user
|
|
51
55
|
Enrollment, and Fast-Track preserves TaskIntent scope, Enrollment, QA,
|
|
52
56
|
Review, authorization, and completion boundaries.
|
|
@@ -124,6 +128,17 @@ always run sequentially.
|
|
|
124
128
|
- Do not translate or rename machine contracts: schema fields, enum values,
|
|
125
129
|
CLI flags, JSON keys, file paths, tool names, API names,
|
|
126
130
|
and code identifiers stay literal.
|
|
131
|
+
- Host-native UI text (Task Rail sentences, authority dialog titles and
|
|
132
|
+
actions, enrollment progress summaries) is deterministic extension code and
|
|
133
|
+
cannot follow conversational rules; users localize it with the
|
|
134
|
+
`IMM_UX_LANGUAGE` environment variable (for example `IMM_UX_LANGUAGE=zh`).
|
|
135
|
+
Only sentence-level interaction text follows it; machine contracts, domain
|
|
136
|
+
field labels, and agent-facing Tool result reasons stay literal English.
|
|
137
|
+
- Internal role dispatches (`dispatch_role` and routed role contexts) carry
|
|
138
|
+
the user-facing interaction language as `interaction_language` in the
|
|
139
|
+
delegation context, so QA/Review/Explorer roles report in the user's
|
|
140
|
+
language while keeping machine contracts literal. Omit it to keep English
|
|
141
|
+
role output.
|
|
127
142
|
- Preserve `CONTEXT.md` canonical terms such as `Step`, `Plan`, `Spec`,
|
|
128
143
|
`Skill`, `Brainstorm`, `Executor`, `QA`, `Compounder`, `Learning`, and `ADR`;
|
|
129
144
|
add local-language explanations around them when helpful.
|