immune-brain 3.2.2 → 3.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 +2 -2
- package/README.zh-CN.md +3 -3
- package/package.json +5 -3
- package/plugins/immune-brain/.claude-plugin/plugin.json +1 -1
- package/plugins/immune-brain/.pi-extension/imm-canary-work.ts +19 -73
- package/plugins/immune-brain/.pi-extension/pi-canary-interaction.ts +1 -2
- package/plugins/immune-brain/.pi-extension/runtime-stub.ts +2 -2
- package/plugins/immune-brain/dist/BASELINE.md +1 -1
- package/plugins/immune-brain/dist/claude/mcp-server.mjs +317 -316
- package/plugins/immune-brain/dist/docs/reference/subagent-dispatch-protocol.md +1 -1
- package/plugins/immune-brain/dist/imm-brainstorm.md +1 -1
- package/plugins/immune-brain/dist/imm-loop.md +15 -10
- package/plugins/immune-brain/dist/imm-planner.md +22 -17
- package/plugins/immune-brain/hooks/hooks.json +0 -10
- package/plugins/immune-brain/runtime/assurance/coordinator.ts +0 -8
- package/plugins/immune-brain/runtime/claude/capability.ts +4 -10
- package/plugins/immune-brain/runtime/claude/interaction.ts +55 -22
- package/plugins/immune-brain/runtime/claude/kernel_ports.ts +63 -73
- package/plugins/immune-brain/runtime/claude/mcp_server.ts +233 -55
- package/plugins/immune-brain/runtime/claude/review_host.ts +2 -138
- package/plugins/immune-brain/runtime/kernel/application.ts +0 -1
- package/plugins/immune-brain/runtime/kernel/assurance_projection.ts +1 -7
- package/plugins/immune-brain/runtime/kernel/canary_application.ts +0 -7
- package/plugins/immune-brain/runtime/kernel/completion.ts +1 -3
- package/plugins/immune-brain/runtime/kernel/reducer.ts +0 -31
- package/plugins/immune-brain/runtime/kernel/types.ts +0 -2
- package/plugins/immune-brain/runtime/kernel/validation.ts +1 -3
- package/plugins/immune-brain/runtime/plugin_version.ts +2 -0
- package/plugins/immune-brain/skills/BASELINE.md +1 -1
- package/plugins/immune-brain/skills/imm-brainstorm/SKILL.md +4 -0
- package/plugins/immune-brain/skills/imm-loop/SKILL.md +4 -0
- package/plugins/immune-brain/skills/imm-planner/SKILL.md +6 -0
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Immune-Brain adds a structured engineering workflow on top of Pi:
|
|
|
14
14
|
- **Plans become trackable tasks** (`TaskIntent` + `TaskRecord`) so progress survives across sessions, not just chat history.
|
|
15
15
|
- **Quality is enforced by code, not promises** — automated QA and isolated review must pass before a task is marked done.
|
|
16
16
|
|
|
17
|
-
Pi and Claude Code are the supported hosts. Undeclared adapters remain unsupported. Minimum Claude Code is `2.1.
|
|
17
|
+
Pi and Claude Code are the supported hosts. Undeclared adapters remain unsupported. Minimum Claude Code is `2.1.236`, the lowest version verified with interactive server-initiated MCP elicitation. Current real-Host evidence is recorded in [Claude native elicitation conformance](docs/verification/claude-native-elicitation-authority-conformance.md); historical reports remain under [docs/verification/archive/](docs/verification/archive/). Either host can use the model provider you configure — Immune-Brain works on top of Kernel authority, not a vendor chat.
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
@@ -191,7 +191,7 @@ docs/specs/ # Living specs (updated in place)
|
|
|
191
191
|
|
|
192
192
|
**QA failed — what now?** QA returns `rework` or `replan_required`. `imm-loop` routes back to the executor or to `imm-planner` for scope changes. No manual reset needed.
|
|
193
193
|
|
|
194
|
-
**Can I use it outside Pi?** Yes. Local interactive Claude Code is supported from version `2.1.
|
|
194
|
+
**Can I use it outside Pi?** Yes. Local interactive Claude Code is supported from version `2.1.236`; its plugin uses a digest-bound native MCP elicitation gate for the same Kernel-backed workflow.
|
|
195
195
|
|
|
196
196
|
---
|
|
197
197
|
|
package/README.zh-CN.md
CHANGED
|
@@ -14,7 +14,7 @@ Immune-Brain 在 Pi 之上提供结构化的工程工作流:
|
|
|
14
14
|
- **计划变为可追踪的任务**(`TaskIntent` + `TaskRecord`),进度落盘持久化,不依赖对话历史。
|
|
15
15
|
- **质量由代码强制保障** — 自动化 QA 与隔离式 Review 必须通过,任务才会完成。
|
|
16
16
|
|
|
17
|
-
Pi 与 Claude Code 是支持的宿主。未声明的适配器仍不受支持。Claude Code 最低版本为 `2.1.
|
|
17
|
+
Pi 与 Claude Code 是支持的宿主。未声明的适配器仍不受支持。Claude Code 最低版本为 `2.1.236`,这是已通过交互式 server-initiated MCP elicitation 验证的最低版本。当前真实 Host 证据见 `docs/verification/claude-native-elicitation-authority-conformance.md`;历史报告归档于 `docs/verification/archive/`。
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
@@ -64,7 +64,7 @@ mise run check-dist-sync # 校验生成文档同步
|
|
|
64
64
|
|
|
65
65
|
Pi 会自动路由:需求模糊走澄清,目标明确走规划。
|
|
66
66
|
|
|
67
|
-
**2. 确认计划** — Planner 会在 `docs/plans/` 生成 `TaskIntent
|
|
67
|
+
**2. 确认计划** — Planner 会在 `docs/plans/` 生成 `TaskIntent`(范围、风险等级、验收条件)。检查无误后由当前 Host 的原生 gate 确认 Enrollment(所有风险等级都需要确认,确认前零 authority 写入)。
|
|
68
68
|
|
|
69
69
|
**3. 开始执行** — `imm-loop` 按计划执行、跑 QA、触发 Review。按提示暂存任务拥有的文件:
|
|
70
70
|
|
|
@@ -191,7 +191,7 @@ docs/specs/ # Living specs(原地更新)
|
|
|
191
191
|
|
|
192
192
|
**QA 失败怎么办?** QA 返回 `rework` 或 `replan_required`,`imm-loop` 会自动路由回 Executor 或 `imm-planner` 调整范围,无需手动重置。
|
|
193
193
|
|
|
194
|
-
**可以在 Pi 之外使用吗?**
|
|
194
|
+
**可以在 Pi 之外使用吗?** 可以从 `2.1.236` 起在本地交互式 Claude Code 中使用同一套 Kernel;Claude plugin 通过绑定 digest 的原生 MCP elicitation gate 获取 authority,未声明的适配器不受支持。
|
|
195
195
|
|
|
196
196
|
---
|
|
197
197
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "immune-brain",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Immune-Brain agent skill system",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -29,8 +29,9 @@
|
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
31
|
"changeset": "changeset",
|
|
32
|
-
"changeset:version": "changeset version && bun scripts/
|
|
33
|
-
"
|
|
32
|
+
"changeset:version": "changeset version && bun scripts/build-claude-plugin.ts && bun scripts/plugin_versioning.ts validate",
|
|
33
|
+
"verify:release": "bun scripts/plugin_versioning.ts validate && bun scripts/build-claude-plugin.ts --check && bun scripts/sync-dist-docs.ts --check && bun test && npm pack --dry-run --ignore-scripts",
|
|
34
|
+
"changeset:publish": "bun run verify:release && changeset publish",
|
|
34
35
|
"release": "bun run changeset:publish"
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|
|
@@ -76,6 +77,7 @@
|
|
|
76
77
|
"plugins/immune-brain/runtime/verification_descriptor.ts",
|
|
77
78
|
"plugins/immune-brain/runtime/role_prompt_bridge.ts",
|
|
78
79
|
"plugins/immune-brain/runtime/loop_contract.ts",
|
|
80
|
+
"plugins/immune-brain/runtime/plugin_version.ts",
|
|
79
81
|
"plugins/immune-brain/runtime/assurance",
|
|
80
82
|
"plugins/immune-brain/runtime/claude",
|
|
81
83
|
"plugins/immune-brain/runtime/prompts",
|
|
@@ -20,6 +20,7 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
20
20
|
import { join, resolve } from "node:path";
|
|
21
21
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
22
22
|
import { Type } from "typebox";
|
|
23
|
+
import { PLUGIN_VERSION } from "../runtime/plugin_version";
|
|
23
24
|
import {
|
|
24
25
|
parseVerificationDescriptor,
|
|
25
26
|
canonicalDescriptorBytes,
|
|
@@ -171,7 +172,6 @@ const TASK_INTENT_SCHEMA = Type.Object({
|
|
|
171
172
|
|
|
172
173
|
export type { AssuranceRole } from "./pi-canary-assurance";
|
|
173
174
|
export type AuthorizeOperation =
|
|
174
|
-
| "record-user-approval"
|
|
175
175
|
| "approve-breaking-intent-revision"
|
|
176
176
|
| "resolve-user-decision"
|
|
177
177
|
| "stop";
|
|
@@ -391,7 +391,7 @@ export default function (
|
|
|
391
391
|
"After implementation and focused verification, freeze the artifacts, call advance_assurance, and consume its direct terminal result; do not poll or create a detached job.",
|
|
392
392
|
"When advance_assurance returns review_ready, invoke the foreground Agent from agent_params once, then pass its structured verdict to submit_review.",
|
|
393
393
|
"For a complete breaking revision, call approve_breaking_intent_revision with the complete next_intent directly; do not ask for chat pre-confirmation because the host opens the single native confirmation before applying it.",
|
|
394
|
-
"For a proven stale authority claim, call repair_authority_state directly;
|
|
394
|
+
"For a proven stale authority claim, call repair_authority_state directly; the Kernel revalidates and removes only the redundant claim without user interaction.",
|
|
395
395
|
"After awaiting_user, call request_authorization directly so the host opens the single native confirmation; do not ask for chat pre-confirmation or ask the user to copy or report a command.",
|
|
396
396
|
],
|
|
397
397
|
parameters: Type.Object({
|
|
@@ -474,43 +474,6 @@ export default function (
|
|
|
474
474
|
presentTaskRailResult(ctx, taskId, blocked);
|
|
475
475
|
return failCanaryTool(taskId, action.op, "authority_conflict", "authority_conflict", blocked.result, blocked.next_action);
|
|
476
476
|
}
|
|
477
|
-
presentTaskRail(ctx, {
|
|
478
|
-
task_id: taskId,
|
|
479
|
-
state: "Approval required",
|
|
480
|
-
result: "Authority repair needs your approval",
|
|
481
|
-
next: "Decide whether to repair the stale claim",
|
|
482
|
-
});
|
|
483
|
-
const repairSelection = await requestAuthorityDialog(pi, ctx, {
|
|
484
|
-
attention_id: randomUUID(),
|
|
485
|
-
task_id: taskId,
|
|
486
|
-
reason: "authority_repair",
|
|
487
|
-
label: "Kernel authority repair required",
|
|
488
|
-
}, {
|
|
489
|
-
title: "Repair Kernel authority state?",
|
|
490
|
-
summary: [
|
|
491
|
-
`Owner: ${taskId}`,
|
|
492
|
-
`Terminal lifecycle: ${authority.owner_lifecycle}`,
|
|
493
|
-
`Claim lifecycle: ${authority.claim_lifecycle_status}`,
|
|
494
|
-
].join("\n"),
|
|
495
|
-
details: [
|
|
496
|
-
`Projection revision: ${authority.revision}`,
|
|
497
|
-
"Action: remove only the stale global claim; preserve TaskRecord and tombstone.",
|
|
498
|
-
].join("\n"),
|
|
499
|
-
signal: ctx.signal ?? signal,
|
|
500
|
-
actions: [
|
|
501
|
-
{ value: "repair", label: "Repair stale claim", description: "Remove only the stale global claim" },
|
|
502
|
-
{ value: "cancel", label: "Cancel", description: "Preserve all authority state unchanged" },
|
|
503
|
-
],
|
|
504
|
-
});
|
|
505
|
-
if (repairSelection !== "repair") {
|
|
506
|
-
const cancelled = {
|
|
507
|
-
state: "cancelled",
|
|
508
|
-
operation: action.op,
|
|
509
|
-
result: "Authority repair cancelled with zero writes",
|
|
510
|
-
next_action: "request authorization again if repair is still intended",
|
|
511
|
-
};
|
|
512
|
-
return toolResult(JSON.stringify(cancelled, null, 2), cancelled);
|
|
513
|
-
}
|
|
514
477
|
try {
|
|
515
478
|
const repaired = await repairKernelAuthority(ctx.cwd, taskId, authority.revision);
|
|
516
479
|
const result = {
|
|
@@ -574,9 +537,11 @@ export default function (
|
|
|
574
537
|
const blockers = state.blocking_finding_ids.length
|
|
575
538
|
+ state.unresolved_user_decision_ids.length
|
|
576
539
|
+ state.replan_required_ids.length;
|
|
540
|
+
const status = { plugin_version: PLUGIN_VERSION, ...state };
|
|
577
541
|
const details = {
|
|
578
542
|
state: "status",
|
|
579
543
|
operation: "status",
|
|
544
|
+
plugin_version: PLUGIN_VERSION,
|
|
580
545
|
lifecycle: state.lifecycle,
|
|
581
546
|
artifact_state: state.artifact_state,
|
|
582
547
|
task_state: state,
|
|
@@ -584,7 +549,7 @@ export default function (
|
|
|
584
549
|
next_action: state.next_obligation,
|
|
585
550
|
};
|
|
586
551
|
presentTaskRailResult(ctx, taskId, details);
|
|
587
|
-
return toolResult(JSON.stringify(
|
|
552
|
+
return toolResult(JSON.stringify(status, null, 2), details);
|
|
588
553
|
}
|
|
589
554
|
const claim = projection.claim;
|
|
590
555
|
if (!claim || claim.task_id !== taskId) {
|
|
@@ -823,6 +788,17 @@ export default function (
|
|
|
823
788
|
`Decision: ${operation}`,
|
|
824
789
|
`State: ${projection.projection.lifecycle}:${projection.projection.artifact_state} | Claim: ${projection.claim.lifecycle_status}`,
|
|
825
790
|
].join("\n");
|
|
791
|
+
const intentDelta = nextIntent
|
|
792
|
+
? [
|
|
793
|
+
`Risk: ${priorIntent.intent.risk} -> ${nextIntent.risk}`,
|
|
794
|
+
`Goal: ${priorIntent.intent.goal} -> ${nextIntent.goal}`,
|
|
795
|
+
`Scope added: ${nextIntent.scope_hint.filter((path) => !priorIntent.intent.scope_hint.includes(path)).join(", ") || "none"}`,
|
|
796
|
+
`Scope removed: ${priorIntent.intent.scope_hint.filter((path) => !nextIntent.scope_hint.includes(path)).join(", ") || "none"}`,
|
|
797
|
+
`Acceptance added: ${nextIntent.acceptance.filter((item) => !priorIntent.intent.acceptance.some((prior) => prior.id === item.id)).map((item) => item.id).join(", ") || "none"}`,
|
|
798
|
+
`Acceptance removed: ${priorIntent.intent.acceptance.filter((item) => !nextIntent.acceptance.some((next) => next.id === item.id)).map((item) => item.id).join(", ") || "none"}`,
|
|
799
|
+
`Acceptance changed: ${nextIntent.acceptance.filter((item) => { const prior = priorIntent.intent.acceptance.find((candidate) => candidate.id === item.id); return prior && (prior.assertion !== item.assertion || prior.verification !== item.verification); }).map((item) => item.id).join(", ") || "none"}`,
|
|
800
|
+
]
|
|
801
|
+
: [];
|
|
826
802
|
const dialogDetails = [
|
|
827
803
|
`Operation: ${operation}`,
|
|
828
804
|
...(userDecisionOperation
|
|
@@ -834,9 +810,8 @@ export default function (
|
|
|
834
810
|
...(nextIntent
|
|
835
811
|
? [
|
|
836
812
|
`Next Intent: rev ${nextIntent.revision} (${nextIntentHash})`,
|
|
837
|
-
|
|
838
|
-
`
|
|
839
|
-
`Next Acceptance Items: ${nextIntent.acceptance.length}`,
|
|
813
|
+
...intentDelta,
|
|
814
|
+
`Acceptance Items: ${priorIntent.intent.acceptance.length} -> ${nextIntent.acceptance.length}`,
|
|
840
815
|
`Next staged diff: ${stagedNextDiffHash}`,
|
|
841
816
|
]
|
|
842
817
|
: []),
|
|
@@ -922,23 +897,6 @@ export default function (
|
|
|
922
897
|
content_hash: nextIntentHash!,
|
|
923
898
|
};
|
|
924
899
|
}
|
|
925
|
-
// record-user-approval: literal-user approval for critical-task-completion. The approval payload is bound to the fresh
|
|
926
|
-
// projection (task revision, intent content hash, diff hash) and
|
|
927
|
-
// applied through the same exact-action capability path; the
|
|
928
|
-
// The reducer requires kind user, user authority, and active:frozen state.
|
|
929
|
-
const isUserApproval = operation === "record-user-approval";
|
|
930
|
-
const approval = isUserApproval
|
|
931
|
-
? {
|
|
932
|
-
id: `approval-user-${randomUUID().slice(0, 8)}`,
|
|
933
|
-
kind: "user" as const,
|
|
934
|
-
authority_role: "user" as const,
|
|
935
|
-
task_revision: projection.projection.intent_revision,
|
|
936
|
-
intent_content_hash: projection.projection.intent_content_hash,
|
|
937
|
-
diff_hash: projection.projection.diff_hash,
|
|
938
|
-
actor_id: "literal-user",
|
|
939
|
-
summary: "literal user approval",
|
|
940
|
-
}
|
|
941
|
-
: undefined;
|
|
942
900
|
const exactOperation = operation === "stop"
|
|
943
901
|
? { op: "stop" as const, reason: "literal user stopped task parked for replan" }
|
|
944
902
|
: operation === "approve-breaking-intent-revision"
|
|
@@ -947,7 +905,7 @@ export default function (
|
|
|
947
905
|
next_intent: nextIntent!,
|
|
948
906
|
next_intent_ref: nextIntentRef!,
|
|
949
907
|
}
|
|
950
|
-
: userDecisionOperation
|
|
908
|
+
: userDecisionOperation!;
|
|
951
909
|
// The exact host-built operation is shared by capability digest and
|
|
952
910
|
// application payload; command arguments cannot inject authority fields.
|
|
953
911
|
try {
|
|
@@ -971,7 +929,6 @@ export default function (
|
|
|
971
929
|
intent_content_hash: nextIntentHash ?? projection.projection.intent_content_hash,
|
|
972
930
|
diff_hash: operationDiffHash,
|
|
973
931
|
actor_id: "literal-user",
|
|
974
|
-
...(exactOperation.op === "record_user_approval" ? { approval: exactOperation.approval } : {}),
|
|
975
932
|
...(exactOperation.op === "approve_breaking_intent_revision"
|
|
976
933
|
? { next_intent: exactOperation.next_intent, next_intent_ref: exactOperation.next_intent_ref }
|
|
977
934
|
: {}),
|
|
@@ -1039,7 +996,6 @@ export default function (
|
|
|
1039
996
|
|
|
1040
997
|
export type DerivedAuthorizationOperation =
|
|
1041
998
|
| "resolve-user-decision"
|
|
1042
|
-
| "record-user-approval"
|
|
1043
999
|
| "stop";
|
|
1044
1000
|
|
|
1045
1001
|
// Kernel projection is the sole source of authorization readiness.
|
|
@@ -1049,7 +1005,6 @@ export function deriveAuthorizationOperation(input: {
|
|
|
1049
1005
|
}): { operation: DerivedAuthorizationOperation } | { blocked: string } {
|
|
1050
1006
|
if (input.hasOpenReplanRequired) return { operation: "stop" };
|
|
1051
1007
|
if (input.readiness.state === "resolve_user_decision") return { operation: "resolve-user-decision" };
|
|
1052
|
-
if (input.readiness.state === "record_user_approval") return { operation: "record-user-approval" };
|
|
1053
1008
|
if (input.readiness.blocked) return { blocked: input.readiness.blocked };
|
|
1054
1009
|
return { blocked: "no unique host-derived authorization operation" };
|
|
1055
1010
|
}
|
|
@@ -1126,15 +1081,6 @@ export function buildUserDecisionOperation(record: {
|
|
|
1126
1081
|
};
|
|
1127
1082
|
}
|
|
1128
1083
|
|
|
1129
|
-
export function userOperationFor(operation: AuthorizeOperation, approval?: unknown) {
|
|
1130
|
-
if (operation !== "record-user-approval")
|
|
1131
|
-
throw new Error(`unsupported authorize operation: ${operation}`);
|
|
1132
|
-
// The approval payload is constructed by the authorize handler from
|
|
1133
|
-
// the fresh projection; it is never derived from untrusted input.
|
|
1134
|
-
if (approval === undefined) throw new Error("record-user-approval requires an approval payload");
|
|
1135
|
-
return { op: "record_user_approval" as const, approval };
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
1084
|
/**
|
|
1139
1085
|
* One record-aware freshness identity. v4 derives the scoped revision digest
|
|
1140
1086
|
* from the immutable Enrollment base so committed and staged task work share a
|
|
@@ -179,7 +179,7 @@ export interface TaskRecordRead {
|
|
|
179
179
|
// --- Assurance projection (host-neutral Kernel facts, not exported from the
|
|
180
180
|
// public Kernel index) ---
|
|
181
181
|
export interface AssuranceAuthorizationReadiness {
|
|
182
|
-
state: "resolve_user_decision" | "
|
|
182
|
+
state: "resolve_user_decision" | "none";
|
|
183
183
|
blocked: string | null;
|
|
184
184
|
}
|
|
185
185
|
export interface AssuranceProjection {
|
|
@@ -191,7 +191,7 @@ export interface AssuranceProjection {
|
|
|
191
191
|
lifecycle: "active" | "done" | "stopped" | "";
|
|
192
192
|
artifact_state: "active" | "frozen" | "";
|
|
193
193
|
risk: "routine" | "material" | "critical" | "";
|
|
194
|
-
next_obligation: "resolve_findings" | "resolve_user_decision" | "revise_intent" | "submit_assurance" | "run_qa" | "run_review" | "
|
|
194
|
+
next_obligation: "resolve_findings" | "resolve_user_decision" | "revise_intent" | "submit_assurance" | "run_qa" | "run_review" | "complete" | "none";
|
|
195
195
|
fresh_acceptance_ids: string[];
|
|
196
196
|
missing_acceptance_ids: string[];
|
|
197
197
|
stale_attestation_ids: string[];
|
|
@@ -59,7 +59,7 @@ Require exact host confirmation only for privileged effects:
|
|
|
59
59
|
override; and
|
|
60
60
|
- external writes whose target or impact cannot be safely reversed locally.
|
|
61
61
|
|
|
62
|
-
Routine Managed enrollment uses one
|
|
62
|
+
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.
|
|
63
63
|
|
|
64
64
|
## Parallel Read-Only Dispatch
|
|
65
65
|
|