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.
Files changed (31) hide show
  1. package/README.md +45 -0
  2. package/package.json +1 -1
  3. package/plugins/immune-brain/.claude-plugin/plugin.json +1 -1
  4. package/plugins/immune-brain/.pi-extension/imm-canary-work.ts +31 -2
  5. package/plugins/immune-brain/.pi-extension/pi-canary-interaction.ts +38 -10
  6. package/plugins/immune-brain/dist/BASELINE.md +48 -15
  7. package/plugins/immune-brain/dist/claude/mcp-server.mjs +20 -10
  8. package/plugins/immune-brain/dist/docs/reference/planning-quality-gate.md +1 -1
  9. package/plugins/immune-brain/dist/docs/reference/subagent-dispatch-protocol.md +1 -1
  10. package/plugins/immune-brain/dist/imm-agent-doc-maintain.md +9 -1
  11. package/plugins/immune-brain/dist/imm-brainstorm.md +49 -35
  12. package/plugins/immune-brain/dist/imm-doc-prune.md +7 -1
  13. package/plugins/immune-brain/dist/imm-loop.md +23 -11
  14. package/plugins/immune-brain/dist/imm-planner.md +65 -28
  15. package/plugins/immune-brain/dist/imm-pr-fix.md +6 -2
  16. package/plugins/immune-brain/dist/role-prompts/executor.md +18 -10
  17. package/plugins/immune-brain/dist/role-prompts/pr-fix.md +5 -2
  18. package/plugins/immune-brain/runtime/assurance/verification.ts +13 -2
  19. package/plugins/immune-brain/runtime/github_issue_tracker.ts +1018 -17
  20. package/plugins/immune-brain/runtime/kernel/canary_application.ts +7 -1
  21. package/plugins/immune-brain/runtime/kernel/reducer.ts +3 -1
  22. package/plugins/immune-brain/runtime/plugin_version.ts +1 -1
  23. package/plugins/immune-brain/runtime/prompts/executor.md +18 -10
  24. package/plugins/immune-brain/runtime/prompts/pr-fix.md +5 -2
  25. package/plugins/immune-brain/skills/BASELINE.md +48 -15
  26. package/plugins/immune-brain/skills/imm-agent-doc-maintain/SKILL.md +20 -4
  27. package/plugins/immune-brain/skills/imm-brainstorm/SKILL.md +24 -64
  28. package/plugins/immune-brain/skills/imm-doc-prune/SKILL.md +18 -3
  29. package/plugins/immune-brain/skills/imm-loop/SKILL.md +20 -6
  30. package/plugins/immune-brain/skills/imm-planner/SKILL.md +35 -8
  31. 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "immune-brain",
3
- "version": "3.6.5",
3
+ "version": "3.6.6",
4
4
  "description": "Immune-Brain agent skill system",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "immune-brain",
3
- "version": "3.6.5",
3
+ "version": "3.6.6",
4
4
  "description": "Immune-Brain Claude Code Host: native Enrollment, QA, Review, and Kernel settlement.",
5
5
  "author": {
6
6
  "name": "Immune-Brain Team"
@@ -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) writeFileSync(sidecar, `${JSON.stringify(operation.next_intent, null, 2)}\n`);
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) writeFileSync(sidecar, priorBytes);
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 { Container, SelectList, Text, type Component, type SelectItem } from "@earendil-works/pi-tui";
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.length <= max ? value : `${value.slice(0, max - 1)}…`;
530
+ return truncateToWidth(value, max, "…");
506
531
  }
507
532
 
