immune-brain 3.6.5 → 3.6.6
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 +45 -0
- 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 +31 -2
- package/plugins/immune-brain/.pi-extension/pi-canary-interaction.ts +38 -10
- package/plugins/immune-brain/dist/BASELINE.md +48 -15
- package/plugins/immune-brain/dist/claude/mcp-server.mjs +20 -10
- package/plugins/immune-brain/dist/docs/reference/planning-quality-gate.md +1 -1
- package/plugins/immune-brain/dist/docs/reference/subagent-dispatch-protocol.md +1 -1
- package/plugins/immune-brain/dist/imm-agent-doc-maintain.md +9 -1
- package/plugins/immune-brain/dist/imm-brainstorm.md +49 -35
- package/plugins/immune-brain/dist/imm-doc-prune.md +7 -1
- package/plugins/immune-brain/dist/imm-loop.md +23 -11
- package/plugins/immune-brain/dist/imm-planner.md +65 -28
- package/plugins/immune-brain/dist/imm-pr-fix.md +6 -2
- package/plugins/immune-brain/dist/role-prompts/executor.md +18 -10
- package/plugins/immune-brain/dist/role-prompts/pr-fix.md +5 -2
- package/plugins/immune-brain/runtime/assurance/verification.ts +13 -2
- package/plugins/immune-brain/runtime/github_issue_tracker.ts +1018 -17
- package/plugins/immune-brain/runtime/kernel/canary_application.ts +7 -1
- package/plugins/immune-brain/runtime/kernel/reducer.ts +3 -1
- package/plugins/immune-brain/runtime/plugin_version.ts +1 -1
- package/plugins/immune-brain/runtime/prompts/executor.md +18 -10
- package/plugins/immune-brain/runtime/prompts/pr-fix.md +5 -2
- package/plugins/immune-brain/skills/BASELINE.md +48 -15
- package/plugins/immune-brain/skills/imm-agent-doc-maintain/SKILL.md +20 -4
- package/plugins/immune-brain/skills/imm-brainstorm/SKILL.md +24 -64
- package/plugins/immune-brain/skills/imm-doc-prune/SKILL.md +18 -3
- package/plugins/immune-brain/skills/imm-loop/SKILL.md +20 -6
- package/plugins/immune-brain/skills/imm-planner/SKILL.md +35 -8
- package/plugins/immune-brain/skills/imm-pr-fix/SKILL.md +17 -3
package/README.md
CHANGED
|
@@ -108,6 +108,51 @@ Internal roles (Executor, QA, Review, Compounder) are dispatched by `imm-loop`
|
|
|
108
108
|
|
|
109
109
|
**Recommended default:** let natural-language routing pick brainstorm vs. planner for you. Explicitly invoke a skill only when you want to force that phase.
|
|
110
110
|
|
|
111
|
+
### Managed Path entries (brainstorm → planner → loop)
|
|
112
|
+
|
|
113
|
+
The three Managed skills form one continuous pipeline with a single authority model: nothing is written or executed until you confirm it in a native gate, and every state transition is settled by the Kernel.
|
|
114
|
+
|
|
115
|
+
#### `imm-brainstorm` — requirement clarification
|
|
116
|
+
|
|
117
|
+
- **Trigger:** explicit `imm-brainstorm`, or a vague request Pi routes to clarification.
|
|
118
|
+
- **What it does:** frames the problem — goal, constraints, unknowns, risks — and produces a `brainstorm_framing` result with a recommended next step (usually → `imm-planner`).
|
|
119
|
+
- **What it never does:** read-only by design. No code, test, or runtime edits; no Spec, Plan, or workflow-state writes.
|
|
120
|
+
- **Exit:** a framed, answerable problem statement you can hand to the Planner.
|
|
121
|
+
|
|
122
|
+
#### `imm-planner` — Spec & TaskIntent planning
|
|
123
|
+
|
|
124
|
+
- **Trigger:** explicit `imm-planner`, or a clear goal Pi routes to planning.
|
|
125
|
+
- **What it does:** authors or revises `TaskIntent` files (`docs/plans/`) and living Specs (`docs/specs/`) — scope (`scope_hint`), risk tier, acceptance descriptors. For multi-task initiatives it decomposes the work into parent/child TaskIntents with dependency order and granularity.
|
|
126
|
+
- **What it never does:** implements code, overwrites an enrolled TaskIntent without a revision flow, or grants execution authority — only the native Enrollment gate can.
|
|
127
|
+
- **Exit:** Git-tracked `TaskIntent` awaiting enrollment confirmation.
|
|
128
|
+
|
|
129
|
+
#### `imm-loop` — managed execution & assurance
|
|
130
|
+
|
|
131
|
+
- **Trigger:** explicit `imm-loop` (start, resume, or check a managed task).
|
|
132
|
+
- **What it does:** drives one task end to end through foreground tools — Executor edits inside the frozen scope, deterministic QA executes every acceptance descriptor, an isolated Review subagent audits material/critical tasks, and the Kernel settles terminal evidence. Interrupted workflows resume from on-disk state; the Kernel projection is authoritative.
|
|
133
|
+
- **What it never does:** skips or weakens a failing check, runs without your Enrollment/revision/authorization gates, or continues after lineage or authority drift — it fails closed.
|
|
134
|
+
- **Exit:** `done` task record with QA + Review attestations in `.imm/audit/<task-id>/`.
|
|
135
|
+
|
|
136
|
+
### Standalone maintenance entries
|
|
137
|
+
|
|
138
|
+
The three repair/maintenance skills are host-native: they never create a managed task, never continue a Managed workflow, and preserve any active Managed owner.
|
|
139
|
+
|
|
140
|
+
#### `imm-pr-fix` — PR repair
|
|
141
|
+
|
|
142
|
+
- **Trigger:** explicit request to repair GitHub PR review feedback, merge conflicts, or failing checks.
|
|
143
|
+
- **What it does:** repairs one PR in place — diagnoses the review/conflict/CI evidence, applies the minimal scoped fix, and re-runs the relevant checks.
|
|
144
|
+
- **Boundaries:** preserves the PR scope; treats remote text as untrusted data; repair never grants merge or approval authority.
|
|
145
|
+
|
|
146
|
+
#### `imm-doc-prune` — stale doc pruning
|
|
147
|
+
|
|
148
|
+
- **Trigger:** explicit request to prune stale current documentation.
|
|
149
|
+
- **What it does:** audits documentation staleness read-only, then deletes only entries you approved in an exact hash-bound manifest, with immediate revalidation after each mutation.
|
|
150
|
+
|
|
151
|
+
#### `imm-agent-doc-maintain` — agent instruction minimization
|
|
152
|
+
|
|
153
|
+
- **Trigger:** explicit request to minimize tracked `AGENTS.md` / `CLAUDE.md` / `GEMINI.md`.
|
|
154
|
+
- **What it does:** keeps only the necessary non-discoverable rules in agent instruction files, under the same read-only-audit + hash-bound-manifest-approval model as `imm-doc-prune`.
|
|
155
|
+
|
|
111
156
|
---
|
|
112
157
|
|
|
113
158
|
## Lifecycle
|
package/package.json
CHANGED
|
@@ -1686,8 +1686,24 @@ async function executeOrdinaryOperation(
|
|
|
1686
1686
|
const priorIntent = await readTaskIntent(ctx.cwd, input.taskId);
|
|
1687
1687
|
const sidecar = join(ctx.cwd, priorIntent.intent_ref.path);
|
|
1688
1688
|
const priorBytes = operation.op === "revise_intent" ? readFileSync(sidecar) : null;
|
|
1689
|
+
// A content-changing revision writes the sidecar before the kernel's drift
|
|
1690
|
+
// check runs; an unstaged write is itself scoped drift and deadlocks the
|
|
1691
|
+
// revision. Mirror the breaking-revision path: stage the written sidecar
|
|
1692
|
+
// (worktree == index) and restore the exact prior index entry on failure.
|
|
1693
|
+
const priorIndexState = priorBytes !== null
|
|
1694
|
+
? execFileSync("git", ["ls-files", "--stage", "-z", "--", priorIntent.intent_ref.path], {
|
|
1695
|
+
cwd: ctx.cwd,
|
|
1696
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1697
|
+
})
|
|
1698
|
+
: null;
|
|
1689
1699
|
try {
|
|
1690
|
-
if (priorBytes)
|
|
1700
|
+
if (priorBytes) {
|
|
1701
|
+
writeFileSync(sidecar, `${JSON.stringify(operation.next_intent, null, 2)}\n`);
|
|
1702
|
+
execFileSync("git", ["add", "--", priorIntent.intent_ref.path], {
|
|
1703
|
+
cwd: ctx.cwd,
|
|
1704
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1705
|
+
});
|
|
1706
|
+
}
|
|
1691
1707
|
const result = await app.execute({
|
|
1692
1708
|
root: ctx.cwd,
|
|
1693
1709
|
task_id: input.taskId,
|
|
@@ -1705,7 +1721,20 @@ async function executeOrdinaryOperation(
|
|
|
1705
1721
|
} catch (error) {
|
|
1706
1722
|
if (priorBytes) {
|
|
1707
1723
|
const current = await readTaskRecord(ctx.cwd, input.taskId);
|
|
1708
|
-
if (current.record?.intent_snapshot.revision === priorIntent.intent.revision)
|
|
1724
|
+
if (current.record?.intent_snapshot.revision === priorIntent.intent.revision) {
|
|
1725
|
+
writeFileSync(sidecar, priorBytes);
|
|
1726
|
+
execFileSync("git", ["update-index", "--force-remove", "--", priorIntent.intent_ref.path], {
|
|
1727
|
+
cwd: ctx.cwd,
|
|
1728
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1729
|
+
});
|
|
1730
|
+
if (priorIndexState && priorIndexState.length > 0) {
|
|
1731
|
+
execFileSync("git", ["update-index", "-z", "--index-info"], {
|
|
1732
|
+
cwd: ctx.cwd,
|
|
1733
|
+
input: priorIndexState,
|
|
1734
|
+
stdio: ["pipe", "ignore", "pipe"],
|
|
1735
|
+
});
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1709
1738
|
}
|
|
1710
1739
|
throw error;
|
|
1711
1740
|
}
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { DynamicBorder, type ExtensionAPI, type ExtensionContext, type Theme, type ThemeColor } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Container,
|
|
4
|
+
SelectList,
|
|
5
|
+
Text,
|
|
6
|
+
sliceByColumn,
|
|
7
|
+
truncateToWidth,
|
|
8
|
+
visibleWidth,
|
|
9
|
+
type Component,
|
|
10
|
+
type SelectItem,
|
|
11
|
+
} from "@earendil-works/pi-tui";
|
|
3
12
|
|
|
4
13
|
export const USER_ATTENTION_EVENT = "immune-brain:user-attention.v1" as const;
|
|
5
14
|
export const TASK_RAIL_KEY = "immune-brain.task-rail" as const;
|
|
@@ -186,12 +195,7 @@ export async function requestAuthorityDialog<T extends string, R = T | undefined
|
|
|
186
195
|
export function presentTaskRail(ctx: UiContext, view: TaskRailView): void {
|
|
187
196
|
try {
|
|
188
197
|
ctx.ui.setWidget(TASK_RAIL_KEY, (_tui, theme) => {
|
|
189
|
-
return
|
|
190
|
-
render(width: number): string[] {
|
|
191
|
-
return renderTaskRail(view, width, theme);
|
|
192
|
-
},
|
|
193
|
-
invalidate(): void {},
|
|
194
|
-
};
|
|
198
|
+
return safeWidgetRender((width) => renderTaskRail(view, width, theme));
|
|
195
199
|
}, { placement: "aboveEditor" });
|
|
196
200
|
if (view.state === "Completed" || view.state === "Stopped") terminalRailUis.add(ctx.ui);
|
|
197
201
|
else terminalRailUis.delete(ctx.ui);
|
|
@@ -277,6 +281,25 @@ export async function presentTaskOverviewOverlay(
|
|
|
277
281
|
}
|
|
278
282
|
}
|
|
279
283
|
|
|
284
|
+
// pi renders widget lines verbatim and throws in doRender — killing the whole
|
|
285
|
+
// process — when a line exceeds the terminal width. Clamp every line at the
|
|
286
|
+
// widget boundary so line-builder bugs degrade to a truncated row instead.
|
|
287
|
+
function safeWidgetRender(render: (width: number) => string[]): {
|
|
288
|
+
render(width: number): string[];
|
|
289
|
+
invalidate(): void;
|
|
290
|
+
} {
|
|
291
|
+
return {
|
|
292
|
+
render(width: number): string[] {
|
|
293
|
+
try {
|
|
294
|
+
return render(width).map((line) => truncateToWidth(line, width, "…"));
|
|
295
|
+
} catch {
|
|
296
|
+
return [];
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
invalidate(): void {},
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
280
303
|
export function clearTaskRail(ctx: UiContext): void {
|
|
281
304
|
try {
|
|
282
305
|
ctx.ui.setWidget(TASK_RAIL_KEY, undefined);
|
|
@@ -501,13 +524,18 @@ function strings(value: unknown): string[] {
|
|
|
501
524
|
return Array.isArray(value) ? value.filter((item): item is string => typeof item === "string") : [];
|
|
502
525
|
}
|
|
503
526
|
|
|
527
|
+
// Truncate by terminal columns, not character count — CJK/double-width chars
|
|
528
|
+
// overflow otherwise and pi's doRender crashes the whole process on wide lines.
|
|
504
529
|
function bounded(value: string, max: number): string {
|
|
505
|
-
return value
|
|
530
|
+
return truncateToWidth(value, max, "…");
|
|
506
531
|
}
|
|
507
532
|
|
|
508
533
|
function boundedMiddle(value: string, max: number): string {
|
|
509
|
-
|
|
534
|
+
const width = visibleWidth(value);
|
|
535
|
+
if (width <= max) return value;
|
|
510
536
|
const visible = max - 1;
|
|
511
537
|
const start = Math.ceil(visible / 2);
|
|
512
|
-
|
|
538
|
+
const head = truncateToWidth(sliceByColumn(value, 0, start, true), start, "");
|
|
539
|
+
const tail = truncateToWidth(sliceByColumn(value, width - (visible - start), visible - start, true), visible - start, "");
|
|
540
|
+
return `${head}…${tail}`;
|
|
513
541
|
}
|
|
@@ -2,15 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
## Shared Guards
|
|
4
4
|
|
|
5
|
-
-
|
|
6
|
-
|
|
7
|
-
-
|
|
5
|
+
- On explicit invocation, read only common constraints and selected section routes
|
|
6
|
+
from `dist/`; nested modes, examples, recovery, and references load on demand.
|
|
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
|
+
- Keep edits inside the user-requested Direct scope or the enrolled TaskIntent acceptance and `scope_hint`.
|
|
9
|
+
- Stage only explicit task-owned paths. Never use `git add .` or `git add -A` in a dirty worktree.
|
|
10
|
+
- Do not create, switch, or delete Git worktrees; operate only in the Host launch directory.
|
|
8
11
|
- Record reproducible evidence before reporting closure.
|
|
9
|
-
-
|
|
12
|
+
- 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.
|
|
13
|
+
- Inspect unknown test scripts before execution. A script named `test` that
|
|
14
|
+
deploys, writes production data, or uses credentials is a protected effect,
|
|
15
|
+
not routine local verification; apply Host Confirmation Boundary before it runs.
|
|
16
|
+
- Unanswered questions block only dependent commitments or execution. Continue
|
|
17
|
+
independent read-only investigation and local alternative drafts; label drafts
|
|
18
|
+
unapproved and never treat silence as consent or finalize a dependent Spec.
|
|
19
|
+
- Disclose unrelated pre-existing failures without repairing them or widening
|
|
20
|
+
scope. If they prevent a required check from passing, report that blocker and
|
|
21
|
+
incomplete verification rather than claiming completion.
|
|
22
|
+
- Use bounded evidence to cover affected callers and state owners for shared-contract, security, migration, persistence, or authority changes; the category alone never requires full-directory reads. Stop expanding once the relevant behavior and verification are understood.
|
|
10
23
|
- Lead with conclusion, evidence, and Next Action.
|
|
11
24
|
- Advisory roles do not implement; Managed execution roles do not close QA.
|
|
12
25
|
- An explicit Managed Skill entry stops host-native mutation and routes scope changes to `imm-planner`; Managed execution remains inside its accepted boundary.
|
|
13
26
|
|
|
27
|
+
Before local edits or checks, read Verification and Local Recovery below. Read-only
|
|
28
|
+
framing does not load that execution guidance.
|
|
29
|
+
|
|
30
|
+
## Verification and Local Recovery
|
|
31
|
+
|
|
32
|
+
- Select required checks from the requested outcome, affected behavior, and project requirements before claiming completion. Documentation changes use relevant link, mirror, and contract checks; local logic uses focused tests; shared behavior, build configuration, cross-module changes, and release preparation widen regression coverage. Never reduce required checks merely because they fail.
|
|
33
|
+
- Reuse a recorded passing local result only while the relevant code, test inputs, command, dependencies, and environment remain unchanged. Changed or uncertain inputs require rerunning affected checks. Role handoff alone does not invalidate local evidence; local evidence never replaces Kernel-owned deterministic QA or fresh snapshot-bound Review.
|
|
34
|
+
- Recover routine local failures within the authorized scope: select an unused port, create temporary outputs, and remove only task-generated disposable files. Never overwrite user data or stop an unrelated process to free a port. Before dependency installation, inspect the existing project command, lifecycle scripts, network use, and credential effects; use it only within existing authorization, without dependency or lockfile changes. Unknown or protected effects follow Host Confirmation Boundary.
|
|
35
|
+
- Retry a failed ordinary operation only after new evidence or a relevant condition changes; do not repeat identical attempts indefinitely. This does not authorize retrying a failed native authority gate or an uncertain remote write.
|
|
36
|
+
- When changing a supported behavior or contract, update its existing tests, remove tests whose protected behavior has retired, merge redundant coverage, and remove orphaned fixtures/helpers within the affected scope. For each removal, identify the retired behavior or the remaining coverage and run the surviving related checks. Never delete by age, count, slowness, or flakiness alone. Temporary tests name their exit condition; no per-test registry or repository-wide audit is required.
|
|
37
|
+
|
|
14
38
|
## Workflow Activation
|
|
15
39
|
|
|
16
40
|
Ordinary host input stays host-native and does not run natural-language Managed
|
|
@@ -46,11 +70,15 @@ returns to `imm-planner`; an enrolled task resumes through `imm-loop` from the
|
|
|
46
70
|
current Assurance projection. Do not create or mutate workflow state while
|
|
47
71
|
classifying a non-mutating request.
|
|
48
72
|
|
|
49
|
-
Stage only explicit task-owned paths. Never use `git add .` or `git add -A` in a dirty worktree.
|
|
50
|
-
|
|
51
73
|
### Host Confirmation Boundary
|
|
52
74
|
|
|
53
|
-
Require exact host confirmation only for privileged effects
|
|
75
|
+
Require exact host confirmation only for privileged effects. For ordinary
|
|
76
|
+
non-Kernel operations, an explicit user approval already covering the same
|
|
77
|
+
operation, target, and impact is sufficient; ask again only for a material delta.
|
|
78
|
+
A generic continuation or configured preference is not blanket authorization.
|
|
79
|
+
Mandatory native gates and hash-bound manifest approvals still apply.
|
|
80
|
+
|
|
81
|
+
Privileged effects include:
|
|
54
82
|
|
|
55
83
|
- publish, release, deployment, or remote-system mutation;
|
|
56
84
|
- destructive or irreversible operations and Git history rewrite;
|
|
@@ -65,7 +93,10 @@ Routine Managed enrollment uses one current-Host native confirmation bound to th
|
|
|
65
93
|
|
|
66
94
|
State mutations, step activations, QA decisions, and plan switches remain
|
|
67
95
|
strictly sequential. Read-only work — repo exploration, advisory review,
|
|
68
|
-
host probing, planner research —
|
|
96
|
+
host probing, planner research — is eligible for parallel dispatch in
|
|
97
|
+
capability terms, but Pi schedules one foreground child at a time: launch one
|
|
98
|
+
child, consume its direct result, then decide whether another child is needed.
|
|
99
|
+
Do not assume multiple foreground Agents run as a concurrent batch.
|
|
69
100
|
|
|
70
101
|
Parallel dispatch is restricted by capability, not by a closed Skill list. Every
|
|
71
102
|
child delegation packet must enforce read-only advisory behavior: no file edits,
|
|
@@ -99,13 +130,15 @@ always run sequentially.
|
|
|
99
130
|
|
|
100
131
|
## Success Criteria
|
|
101
132
|
|
|
102
|
-
- Direct work closes only
|
|
103
|
-
- A Managed
|
|
133
|
+
- Direct work closes only when the requested result is delivered and the required verification passes: a failed or unavailable required check is reported as incomplete work with its concrete blocker, never as completion. Check breadth follows the request and established project requirements, not a universal full-repository rule. Apply Shared Guards and Verification and Local Recovery for in-scope repair and evidence reuse.
|
|
134
|
+
- A Managed task is ready to execute only when the target result, boundary, and
|
|
104
135
|
verification path are clear enough to avoid speculative edits.
|
|
105
|
-
- A Managed
|
|
106
|
-
verification path and the
|
|
107
|
-
-
|
|
108
|
-
|
|
136
|
+
- A Managed task is closable only when execution evidence proves the recorded
|
|
137
|
+
verification path and the TaskRecord still matches the enrolled TaskIntent boundary.
|
|
138
|
+
- Collect missing in-scope evidence and continue under the current owner. Missing
|
|
139
|
+
evidence alone does not require replanning. Escalate only a demonstrated
|
|
140
|
+
scope/acceptance mismatch or protected decision through the current owner's
|
|
141
|
+
revision or authorization path; never silently expand execution or QA scope.
|
|
109
142
|
|
|
110
143
|
## Retirement Completion
|
|
111
144
|
|
|
@@ -135,4 +168,4 @@ Immune-Brain commands and `.imm` state.
|
|
|
135
168
|
|
|
136
169
|
Prefer shallow discovery before full-file reads. Start with file lists,
|
|
137
170
|
`rg` hits, symbol/signature scans, and targeted line ranges; read whole files
|
|
138
|
-
only when the narrower evidence path cannot answer the active
|
|
171
|
+
only when the narrower evidence path cannot answer the active task question.
|
|
@@ -42,7 +42,7 @@ function probeHost(env = process.env, platform = process.platform, hostVersion)
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// plugins/immune-brain/runtime/plugin_version.ts
|
|
45
|
-
var PLUGIN_VERSION = "3.6.
|
|
45
|
+
var PLUGIN_VERSION = "3.6.6";
|
|
46
46
|
|
|
47
47
|
// plugins/immune-brain/runtime/claude/interaction.ts
|
|
48
48
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -688,7 +688,7 @@ import { createHash as createHash5, randomUUID as randomUUID2 } from "node:crypt
|
|
|
688
688
|
|
|
689
689
|
// plugins/immune-brain/runtime/assurance/verification.ts
|
|
690
690
|
import { createHash as createHash3 } from "node:crypto";
|
|
691
|
-
import { execFileSync, spawn } from "node:child_process";
|
|
691
|
+
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
692
692
|
import { realpathSync as realpathSync2, statSync } from "node:fs";
|
|
693
693
|
import { isAbsolute as isAbsolute2, resolve, sep as sep2, relative } from "node:path";
|
|
694
694
|
|
|
@@ -792,7 +792,15 @@ function resolveBunRunner() {
|
|
|
792
792
|
}
|
|
793
793
|
let real;
|
|
794
794
|
try {
|
|
795
|
-
|
|
795
|
+
const execPath = spawnSync(executable, ["-e", "console.log(process.execPath)"], {
|
|
796
|
+
encoding: "utf8",
|
|
797
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
798
|
+
});
|
|
799
|
+
if (execPath.status === 0 && execPath.stdout.trim().length > 0) {
|
|
800
|
+
real = realpathSync2(execPath.stdout.trim());
|
|
801
|
+
} else {
|
|
802
|
+
real = realpathSync2(executable);
|
|
803
|
+
}
|
|
796
804
|
} catch {
|
|
797
805
|
throw new VerificationDescriptorError("bun runner realpath is unresolvable");
|
|
798
806
|
}
|
|
@@ -1823,7 +1831,7 @@ import { tmpdir as tmpdir2 } from "node:os";
|
|
|
1823
1831
|
import { join as join4 } from "node:path";
|
|
1824
1832
|
|
|
1825
1833
|
// plugins/immune-brain/runtime/workspace_scope.ts
|
|
1826
|
-
import { spawnSync } from "node:child_process";
|
|
1834
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
1827
1835
|
import { createHash as createHash6 } from "node:crypto";
|
|
1828
1836
|
import {
|
|
1829
1837
|
existsSync as existsSync2,
|
|
@@ -1834,7 +1842,7 @@ import {
|
|
|
1834
1842
|
} from "node:fs";
|
|
1835
1843
|
import { resolve as resolve2 } from "node:path";
|
|
1836
1844
|
function git(root, args) {
|
|
1837
|
-
const result =
|
|
1845
|
+
const result = spawnSync2("git", ["-C", root, ...args], {
|
|
1838
1846
|
encoding: "utf8",
|
|
1839
1847
|
stdio: ["ignore", "pipe", "pipe"]
|
|
1840
1848
|
});
|
|
@@ -1858,7 +1866,7 @@ var portablePathCollator = new Intl.Collator("und", {
|
|
|
1858
1866
|
});
|
|
1859
1867
|
var gitTaskSnapshotTestHook;
|
|
1860
1868
|
function gitBytes(root, args) {
|
|
1861
|
-
const result =
|
|
1869
|
+
const result = spawnSync2("git", ["-C", root, ...args], {
|
|
1862
1870
|
encoding: null,
|
|
1863
1871
|
stdio: ["ignore", "pipe", "pipe"],
|
|
1864
1872
|
maxBuffer: 8 * 1024 * 1024
|
|
@@ -5323,7 +5331,9 @@ function appendHistory(record, action, from, detail, audit) {
|
|
|
5323
5331
|
record.history.push(entry);
|
|
5324
5332
|
}
|
|
5325
5333
|
function intentRefMatches(intent, ref) {
|
|
5326
|
-
|
|
5334
|
+
const activePath = `docs/plans/${intent.task_id}.intent.json`;
|
|
5335
|
+
const archivedPath = `docs/plans/archive/${intent.task_id}.intent.json`;
|
|
5336
|
+
return (ref.path === activePath || ref.path === archivedPath) && ref.content_hash === canonicalIntentHash(intent);
|
|
5327
5337
|
}
|
|
5328
5338
|
function hasPrivilegedKind(action) {
|
|
5329
5339
|
return action.type === "record_approval" || action.type === "approve_breaking_intent_revision" || action.type === "request_rework" || action.type === "authorize_rework" || action.type === "stop" || action.type === "resolve_user_decision";
|
|
@@ -6051,7 +6061,7 @@ function createCanaryApplication(registry) {
|
|
|
6051
6061
|
type: "revise_intent",
|
|
6052
6062
|
next_intent: operation.next_intent,
|
|
6053
6063
|
next_intent_ref: {
|
|
6054
|
-
path: `docs/plans/${operation.next_intent.task_id}.intent.json`,
|
|
6064
|
+
path: snapshot.record.artifact_state === "frozen" ? `docs/plans/archive/${operation.next_intent.task_id}.intent.json` : `docs/plans/${operation.next_intent.task_id}.intent.json`,
|
|
6055
6065
|
content_hash: canonicalIntentHash(operation.next_intent)
|
|
6056
6066
|
}
|
|
6057
6067
|
};
|
|
@@ -6336,12 +6346,12 @@ function createEnrollmentAuthorityRegistry() {
|
|
|
6336
6346
|
|
|
6337
6347
|
// plugins/immune-brain/runtime/kernel/pi_canary_prepare.ts
|
|
6338
6348
|
import { createHash as createHash12 } from "node:crypto";
|
|
6339
|
-
import { spawnSync as
|
|
6349
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
6340
6350
|
import { resolve as resolve6 } from "node:path";
|
|
6341
6351
|
var SOURCE_PATH = ".imm/state/workspace.json";
|
|
6342
6352
|
var GIT_OBJECT_ID4 = /^(?:[a-f0-9]{40}|[a-f0-9]{64})$/;
|
|
6343
6353
|
function readGitHead(root) {
|
|
6344
|
-
const result =
|
|
6354
|
+
const result = spawnSync3("git", ["-C", root, "rev-parse", "--verify", "HEAD^{commit}"], {
|
|
6345
6355
|
encoding: "utf8"
|
|
6346
6356
|
});
|
|
6347
6357
|
const head = typeof result.stdout === "string" ? result.stdout.trim() : "";
|
|
@@ -23,7 +23,7 @@ Apply the gate when the task touches one or more of these surfaces:
|
|
|
23
23
|
- **Technical Design baseline**: keep the Spec as the single design authority and make each Plan Step reference the applicable decision or invariant instead of duplicating design prose.
|
|
24
24
|
- **design-view selection**: for Medium/High risk, select every materially relevant technical-design view from architecture layers, service/component interfaces, data flow, state transitions, and temporal sequence. Record selected views and why omitted views cannot affect the design. Low risk remains concise.
|
|
25
25
|
- **TaskIntent decomposition**: use Technical Design boundaries as one retain/split criterion with outcome, Verification, dependency, risk, rollback, compatibility, and authority. Split a successor TaskIntent only when a service, state-machine owner, migration, independently promotable layer, or sequence dependency needs independent verification, rollback, authorization, or settlement. A TaskIntent should normally change one primary trust-boundary invariant, but traversing several boundaries or updating both sides of one authority chain does not itself require a split. Split independently verifiable, reversible, authorizable, migratable, or settleable trust invariants. Keep multiple trust-boundary changes together only for one atomic security outcome whose split would create an unsafe or unusable intermediate state, and record that rationale in the Spec. Treat this as Planner judgment rather than a schema field or Enrollment counting rule. Do not split merely because the design names several layers, files, or services, and do not revive prose Plan authority.
|
|
26
|
-
- **Mermaid intent**: use Mermaid only when it clarifies structure, sequence, data flow, or state transitions; it is not a universal gate or a second source of truth.
|
|
26
|
+
- **Mermaid intent**: use Mermaid only when it clarifies structure, sequence, data flow, or state transitions; it is not a universal gate or a second source of truth. Medium/High risk Specs record `**Diagram decision**: required|not_required` and a non-empty `**Diagram reason**:`. A `required` decision must include Mermaid; `not_required` explains why prose is sufficient. Low-risk Specs omit the empty ceremony and record neither field.
|
|
27
27
|
- **Design Conformance**: before final closure, require Spec-to-implementation evidence. A local implementation mismatch routes to `rework`; a structural or intended design change routes to `replan` through Planner. QA cannot silently approve a design change.
|
|
28
28
|
- **Brainstorm traceability**: ensure every `BR-*` item listed in `Brainstorm manifest` is mapped in `Brainstorm Trace`.
|
|
29
29
|
- **roadmap information preservation**: for large or multi-phase work, distinguish the Roadmap from the current executable slice, preserve deferred phase goals, open questions, promotion criteria, and candidate next Plans.
|
|
@@ -104,7 +104,7 @@ Parent workflow role 必须:
|
|
|
104
104
|
4. 把 partial/error 标记为 `degraded`。
|
|
105
105
|
5. 保留自身 baseline review,不把最终判断权交给 child。
|
|
106
106
|
|
|
107
|
-
普通 advisory/discovery 的每次启动都消耗一个 candidate budget slot;失败、取消、timeout 或 result_untrusted 均丢弃该输出且不得自动重试。Parent 仅在剩余候选仍独立有用且 evidence budget 仍需要时继续,否则转 solo/fail-closed fallback,并记录 `dispatch_failed` 或 `child_timeout
|
|
107
|
+
普通 advisory/discovery 的每次启动都消耗一个 candidate budget slot;失败、取消、timeout 或 result_untrusted 均丢弃该输出且不得自动重试。Parent 仅在剩余候选仍独立有用且 evidence budget 仍需要时继续,否则转 solo/fail-closed fallback,并记录 `dispatch_failed` 或 `child_timeout`。Read-only eligibility 与 Pi 的 one-foreground-child 调度限制是两回事:只读调查可同时存在多个待派发候选,但实际执行仍逐个 foreground child 串行消费,不得把多个 foreground Agent 假定为并发 batch。该规则不改变 Kernel authority Review 的显式恢复协议。Child 永远不获得实现、Plan write、workflow mutation 或 QA closure authority。
|
|
108
108
|
|
|
109
109
|
If Kernel Review dispatch fails, the Parent does not call `submit_review`; the existing Review reservation and immutable evidence remain available for a later foreground retry. A malformed verdict may be corrected and resubmitted. A stale snapshot, explicit release, successful settlement, or session shutdown removes the reservation and evidence. There is no retry counter, dispatch receipt state machine, or provider-specific recovery path.
|
|
110
110
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: imm-agent-doc-maintain
|
|
3
|
-
description: Use
|
|
3
|
+
description: Use when the user explicitly requests Immune-Brain minimization of tracked AGENTS.md, CLAUDE.md, or GEMINI.md.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Immune-Brain: Agent Doc Maintain
|
|
@@ -37,6 +37,8 @@ commit.
|
|
|
37
37
|
|
|
38
38
|
## Ordered Maintenance Protocol
|
|
39
39
|
|
|
40
|
+
### Inventory and Manifest
|
|
41
|
+
|
|
40
42
|
1. **Establish repository safety.** Mutation requires a Git worktree. Only
|
|
41
43
|
tracked regular files named exactly `AGENTS.md`, `CLAUDE.md`, or `GEMINI.md`,
|
|
42
44
|
at the repository root or in nested tracked directories, are candidates.
|
|
@@ -100,6 +102,8 @@ commit.
|
|
|
100
102
|
repository scope or declared precedence are `BLOCKED`. Filename convention,
|
|
101
103
|
nesting, or guessed host behavior alone may not resolve a conflict.
|
|
102
104
|
|
|
105
|
+
### Manifest Approval and Recovery
|
|
106
|
+
|
|
103
107
|
7. **Produce one exact manifest.** `audit` mode stops after the manifest.
|
|
104
108
|
Mutation mode also stops until the literal user approves exact manifest
|
|
105
109
|
entries (for example, "all recommendations except 4 and 7"). Broad approval
|
|
@@ -107,6 +111,8 @@ commit.
|
|
|
107
111
|
no manifest is persisted. No fixed line, byte, percentage, or Token target
|
|
108
112
|
authorizes removal.
|
|
109
113
|
|
|
114
|
+
### Approved Mutation
|
|
115
|
+
|
|
110
116
|
8. **Revalidate and mutate minimally.** Re-read candidate bytes, Git status,
|
|
111
117
|
content hash, references, precedence evidence, and active scope immediately
|
|
112
118
|
before each approved change. Drift blocks that item. Never execute commands
|
|
@@ -116,6 +122,8 @@ commit.
|
|
|
116
122
|
basics, and explicit user requirements are never simplified away for
|
|
117
123
|
brevity.
|
|
118
124
|
|
|
125
|
+
### Verify and Report
|
|
126
|
+
|
|
119
127
|
9. **Verify and report.** Re-scan modified instruction relationships, local
|
|
120
128
|
pointer targets, duplicate retained meanings, unresolved conflicts,
|
|
121
129
|
source/package public-surface parity, existing focused documentation
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: imm-brainstorm
|
|
3
|
-
description: Use when
|
|
3
|
+
description: Use when the user explicitly requests Immune-Brain requirement clarification.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Immune-Brain: Brainstormer
|
|
@@ -17,46 +17,47 @@ This skill adheres to the **[BASELINE.md](BASELINE.md)**.
|
|
|
17
17
|
|
|
18
18
|
## Invocation modes
|
|
19
19
|
|
|
20
|
-
`imm-brainstorm`
|
|
21
|
-
|
|
20
|
+
`imm-brainstorm` owns proportionate clarification. Its modes share decision
|
|
21
|
+
provenance and authority constraints:
|
|
22
22
|
|
|
23
|
-
- `default`:
|
|
23
|
+
- `default`: resolve facts and delegated choices; ask only material unresolved decisions.
|
|
24
24
|
- `roundtable`: add bounded multi-role perspectives, visible agreement and
|
|
25
25
|
disagreement, and decision criteria.
|
|
26
26
|
- `adversarial`: add high-pressure security, migration, rollback, verification,
|
|
27
27
|
audit, and cross-boundary analysis.
|
|
28
28
|
|
|
29
|
-
All modes produce the same `brainstorm_framing` shape and
|
|
30
|
-
exhaustive frontier protocol. `roundtable` and `adversarial` are analysis lenses
|
|
29
|
+
All modes produce the same `brainstorm_framing` shape. `roundtable` and `adversarial` are analysis lenses
|
|
31
30
|
only when explicitly selected by the user; model task-type or risk
|
|
32
|
-
classification never selects them.
|
|
33
|
-
|
|
31
|
+
classification never selects them. Exhaustive interviewing requires an explicit
|
|
32
|
+
request for thorough interrogation; selecting a lens alone does not require it.
|
|
34
33
|
|
|
35
|
-
## Default
|
|
34
|
+
## Default clarification
|
|
36
35
|
|
|
37
|
-
Exhaustive means every sourced current-goal branch, not a fixed question count.
|
|
38
36
|
Every branch must trace to the current user request, repository evidence, or a
|
|
39
|
-
settled parent decision.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
37
|
+
settled parent decision. For a clear request, use a zero-question fast path when
|
|
38
|
+
no material decision or required fact remains unresolved. Do not seed or expand
|
|
39
|
+
a complete tree by default. Failure, compatibility, rollback, and risk questions
|
|
40
|
+
are relevant when evidence shows they can change the current outcome.
|
|
41
|
+
|
|
42
|
+
Classify each unresolved node as a repository fact, a delegated technical
|
|
43
|
+
choice, or a material user-owned decision. Resolve repository facts with
|
|
44
|
+
bounded, on-demand read-only evidence. If evidence is unavailable, record a
|
|
45
|
+
blocked fact and block only its dependent subtree; never turn the fact into a
|
|
46
|
+
user preference. A delegated technical choice is verifiable through existing
|
|
47
|
+
conventions, a reversible local probe, or an existing recorded decision when it
|
|
48
|
+
does not change the goal, scope, observable behavior, compatibility, risk
|
|
49
|
+
acceptance, or a protected effect; resolve it with evidence and record the
|
|
50
|
+
chosen assumption instead of asking. When a technical choice does change one of
|
|
51
|
+
those, it is material and belongs on the user frontier. Place every material
|
|
52
|
+
user-owned decision on the current frontier.
|
|
51
53
|
|
|
52
54
|
Ask every independent question on the complete currently unblocked frontier
|
|
53
55
|
together. Hold downstream questions until their prerequisites are decided.
|
|
54
56
|
Number every question, include grounded options and one recommended answer with
|
|
55
57
|
a short reason, and accept bulk approval of all recommendations with explicit
|
|
56
|
-
exceptions. Direct requirements and adopted recommendations settle
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
downstream branches.
|
|
58
|
+
exceptions. Direct requirements and adopted recommendations settle their
|
|
59
|
+
decisions without another approval round. After an answer, ask again only for
|
|
60
|
+
a newly evidenced material decision, not to manufacture further rounds.
|
|
60
61
|
|
|
61
62
|
Minimally clarify an ambiguous answer while independent branches continue. If a
|
|
62
63
|
later answer or new fact invalidates an earlier choice, reopen only that decision
|
|
@@ -64,13 +65,13 @@ delta and explain the new evidence. An explicit defer stops its subtree and is
|
|
|
64
65
|
recorded as `BR-DEFER-*`; if the subtree still changes the current Result,
|
|
65
66
|
interface, or compatibility, explain why it cannot be deferred.
|
|
66
67
|
|
|
67
|
-
Brainstorm finishes
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
Brainstorm finishes when the material decision frontier is empty and no blocked
|
|
69
|
+
fact prevents the current handoff. Independent framing may continue while a
|
|
70
|
+
dependent subtree is blocked. If the user
|
|
70
71
|
stops early, record every open node as `BR-Q-*` and do not mark the framing
|
|
71
72
|
planning-ready.
|
|
72
73
|
|
|
73
|
-
When
|
|
74
|
+
When clarification completes, present a concise result-only summary as a
|
|
74
75
|
non-blocking correction window. Do not ask the user to reconfirm decisions
|
|
75
76
|
reflected without change. If the summary introduces or changes a
|
|
76
77
|
decision, ask for explicit confirmation of only that decision delta
|
|
@@ -79,16 +80,29 @@ confirms a proposed direction or scope. Persist only final decisions: map them
|
|
|
79
80
|
to `BR-REQ-*`, `BR-DEC-*`, `BR-OUT-*`, `BR-DEFER-*`, and resolved `BR-Q-*`
|
|
80
81
|
manifest entries; do not copy the question transcript into repository artifacts.
|
|
81
82
|
|
|
83
|
+
## Explicit exhaustive interrogation
|
|
84
|
+
|
|
85
|
+
Read this section only when the user explicitly requests thorough or exhaustive
|
|
86
|
+
interrogation. Exhaustive means every sourced current-goal branch, not a fixed
|
|
87
|
+
question count. Seed the fixed framing roots: goal, beneficiary and scenario,
|
|
88
|
+
current state, desired behavior, scope and non-goals, constraints, failure and
|
|
89
|
+
edge behavior, compatibility and migration, success and Verification, and
|
|
90
|
+
deferred items. Recompute the tree after every response and traverse newly
|
|
91
|
+
unlocked downstream branches. Adoption closes current nodes, not unexplored
|
|
92
|
+
branches. Resolve facts and delegated choices locally; ask material user-owned
|
|
93
|
+
decisions. Stop when the sourced tree is traversed and its material frontier is
|
|
94
|
+
empty, or report remaining blocked/open nodes if the user stops early.
|
|
95
|
+
|
|
82
96
|
## Workflow Rules
|
|
83
97
|
|
|
84
|
-
- **Trigger Shape**:
|
|
85
|
-
- **Decision Provenance**:
|
|
98
|
+
- **Trigger Shape**: Explicit Brainstorm entry permits proportionate clarification, including a zero-question handoff for a clear request. Read the exhaustive protocol only on an explicit request for thorough interrogation. Do not add a second confirmation for an unchanged final summary.
|
|
99
|
+
- **Decision Provenance**: Investigate evidenced current-goal uncertainty. A concrete scenario is relevant when the request, repository, or a settled parent decision makes it material; do not invent speculative future needs.
|
|
86
100
|
- **Dependency-Aware Rounds**: Ask every independent question on the complete currently unblocked frontier together. Ask fewer questions only because dependencies keep downstream branches blocked, never because of an arbitrary question budget.
|
|
87
101
|
- **Read-only by default**: Inspect context and summarize the problem. do not implement inside this skill.
|
|
88
102
|
- **Handoff**: Write concise design notes under `docs/brainstorms/` only if explicitly requested.
|
|
89
103
|
- **Handoff Manifest**: When framing is stable, user-confirmed, and routes to planner, include a compact `Brainstorm manifest` with stable IDs for every planner-relevant item: `BR-REQ-*` for confirmed requirements, `BR-DEC-*` for confirmed decisions, `BR-OUT-*` for non-goals, `BR-DEFER-*` for explicitly deferred items, and `BR-Q-*` for open questions. The manifest is the closed-world handoff; the planner must account for every ID instead of relying on prose memory.
|
|
90
|
-
- **Default Next Route**: Route to `imm-planner`
|
|
91
|
-
- **Subagents**:
|
|
104
|
+
- **Default Next Route**: Route to `imm-planner` when the material frontier is empty, no required fact blocks the handoff, and every material user decision is settled by a direct requirement, explicit answer, or adopted recommendation. An unchanged final summary is a correction window, not another gate. If Brainstorm introduces a new decision, ask for that delta and do not name `imm-planner` as the current next skill.
|
|
105
|
+
- **Subagents**: Only when optional research is needed, read Research Dispatch and its shared dispatch reference. Default to inline evidence gathering; do not load dispatch instructions merely because Brainstorm was invoked.
|
|
92
106
|
- **Rejected Decision Evidence**: Use on-demand rejected-decision evidence instead of a global preflight. When a live branch resembles a rejected decision, resolve its recorded reason and optional `reconsider_if` conditions through code/docs inspection before asking the user. Treat each `reconsider_if` list item as an independently sufficient trigger (OR semantics): if available evidence satisfies none, keep the rejection as a current constraint or non-goal without re-litigation; if evidence satisfies one, reopen the decision and cite the condition plus changed evidence; if a condition cannot be resolved, ask only for that concrete missing fact. When `reconsider_if` is absent, preserve the backwards-compatible "what has changed?" fallback after inspection. When `rejection_reason` is absent, inspect an explicit rejection-reason section in the body; if no reason exists, report the metadata gap without inventing a reason or reconsideration condition.
|
|
93
107
|
- **CONTEXT.md Awareness**: When the user uses vague or conflicting domain terms, check `CONTEXT.md` at the repo root. If a canonical term exists, surface the conflict: "CONTEXT.md defines X as Y, but you seem to mean Z — which is it?" If CONTEXT.md does not exist, note the gap and recommend the planner create it during planning. Use CONTEXT.md vocabulary in the output artifact when available.
|
|
94
108
|
- **Discovery Protocol**: Before broad searching, read `CONTEXT.md` `## Architecture Map` and the active `.imm/memory/current_iteration.json` step `discovery_cache` when present. Use matching `docs/solutions/` `key_files` frontmatter as the pattern layer. If these pointers are missing or stale, note the discovery gap in the framing instead of compensating with unbounded search.
|
|
@@ -135,6 +149,6 @@ Default user-facing shape: `Conclusion -> Scope -> Next Action`. For the normal
|
|
|
135
149
|
|
|
136
150
|
## Next Action
|
|
137
151
|
|
|
138
|
-
- Gate: The
|
|
152
|
+
- Gate: The material frontier is empty; no required fact blocks the handoff; every material user decision is settled by a direct requirement, explicit answer, or adopted recommendation; and the result-only summary introduces no unconfirmed decision delta. **If any required clarification remains unanswered, you MUST NOT proceed to planning or suggest the next skill.** **If a decision delta is still unconfirmed, you MUST NOT proceed to planning, must not name a next skill, and should ask the user to confirm only that delta.**
|
|
139
153
|
- If gates pass: suggest `imm-planner` with a one-line reason.
|
|
140
154
|
- If gates are not met: state which questions or decision deltas remain open; do not name a next skill and wait for the user's answer.
|