immune-brain 4.4.0 → 4.5.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/package.json +1 -1
- package/plugins/immune-brain/.claude-plugin/plugin.json +1 -1
- package/plugins/immune-brain/.pi-extension/imm-canary-work.ts +19 -2
- package/plugins/immune-brain/.pi-extension/imm-unattended-batch.ts +10 -2
- package/plugins/immune-brain/.pi-extension/pi-canary-tool-failure.ts +6 -1
- package/plugins/immune-brain/.pi-extension/runtime-stub.ts +11 -6
- package/plugins/immune-brain/dist/BASELINE.md +18 -1
- package/plugins/immune-brain/dist/claude/mcp-server.mjs +1039 -465
- package/plugins/immune-brain/dist/docs/reference/subagent-dispatch-protocol.md +30 -0
- package/plugins/immune-brain/dist/imm-brainstorm.md +21 -0
- package/plugins/immune-brain/dist/imm-loop.md +76 -4
- package/plugins/immune-brain/dist/imm-planner.md +65 -1
- package/plugins/immune-brain/dist/role-prompts/code-review.md +19 -0
- package/plugins/immune-brain/dist/role-prompts/executor.md +6 -0
- package/plugins/immune-brain/dist/role-prompts/qa.md +13 -1
- package/plugins/immune-brain/runtime/assurance/coordinator.ts +160 -12
- package/plugins/immune-brain/runtime/assurance/qa.ts +57 -42
- package/plugins/immune-brain/runtime/claude/kernel_ports.ts +20 -8
- package/plugins/immune-brain/runtime/github_issue_tracker.ts +321 -60
- package/plugins/immune-brain/runtime/kernel/storage.ts +8 -3
- package/plugins/immune-brain/runtime/plugin_version.ts +1 -1
- package/plugins/immune-brain/runtime/prompts/code-review.md +19 -0
- package/plugins/immune-brain/runtime/prompts/executor.md +6 -0
- package/plugins/immune-brain/runtime/prompts/qa.md +13 -1
- package/plugins/immune-brain/runtime/unattended/batch_plan.ts +1 -1
- package/plugins/immune-brain/runtime/unattended/batch_preflight.ts +73 -26
- package/plugins/immune-brain/runtime/unattended/batch_reasons.ts +6 -0
- package/plugins/immune-brain/runtime/unattended/batch_reconfirmation.ts +194 -0
- package/plugins/immune-brain/runtime/unattended/batch_runner.ts +126 -151
- package/plugins/immune-brain/runtime/unattended/batch_state.ts +34 -4
- package/plugins/immune-brain/runtime/v4_runtime.ts +54 -0
- package/plugins/immune-brain/runtime/workspace_scope.ts +31 -4
- package/plugins/immune-brain/skills/BASELINE.md +18 -1
- package/plugins/immune-brain/skills/imm-brainstorm/SKILL.md +5 -0
- package/plugins/immune-brain/skills/imm-loop/SKILL.md +4 -2
- package/plugins/immune-brain/skills/imm-planner/SKILL.md +10 -1
package/package.json
CHANGED
|
@@ -64,7 +64,7 @@ import {
|
|
|
64
64
|
type UserAttentionEventV1,
|
|
65
65
|
type UserAttentionReason,
|
|
66
66
|
} from "./pi-canary-interaction";
|
|
67
|
-
import { isToolFailureState, throwToolFailure, type ToolFailureV1 } from "./pi-canary-tool-failure";
|
|
67
|
+
import { isToolFailureState, throwToolFailure, type AssuranceFailureDetails, type ToolFailureV1 } from "./pi-canary-tool-failure";
|
|
68
68
|
import { resolveUxLanguage, uxText } from "./ux-language";
|
|
69
69
|
|
|
70
70
|
/** Host-native UI language; see ux-language.ts. Resolved once per process. */
|
|
@@ -1737,6 +1737,11 @@ async function enrichAssuranceResult(
|
|
|
1737
1737
|
taskId: string,
|
|
1738
1738
|
result: Record<string, unknown>,
|
|
1739
1739
|
): Promise<Record<string, unknown>> {
|
|
1740
|
+
if (result.recovery_error) {
|
|
1741
|
+
// Do not replay a failed observation for Host decoration or tracker hygiene.
|
|
1742
|
+
const taskState = { error: typeof result.reason === "string" ? result.reason : "authority projection unavailable" };
|
|
1743
|
+
return { ...result, task_state: taskState, next_action: nextActionForAssuranceResult(result, taskState) };
|
|
1744
|
+
}
|
|
1740
1745
|
const projection = await projectAssuranceState(ctx.cwd, taskId);
|
|
1741
1746
|
const taskState: AssuranceTaskState = projection.error
|
|
1742
1747
|
? { error: projection.error }
|
|
@@ -1761,11 +1766,13 @@ async function enrichAssuranceResult(
|
|
|
1761
1766
|
}
|
|
1762
1767
|
|
|
1763
1768
|
function nextActionForAssuranceResult(result: Record<string, unknown>, taskState: AssuranceTaskState): string {
|
|
1769
|
+
const derived = result.recovery as { next_action: string } | undefined;
|
|
1770
|
+
if (derived) return derived.next_action;
|
|
1764
1771
|
const recovery = recoveryActionForAssuranceFailure(
|
|
1765
1772
|
"error" in taskState ? taskState.error : result.reason,
|
|
1766
1773
|
);
|
|
1767
1774
|
if (recovery) return recovery;
|
|
1768
|
-
if ("error" in taskState) return "inspect authority state";
|
|
1775
|
+
if (result.recovery_error || "error" in taskState) return "inspect authority state";
|
|
1769
1776
|
if (result.state === "review_preparation_failed") return "repair Review preparation, then retry advance_assurance; QA is already committed";
|
|
1770
1777
|
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";
|
|
1771
1778
|
if (taskState.lifecycle === "done" || taskState.lifecycle === "stopped") return "none";
|
|
@@ -1872,6 +1879,7 @@ function failCanaryTool(
|
|
|
1872
1879
|
code: string,
|
|
1873
1880
|
message: string,
|
|
1874
1881
|
nextAction: string,
|
|
1882
|
+
details: AssuranceFailureDetails = {},
|
|
1875
1883
|
): never {
|
|
1876
1884
|
return throwToolFailure({
|
|
1877
1885
|
tool: "imm_kernel_canary",
|
|
@@ -1881,6 +1889,7 @@ function failCanaryTool(
|
|
|
1881
1889
|
code,
|
|
1882
1890
|
message,
|
|
1883
1891
|
next_action: nextAction,
|
|
1892
|
+
...details,
|
|
1884
1893
|
});
|
|
1885
1894
|
}
|
|
1886
1895
|
|
|
@@ -1890,6 +1899,7 @@ function throwIfCanaryToolFailure(
|
|
|
1890
1899
|
result: Record<string, unknown>,
|
|
1891
1900
|
): void {
|
|
1892
1901
|
if (!isToolFailureState(result.state)) return;
|
|
1902
|
+
const details = result as AssuranceFailureDetails;
|
|
1893
1903
|
failCanaryTool(
|
|
1894
1904
|
taskId,
|
|
1895
1905
|
operation,
|
|
@@ -1903,6 +1913,13 @@ function throwIfCanaryToolFailure(
|
|
|
1903
1913
|
typeof result.next_action === "string"
|
|
1904
1914
|
? result.next_action
|
|
1905
1915
|
: "inspect authority state",
|
|
1916
|
+
// Preserve only the coordinator's bounded observation metadata.
|
|
1917
|
+
{
|
|
1918
|
+
...(details.diagnostics ? { diagnostics: details.diagnostics } : {}),
|
|
1919
|
+
...(details.environment_failure ? { environment_failure: true } : {}),
|
|
1920
|
+
...(details.recovery ? { recovery: details.recovery } : {}),
|
|
1921
|
+
...(details.recovery_error ? { recovery_error: details.recovery_error } : {}),
|
|
1922
|
+
},
|
|
1906
1923
|
);
|
|
1907
1924
|
}
|
|
1908
1925
|
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
createBatchAuthorityRegistry,
|
|
6
6
|
deriveChildEnrollment,
|
|
7
7
|
startBatch,
|
|
8
|
+
batchQaFailureFacts,
|
|
8
9
|
readTaskRecord,
|
|
9
10
|
advancePiTask,
|
|
10
11
|
projectAssuranceForTask,
|
|
@@ -114,7 +115,7 @@ export async function executePiUnattendedBatch(
|
|
|
114
115
|
// working-tree cleanliness against the authorized scope, recovery children,
|
|
115
116
|
// plan digest, and base HEAD are one shared projection, so neither Host
|
|
116
117
|
// re-implements a batch decision.
|
|
117
|
-
|
|
118
|
+
let now = new Date().toISOString();
|
|
118
119
|
const preflight = await projectBatchPreflight({
|
|
119
120
|
root,
|
|
120
121
|
initiative_slug: initiativeSlug,
|
|
@@ -203,6 +204,9 @@ export async function executePiUnattendedBatch(
|
|
|
203
204
|
// review-2: verify cancellation signal right before authority issuance and startBatch
|
|
204
205
|
if (signal?.aborted) return batchReason("cancelled_before_execution");
|
|
205
206
|
|
|
207
|
+
now = new Date().toISOString();
|
|
208
|
+
if (Date.parse(expiresAt) <= Date.parse(now))
|
|
209
|
+
return batchReason("confirmation_failed", "confirmed batch deadline expired before authorization issuance");
|
|
206
210
|
const capability = batchRegistry.issue(binding, recoveryChildren as any, now);
|
|
207
211
|
|
|
208
212
|
let activeReviewDispatch: { operation_id: string; agent_params: Record<string, unknown> } | null = null;
|
|
@@ -251,7 +255,11 @@ export async function executePiUnattendedBatch(
|
|
|
251
255
|
return res;
|
|
252
256
|
},
|
|
253
257
|
projectTask: async (taskRoot, taskId) => {
|
|
254
|
-
|
|
258
|
+
const fresh = await projectAssuranceForTask(taskRoot, taskId);
|
|
259
|
+
if (!fresh.claim || fresh.projection.lifecycle !== "active" || fresh.error !== null) return fresh;
|
|
260
|
+
const { record, revision } = await readTaskRecord(taskRoot, taskId);
|
|
261
|
+
if (!record || revision !== fresh.projection.record_revision) throw new Error(`Kernel recovery projection changed for ${taskId}`);
|
|
262
|
+
return { ...fresh, ...batchQaFailureFacts(record) };
|
|
255
263
|
},
|
|
256
264
|
ownsTaskClaim: (taskId) => {
|
|
257
265
|
if (isResuming && taskId === readActiveClaimTaskId(root)) {
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import type { AssuranceAdvanceResult } from "../runtime/assurance/coordinator";
|
|
2
|
+
|
|
3
|
+
export type AssuranceFailureDetails = Pick<AssuranceAdvanceResult,
|
|
4
|
+
"diagnostics" | "environment_failure" | "recovery" | "recovery_error">;
|
|
5
|
+
|
|
6
|
+
export interface ToolFailureV1 extends AssuranceFailureDetails {
|
|
2
7
|
contract: "immune_brain/tool_failure/v1";
|
|
3
8
|
tool: "imm_canary_enrollment" | "imm_kernel_canary";
|
|
4
9
|
task_id: string;
|
|
@@ -171,10 +171,12 @@ export interface TaskRecordRead {
|
|
|
171
171
|
manifest_digest: string;
|
|
172
172
|
};
|
|
173
173
|
}>;
|
|
174
|
+
history: import("../runtime/kernel/types").TaskRecord["history"];
|
|
174
175
|
findings: Array<{
|
|
175
176
|
id: string;
|
|
176
177
|
kind: string;
|
|
177
178
|
status: string;
|
|
179
|
+
acceptance_id?: string | null;
|
|
178
180
|
summary?: string;
|
|
179
181
|
anchor?: string | null;
|
|
180
182
|
evidence?: unknown;
|
|
@@ -451,6 +453,7 @@ export type {
|
|
|
451
453
|
BatchAuthorizationBinding,
|
|
452
454
|
ValidatedBatchAuthorization,
|
|
453
455
|
} from "../runtime/kernel/batch_authority";
|
|
456
|
+
export { batchQaFailureFacts } from "../runtime/unattended/batch_runner";
|
|
454
457
|
export type {
|
|
455
458
|
BatchRunnerKernelPort,
|
|
456
459
|
StartBatchInput,
|
|
@@ -553,12 +556,14 @@ export async function getSharedPiProgression(): Promise<any> {
|
|
|
553
556
|
export async function advancePiTask(root: string, taskId: string): Promise<any> {
|
|
554
557
|
const progression = await getSharedPiProgression();
|
|
555
558
|
const result = await progression.advance(taskId, { cwd: root });
|
|
556
|
-
|
|
557
|
-
if (result.state === "
|
|
558
|
-
if (result.state === "
|
|
559
|
-
if (result.state === "
|
|
560
|
-
if (result.state === "
|
|
561
|
-
return { state:
|
|
559
|
+
const facts = { diagnostics: result.diagnostics, environment_failure: result.environment_failure, recovery: result.recovery };
|
|
560
|
+
if (result.state === "completed") return { state: "completed", ...facts };
|
|
561
|
+
if (result.state === "stopped") return { state: "stopped", ...facts };
|
|
562
|
+
if (result.state === "rework") return { state: "rework", operation: result.operation, summary: result.summary, ...facts };
|
|
563
|
+
if (result.state === "review_ready") return { state: "review_ready", operation_id: result.operation_id, agent_params: result.agent_params, ...facts };
|
|
564
|
+
if (result.state === "review_preparation_failed") return { state: result.state, operation: result.operation, operation_id: result.operation_id, reason: result.reason, ...facts };
|
|
565
|
+
if (result.state === "blocked") return { state: "blocked", reason: result.reason, ...facts };
|
|
566
|
+
return { state: "failed", reason: (result as { reason?: string }).reason ?? "advance failed", ...facts };
|
|
562
567
|
}
|
|
563
568
|
|
|
564
569
|
export async function projectAssuranceForTask(root: string, taskId: string): Promise<any> {
|
|
@@ -9,6 +9,20 @@
|
|
|
9
9
|
- Stage only explicit task-owned paths. This staging authority does not grant
|
|
10
10
|
commit, push, broad staging, or authority over pre-existing user changes.
|
|
11
11
|
Never use `git add .` or `git add -A` in a dirty worktree.
|
|
12
|
+
- Grant effects separately: staging, commit, push, publication, and outbound
|
|
13
|
+
model/data calls are distinct operations. Recovering a stage-only instruction
|
|
14
|
+
restores staging and nothing more; commit, push, and publication each keep
|
|
15
|
+
their own existing grant. An explicit approval already covering the same
|
|
16
|
+
operation, target, and impact — including a valid batch capability — stays
|
|
17
|
+
usable without another gate.
|
|
18
|
+
- Before a new outbound effect, check the project's existing research channel and
|
|
19
|
+
data scope. A public article, a mock, a documentation example, or a local
|
|
20
|
+
read-only database gives no authority to call an arbitrary provider or send new
|
|
21
|
+
data; authorize only a genuinely new channel/data/effect delta. Distinguish
|
|
22
|
+
documentation, mock, real-channel, and model-quality evidence when reporting.
|
|
23
|
+
- These text rules are instruction contracts, not a hard bash sandbox. They
|
|
24
|
+
guide behavior and are checked as contracts; they do not technically prevent an
|
|
25
|
+
arbitrary shell command, so authority gates and review remain the real boundary.
|
|
12
26
|
- Do not create, switch, or delete Git worktrees; operate only in the Host launch directory.
|
|
13
27
|
- Record reproducible evidence before reporting closure.
|
|
14
28
|
- 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.
|
|
@@ -81,7 +95,6 @@ non-Kernel operations, an explicit user approval already covering the same
|
|
|
81
95
|
operation, target, and impact is sufficient; ask again only for a material delta.
|
|
82
96
|
A generic continuation or configured preference is not blanket authorization.
|
|
83
97
|
Mandatory native gates and hash-bound manifest approvals still apply.
|
|
84
|
-
|
|
85
98
|
Privileged effects include:
|
|
86
99
|
|
|
87
100
|
- publish, release, deployment, or remote-system mutation;
|
|
@@ -91,6 +104,10 @@ Privileged effects include:
|
|
|
91
104
|
override; and
|
|
92
105
|
- external writes whose target or impact cannot be safely reversed locally.
|
|
93
106
|
|
|
107
|
+
An existing grant for one of these never inherits another: a stage-only
|
|
108
|
+
instruction stays stage-only, a commit is not push or publication authority,
|
|
109
|
+
and a valid batch capability commits only its own scope-bounded child.
|
|
110
|
+
|
|
94
111
|
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
112
|
|
|
96
113
|
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.
|