508
533
  function boundedMiddle(value: string, max: number): string {
509
- if (value.length <= max) return value;
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
- return `${value.slice(0, start)}…${value.slice(-(visible - start))}`;
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
- - Load detailed workflow text from `dist/` only on invocation.
6
- - Ask only when missing information changes outcome or risk.
7
- - Keep edits inside the user-requested Direct scope or the active Managed step boundary.
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
- - Use shallow discovery first.
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 — may be dispatched in parallel.
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 under the Direct completion contract above.
103
- - A Managed Step is ready to execute only when the target result, boundary, and
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 Step is closable only when execution evidence proves the recorded
106
- verification path and the active boundary still matches the Plan.
107
- - Managed scope changes, missing evidence, or structural mismatch return to
108
- `imm-planner` instead of being hidden inside execution or QA.
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 Step question.
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.5";
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
- real = realpathSync2(executable);
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 = spawnSync("git", ["-C", root, ...args], {
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 = spawnSync("git", ["-C", root, ...args], {
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
- return ref.path === `docs/plans/${intent.task_id}.intent.json` && ref.content_hash === canonicalIntentHash(intent);
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 spawnSync2 } from "node:child_process";
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 = spawnSync2("git", ["-C", root, "rev-parse", "--verify", "HEAD^{commit}"], {
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. Every new or revised Spec records `**Diagram decision**: required|not_required` and a non-empty `**Diagram reason**:`. A `required` decision must include Mermaid; `not_required` explains why prose is sufficient.
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`。该规则不改变 Kernel authority Review 的显式恢复协议。Child 永远不获得实现、Plan write、workflow mutation 或 QA closure authority。
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 to minimize tracked AGENTS.md, CLAUDE.md, and GEMINI.md files to necessary non-discoverable context after an explicit, hash-bound, user-approved manifest; never installs or validates project contracts.
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 clarifying scope.
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` is the canonical exhaustive clarification owner. Its modes share
21
- one interaction protocol:
20
+ `imm-brainstorm` owns proportionate clarification. Its modes share decision
21
+ provenance and authority constraints:
22
22
 
23
- - `default`: traverse the full sourced design tree.
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 use the same
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. Failure, edge, rollback, compatibility,
33
- migration, and risk branches remain part of `default` traversal.
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 exhaustive decision tree
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. Seed the fixed framing roots: goal, beneficiary and
40
- scenario, current state, desired behavior, scope and non-goals, constraints,
41
- failure and edge behavior, compatibility and migration, success and
42
- Verification, and deferred items. Expand them dynamically after every answer.
43
- Do not use materiality, task type, or risk classification to decide whether a
44
- sourced user decision is worth asking.
45
-
46
- Classify each unresolved node only as a repository fact or a user-owned decision.
47
- Resolve facts with bounded, on-demand read-only evidence. If evidence is
48
- unavailable, record a blocked fact and block only its dependent subtree; never
49
- turn the fact into a user preference. Place every sourced user decision on the
50
- current frontier.
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 only the
57
- current nodes; they never complete the Brainstorm session by themselves.
58
- Recompute the tree after every response and continue through newly unlocked
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 only when the frontier is empty and no blocked fact prevents
68
- traversal. A zero-question fast path is valid only when the complete seeded and
69
- dynamically expanded tree contains no unresolved user decision. If the user
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 traversal completes, present a concise result-only summary as a
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**: Use when product framing is still needed. Direct Planner entry remains available for a clear request, but once the user invokes Brainstorm, do not short-circuit its exhaustive traversal because an initial frame appears clear. Do not add a second confirmation for an unchanged final summary.
85
- - **Decision Provenance**: Traverse every sourced current-goal branch. A concrete scenario is a branch when the request, repository, or a settled parent decision makes it relevant; do not invent speculative future needs.
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` only when the full frontier is empty, no blocked fact prevents traversal, and every sourced user decision is settled by a direct requirement, explicit answer, or adopted recommendation. Those inputs close their nodes but never the session. 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.
91
- - **Subagents**: Follow the Adaptive Cache-First Route in `docs/reference/subagent-dispatch-protocol.md`: classify the task, check cache-first discovery pointers, and carry subagent split pressure forward only when the Cost-Based Subagent Gate says parallel research is worth the coordination cost. User explicitly wants solo fallback when split is impossible.
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 exhaustive frontier is empty; no blocked fact prevents traversal; every sourced 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 requested 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.**
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.