immune-brain 5.1.2 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +13 -6
  2. package/README.zh-CN.md +12 -5
  3. package/package.json +1 -1
  4. package/plugins/immune-brain/.claude-plugin/plugin.json +1 -1
  5. package/plugins/immune-brain/.pi-extension/imm-canary-enroll.ts +14 -2
  6. package/plugins/immune-brain/.pi-extension/imm-canary-work.ts +73 -0
  7. package/plugins/immune-brain/.pi-extension/imm-unattended-batch.ts +15 -2
  8. package/plugins/immune-brain/agents/immune-brain-reviewer.md +5 -0
  9. package/plugins/immune-brain/dist/BASELINE.md +6 -2
  10. package/plugins/immune-brain/dist/claude/mcp-server.mjs +429 -140
  11. package/plugins/immune-brain/dist/imm-brainstorm.md +3 -3
  12. package/plugins/immune-brain/dist/imm-doc-prune.md +2 -1
  13. package/plugins/immune-brain/dist/imm-planner.md +33 -37
  14. package/plugins/immune-brain/dist/imm-run.md +14 -3
  15. package/plugins/immune-brain/dist/imm-test-prune.md +233 -0
  16. package/plugins/immune-brain/dist/registry.yaml +9 -0
  17. package/plugins/immune-brain/dist/role-prompts/code-review.md +5 -0
  18. package/plugins/immune-brain/dist/role-prompts/executor.md +8 -0
  19. package/plugins/immune-brain/hooks/hooks.json +10 -1
  20. package/plugins/immune-brain/runtime/assurance/alias_file.ts +24 -0
  21. package/plugins/immune-brain/runtime/assurance/phase_entry.ts +133 -0
  22. package/plugins/immune-brain/runtime/claude/interaction.ts +5 -1
  23. package/plugins/immune-brain/runtime/claude/lane_guard.ts +197 -3
  24. package/plugins/immune-brain/runtime/claude/mcp_server.ts +21 -3
  25. package/plugins/immune-brain/runtime/claude/review_host.ts +6 -6
  26. package/plugins/immune-brain/runtime/plugin_version.ts +1 -1
  27. package/plugins/immune-brain/runtime/prompts/code-review.md +5 -0
  28. package/plugins/immune-brain/runtime/prompts/executor.md +8 -0
  29. package/plugins/immune-brain/skills/BASELINE.md +6 -2
  30. package/plugins/immune-brain/skills/imm-brainstorm/SKILL.md +6 -4
  31. package/plugins/immune-brain/skills/imm-planner/SKILL.md +8 -7
  32. package/plugins/immune-brain/skills/imm-run/SKILL.md +2 -1
  33. package/plugins/immune-brain/skills/imm-test-prune/SKILL.md +28 -0
  34. package/plugins/immune-brain/skills/registry.yaml +9 -0
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: imm-brainstorm
3
- description: Use when the user explicitly requests Immune-Brain requirement clarification.
3
+ description: Use when the user asks to clarify or explore requirements before Immune-Brain planning.
4
4
  ---
5
5
 
6
6
  # Immune-Brain: Brainstormer
@@ -138,7 +138,7 @@ Runtime helpers: `imm_core.buildBrainstormEnsembleRequest`, `imm_core.buildBrain
138
138
 
139
139
  A Brainstorm ensemble is optional advisory-only framing input, not a vote and not a child-owned decision. The default roles are clarify scope, divergent options, minimal solution, and risk review.
140
140
 
141
- All Brainstorm ensemble children are advisory-only with `tool_policy: no tools`; they do not edit code, write Specs, write Plans, mutate workflow state, or close QA. The parent `imm-brainstorm` owns final framing synthesis, Brainstorm manifest IDs, and decision-delta confirmation. Final Spec and Plan authority stays with `imm-planner`. Routine Managed enrollment uses the current Host's native confirmation bound to the TaskIntent revision, content hash, and preparation digest as the single authority gate; Enrollment validates descriptor structure without executing acceptance descriptors, deterministic QA executes them after implementation, and the routine task proceeds without a second human stop. A later authority-gate failure stays fail-closed in the current Host and reports exactly one same-Host recovery action; Brainstorm must never recommend another Host, worktree, or unmanaged implementation as a fallback.
141
+ All Brainstorm ensemble children are advisory-only with `tool_policy: no tools`; they do not edit code, write Specs, write Plans, mutate workflow state, or close QA. The parent `imm-brainstorm` owns final framing synthesis, Brainstorm manifest IDs, and decision-delta confirmation. Final Spec and Plan authority stays with `imm-planner`. Neither Brainstorm nor the Planner invokes Enrollment: the user launches `imm-planner` after framing and `imm-run` after planning, and a confirmation of a framing or a plan starts neither. Routine Managed enrollment is the first step of an explicit `imm-run` entry and uses the current Host's native confirmation bound to the TaskIntent revision, content hash, and preparation digest as the single authority gate; Enrollment validates descriptor structure without executing acceptance descriptors, and deterministic QA executes them after implementation. A later authority-gate failure stays fail-closed in the current Host and reports exactly one same-Host recovery action; Brainstorm must never recommend another Host, worktree, or unmanaged implementation as a fallback.
142
142
 
143
143
  Pi's adapter may consume `brainstorm_ensemble` dispatch JSON to prepare advisory Pi subagent envelopes, but envelope construction is not child execution and does not transfer framing authority. Pi launches one foreground Agent at a time, consumes its direct result, and re-evaluates the remaining dispatch budget before launching another candidate. Runtime does not call any agent, poll or recover background work, mutate state, or own final Spec/Plan authority. Pi subagent children remain no-tools advisory candidates; the parent `imm-brainstorm` collects outputs before synthesis.
144
144
 
@@ -171,5 +171,5 @@ Default user-facing shape: `Conclusion -> Scope -> Next Action`. For the normal
171
171
  ## Next Action
172
172
 
173
173
  - 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.**
174
- - If gates pass: suggest `imm-planner` with a one-line reason.
174
+ - If gates pass: suggest `imm-planner` with a one-line reason and stop. The user launches it; Brainstorm never enters `imm-planner` or `imm-run` on its own and never invokes Enrollment.
175
175
  - 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.
@@ -117,7 +117,8 @@ no persistent report, and no automatic commit.
117
117
 
118
118
  This Skill may modify or delete approved documentation, explicit translation
119
119
  or generated mirrors, documentation sync manifests, and tests whose only
120
- behavior is asserting document existence or obsolete wording. It must stop
120
+ behavior is asserting document existence or obsolete wording; test structure and
121
+ behavioral coverage belong to `imm-test-prune`. It must stop
121
122
  when completion requires runtime behavior, business-test semantics, package
122
123
  exports, public API, credentials, network writes, Git history rewriting, or
123
124
  any Managed authority mutation.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: imm-planner
3
- description: Use when the user explicitly requests Immune-Brain Spec and TaskIntent planning.
3
+ description: Use when the user asks for an Immune-Brain Spec, Plan, or TaskIntent for a repository change.
4
4
  ---
5
5
 
6
6
  # Immune-Brain: Planner
@@ -9,24 +9,24 @@ This skill adheres to the **[BASELINE.md](BASELINE.md)**.
9
9
 
10
10
  ## Managed Request Routing
11
11
 
12
- `imm-planner` is entered explicitly by the user for a clear repository mutation.
13
- Ordinary host input does not invoke this Skill through natural-language routing.
12
+ `imm-planner` starts on the user's request for a Spec, Plan, or TaskIntent for a
13
+ repository change, by slash command or in natural language. A request that asks
14
+ for none of these stays host-native, and `imm-run` starts only from a
15
+ literal-user entry. A model-entered Planner outside an enrolled task ends the
16
+ session's run entry, so Enrollment needs a fresh `imm-run` entry.
14
17
  An active Assurance projection remains authoritative and is resumed only through
15
- an explicit `imm-run` entry; explicit Planner entry owns planning and the later
16
- native Enrollment gate.
17
-
18
- Plan-only output remains non-authoritative. Planner creates or validates a
19
- candidate Spec/TaskIntent. Planner may request the native Enrollment gate;
20
- only that gate grants execution authority. Explicit Plan-only requests stop after returning the
21
- planning artifacts. A later literal-user request to start Enrollment is a
22
- non-authoritative execution trigger: invoke the native Enrollment gate directly,
23
- without asking for chat pre-confirmation. For a clear mutation request that
24
- already includes execution, invoke that gate as soon as the candidate is
25
- validated and Git-tracked. Literal-user confirmation in the current Host's
26
- native gate remains the authority boundary. A gate failure preserves candidate
27
- artifacts and reports its reason plus exactly one same-Host recovery action; it
28
- must never recommend another Host, worktree, Direct Path, unmanaged
29
- implementation, or automatic retry. Fast-Track may compress the same phases but
18
+ an explicit `imm-run` entry; Planner entry owns planning only.
19
+
20
+ Planner output remains non-authoritative. Planner creates or validates a
21
+ candidate Spec/TaskIntent and never invokes the native Enrollment gate;
22
+ only that gate grants execution authority, and it opens only as the first step
23
+ of a literal-user `imm-run` entry. Every Planner request stops after returning
24
+ the validated planning artifacts, including a request that also asks for
25
+ execution: report the candidate and name a literal-user `imm-run` entry as the
26
+ only next step. A design confirmation, a generic continuation, or a request to
27
+ start Enrollment received inside the Planner is not an `imm-run` entry and
28
+ opens no gate. Literal-user confirmation in the current Host's
29
+ native gate remains the authority boundary. Fast-Track may compress the same phases but
30
30
  cannot bypass that boundary, QA, Review, authorization, or completion.
31
31
 
32
32
  ## Clarification supplement
@@ -119,13 +119,12 @@ Enrollment.
119
119
 
120
120
  Host identity is implicit and never a planning input. The production boundary
121
121
  that turns a Git-tracked TaskIntent draft into managed execution authority is
122
- the current Host's native Enrollment gate. Invoke that Host integration
123
- directly when the route is ready; do not ask for chat pre-confirmation. The
124
- single literal-user decision is bound to the TaskIntent revision, content hash,
125
- and preparation digest. Enrollment validates the intent, Git ownership, scope,
126
- workspace claim, and final authority preconditions without executing acceptance
127
- descriptors. A routine task proceeds from that single confirmation through
128
- enrollment, execution and QA without a second human stop.
122
+ the current Host's native Enrollment gate. `imm-run` invokes that Host
123
+ integration as the first step of a literal-user entry; the Planner never does.
124
+ The single literal-user decision is bound to the TaskIntent revision, content
125
+ hash, and preparation digest. Enrollment validates the intent, Git ownership,
126
+ scope, workspace claim, and final authority preconditions without executing
127
+ acceptance descriptors.
129
128
 
130
129
  **Automatic policy activation**
131
130
 
@@ -327,11 +326,9 @@ prompt digests never belong in this external handoff. If
327
326
  Local mode performs zero GitHub operations.
328
327
 
329
328
  The batch result includes an execution recommendation: the first unblocked Task,
330
- a stable dependency order, and parallel groups. For a plan-only request, report
331
- that recommendation and stop. For a request that includes execution, invoke the
332
- native Enrollment gate for the recommended first TaskIntent after successful
333
- publication; do not ask for another chat confirmation. GitHub selection never
334
- bypasses Enrollment.
329
+ a stable dependency order, and parallel groups. Report that recommendation and
330
+ stop; the user enrolls the recommended first TaskIntent through a literal-user
331
+ `imm-run` entry. GitHub selection never bypasses Enrollment.
335
332
 
336
333
  Tracker output is observation, never authority. Before the Planner returns, its
337
334
  GitHub carrier outcome must be exactly one of: `tracker_associated` after the
@@ -435,7 +432,7 @@ it, and structural Enrollment readiness is not proof that a descriptor executed.
435
432
  - **Planning granularity**: Keep a coherent outcome together when acceptance, risk, rollback, and authority can settle together. Use the TaskIntent decomposition rules below for independent outcomes. File count, tokens, compactions, elapsed time, and review rounds are evidence for judgment, not universal gates.
436
433
  - **Historical artifacts**: v3 prose Plan mutation is retired. `imm-plan` is a read-only validator for archived Plans; create no new Roadmap, Phase, successor Plan, or State Ledger.
437
434
  - **Risk-Triggered Exploration**: Before authoring a TaskIntent, resolve only unknowns that could change scope, design, or verification using targeted read-only probes. Internal `arch-explorer` and explicit-lens `advisory-reviewer` roles return evidence without writing the Spec, TaskIntent, or workflow state. Stop probing when outcome, scope, and verification are concrete. Do not use retired Plan termination flags to classify discovery failures.
438
- - **Simplicity**: Apply the BASELINE Workflow Activation gate first. Non-mutating host-native work creates no Planner artifact. Explicit Immune-Brain Skill entry starts this Planner phase; ordinary host input does not invoke it through natural-language routing. Create one coherent outcome instead of expanding ceremony.
435
+ - **Simplicity**: Apply the BASELINE Workflow Activation gate first. Non-mutating host-native work creates no Planner artifact. The user's request for a Spec, Plan, or TaskIntent, by slash command or in natural language, starts this Planner phase; other host input stays host-native. Create one coherent outcome instead of expanding ceremony.
439
436
  - **Design-Depth Classification**: Classify change design risk with the smallest sufficient tier: **Low risk** (copy, configuration, trivial rename, or contained local fix) may omit a separate Technical Design; **Medium risk** (non-trivial single-module behavior or internal contract) records affected components, decisions, invariants, failure behavior, and verification implications; **High risk** (cross-module/API/data-flow/state-machine, security, migration, concurrency, architecture ownership, cross-runtime/package-contract, or persisted-state work) records boundaries, interfaces or flow, alternatives, invariants, rollback/compatibility, and verification implications. Medium and High risk require Technical Design in the Spec. Do not classify a change as Low risk when it has a contract, ownership, security, persistence, compatibility, or multi-component concern. Every new or revised Spec records `**Design risk**: Low|Medium|High` with an adjacent rationale.
440
437
  - **Design-view selection**: For Medium and High risk, select every materially relevant technical-design view from architecture layers, service/component interfaces, data flow, state transitions, and temporal sequence. Record a short `Design views` statement naming the selected views and why any omitted view cannot affect the design. Do not write empty architecture, interface, data-flow, state, or sequence sections. Low risk remains concise and may omit Technical Design. When a selected view is recorded, also record its required decision content: architecture layers need layer responsibilities, dependency direction, ownership, and prohibited coupling; service/component interfaces need inputs, outputs, errors, compatibility/versioning, and caller/callee ownership; data flow needs source, transformations, validation, destination, and failure handling; state transitions need states, legal transitions, trigger, invariant, terminal ownership, and recovery; temporal sequence needs ordered interactions, authority at each point, interruption behavior, and idempotency.
441
438
  - **Technical Design Authority**: The Spec is the single Technical Design baseline. TaskIntent acceptance and scope reference the applicable design decisions or invariants without copying Technical Design prose. If discovery invalidates the baseline, stop execution and return to Planner to update the Spec and decide whether `replan` is required. TaskIntent and Initiative text do not duplicate Technical Design prose or become a prose Plan substitute.
@@ -520,7 +517,7 @@ states principles; enumeration of cases belongs in tests.
520
517
 
521
518
  ## Planning Rules
522
519
 
523
- - **Entry Contract**: Use when Spec/TaskIntent planning is needed. An already enrolled owner remains on its current Kernel authority and resumes only through explicit `imm-run`; a validated candidate still needs native Enrollment.
520
+ - **Entry Contract**: Use when Spec/TaskIntent planning is needed. An already enrolled owner remains on its current Kernel authority and resumes only through explicit `imm-run`; a validated candidate still needs native Enrollment, which only an explicit `imm-run` entry opens.
524
521
  - **Output Language Gate**: Before writing or revising any Spec or Plan, read the project output language policy from `AGENTS.md`, `IMMUNE.md`, or Immune-Brain plugin config. Default Spec and Plan prose to English unless the current user request, project instructions, or host/user preference contains an explicit document-language instruction. A reply-language instruction does not change document language. Keep schema fields, CLI commands, file paths, code identifiers, enum values, JSON keys, and canonical terms such as `Step`, `Plan`, `Spec`, `Verification`, `Discovery cache`, and `Devil's Advocate Audit` literal.
525
522
  - **Clarification Supplement**: If an upstream `imm-brainstorm` manifest exists, verify that every `BR-Q-*` item is resolved and every confirmed framing decision is represented; must not repeat, reopen, or rewrite confirmed decisions. Ask only a focused omission, repository-conflict, or invalidated-assumption delta tied to concrete evidence. Resolve a local delta here; return to `imm-brainstorm` when it reopens multiple product branches or changes the overall goal or Scope. Finalization requires no unresolved supplement and no unconfirmed decision introduced by Planner.
526
523
  - **Planning Bootstrap**: When no upstream `imm-brainstorm` manifest exists, preserve Direct Planner entry by resolving repository facts and deriving ordinary technical choices. An already-clear request takes the zero-question fast path to a non-blocking correction summary. Discovery of an unresolved user-owned goal, user, scope, behavior, compatibility preference, risk acceptance, or success criterion returns to `imm-brainstorm`; Planner does not convert product uncertainty into a silent assumption or duplicate Brainstorm's interview.
@@ -601,7 +598,7 @@ optional advisory dispatch fails, continue inline and record the reason.
601
598
 
602
599
  - **Allowed**: Write a TaskIntent. Add a Spec only for complex work. Activate an absent routing policy under Kernel TaskIntent Routing. Initiative planning carriers and necessary domain vocabulary.
603
600
  - **Blocked**: Implementation edits, direct Kernel-store writes, enrolled intent overwrites, and QA/Review decisions.
604
- - **Workflow guard**: Execution continues through native Enrollment and explicit `imm-run`. Planner owns design and decomposition, not execution authority.
601
+ - **Workflow guard**: Execution starts only from a literal-user `imm-run` entry, whose first step is native Enrollment. Planner owns design and decomposition, never Enrollment or execution authority.
605
602
 
606
603
  ## Output artifact
607
604
 
@@ -649,11 +646,10 @@ a State Ledger. Keep historical Plan validation strictly read-only.
649
646
  - Validate every candidate through `imm-kernel intent validate <path> --json` after authoring and staging. Require `valid: true` and `enrollment_ready: true` before Enrollment. When `git_base_initialization_required: true`, report that the existing native Enrollment confirmation includes an empty root commit; leave initialization to the Host. An invalid `git_base` blocks Enrollment and requires Git repair.
650
647
  - For complex work, verify Spec design metadata, document language, reference closure, concrete descriptor paths, and complete Brainstorm traceability before handoff. Simple TaskIntent-only work verifies those properties on the Intent.
651
648
  - Enrollment validates descriptor structure only. Deterministic QA owns descriptor execution after implementation; planning does not run the acceptance suite.
652
- - Managed execution handoff is Git-tracked TaskIntent author/validate plus current-Host native Enrollment. Do not sync a v3 State Ledger or invoke a missing dispatcher.
649
+ - Managed execution handoff is Git-tracked TaskIntent author/validate; current-Host native Enrollment follows in `imm-run`. Do not sync a v3 State Ledger or invoke a missing dispatcher.
653
650
 
654
651
  ## Next Action
655
652
 
656
- - Gate: Reference closure and clarification are complete; every upstream `BR-*` item is represented; no unresolved user decision remains; Planner-introduced decision deltas are confirmed; the candidate is Git-tracked and validates with `valid: true` and `enrollment_ready: true`; each acceptance has concrete focused verification. Plan-only requests stop here.
657
- - If gates pass: for Kernel-managed work, invoke the current Host's native Enrollment Tool directly without chat pre-confirmation. Its single literal-user gate binds the TaskIntent revision, content hash, and preparation digest, validates Enrollment preconditions without executing acceptance descriptors, and enrolls the task to continue through `imm-run`.
658
- - If the native gate fails: preserve candidate artifacts and report the stable reason plus exactly one same-Host recovery action. Do not suggest another Host, worktree, Direct Path, unmanaged implementation, or automatic retry.
653
+ - Gate: Reference closure and clarification are complete; every upstream `BR-*` item is represented; no unresolved user decision remains; Planner-introduced decision deltas are confirmed; the candidate is Git-tracked and validates with `valid: true` and `enrollment_ready: true`; each acceptance has concrete focused verification. Plan-only requests stop here, and so does every other Planner request.
654
+ - If gates pass: report the validated candidate (and, for an Initiative, the recommended first Task) and name a literal-user `imm-run` entry as the only next step. Do not invoke the current Host's native Enrollment Tool: Enrollment is the first step of `imm-run`, and a confirmation of the plan is not that entry.
659
655
  - If gates are not met: state which validation failures, unresolved verification paths, or material decision deltas remain; do not name a next skill.
@@ -20,6 +20,17 @@ Host's `status` projection first and verify the exact active backend claim,
20
20
  TaskIntent, and TaskRecord. Invalid or contradictory projections fail closed. A
21
21
  candidate TaskIntent is not Enrollment authority.
22
22
 
23
+ Enrollment is the first step of an explicit `imm-run` entry and belongs to no
24
+ other Skill. When the entry finds no active claim, resolve the validated
25
+ candidate the user named (or the Planner's recommended first Task when the entry
26
+ names none and exactly one candidate fits), then invoke the current Host's
27
+ native Enrollment gate once, without chat pre-confirmation, and continue from
28
+ the returned projection. Planner and Brainstorm never open that gate; a
29
+ confirmation given to either is not this entry. A gate failure preserves the
30
+ candidate and reports its stable reason plus exactly one same-Host recovery
31
+ action; never recommend another Host, worktree, Direct Path, unmanaged
32
+ implementation, or automatic retry.
33
+
23
34
  Before the first Enrollment of a candidate TaskIntent, confirm the Planner
24
35
  returned `tracker_associated` — but only when the candidate belongs to an
25
36
  identified GitHub-carried Initiative. Standalone TaskIntents and Local
@@ -60,9 +71,9 @@ Before a child dispatch, read the [Subagent Dispatch Protocol](docs/reference/su
60
71
  Never load an internal role as a public Skill or spawn another loop process;
61
72
  the only exception is a Lane's Executor Host under
62
73
  [Lane Executor Supervision](#lane-executor-supervision).
63
- The standalone `imm-pr-fix`, `imm-doc-prune`, and `imm-doc-slim` are host-native
64
- maintenance entries, never dispatched as the Loop role. Internal `test-fixer`
65
- and `pr-fix` repairs remain bounded by the enrolled TaskIntent.
74
+ The standalone `imm-pr-fix`, `imm-doc-prune`, `imm-doc-slim`, and `imm-test-prune`
75
+ are host-native maintenance entries, never dispatched as the Loop role. Internal
76
+ `test-fixer` and `pr-fix` repairs remain bounded by the enrolled TaskIntent.
66
77
 
67
78
  ## Execution Loop
68
79
 
@@ -0,0 +1,233 @@
1
+ ---
2
+ name: imm-test-prune
3
+ description: Use when the user explicitly requests Immune-Brain audit or pruning of redundant, bloated, or orphaned tests.
4
+ ---
5
+
6
+ # Immune-Brain: Test Prune
7
+
8
+ Reduce test-suite bloat in one Git repository. The Skill works through explicit
9
+ invocation, a comprehensive test inventory, evidence-based candidate narrowing,
10
+ one exact user-approved manifest, and bounded test-only mutation that never
11
+ weakens a live guarantee. It is language- and runner-agnostic: it uses the
12
+ target repository's own test, coverage, and static-check commands. This is a
13
+ standalone host-native maintenance entry, not a Managed Path continuation and
14
+ not an `imm-run` internal-role dispatch.
15
+
16
+ ## Authority Boundary
17
+
18
+ This Skill restructures and prunes tests without creating or mutating
19
+ TaskIntent, TaskRecord, Kernel, Spec, or Plan authority. An already active
20
+ Managed task remains owned by `imm-run`. Read-only inventory and manifest
21
+ production remain available.
22
+
23
+ Classify each of the following candidates as `BLOCKED_ACTIVE_SCOPE` and
24
+ continue auditing unaffected candidates:
25
+ - a candidate overlapping the active TaskIntent `scope_hint`;
26
+ - a candidate named by an active acceptance descriptor's verification `argv`.
27
+
28
+ If the routing owner or scope cannot be read reliably, fail closed for
29
+ mutation. This Skill does not invoke `imm-doc-prune`. Tests whose only behavior
30
+ is asserting document existence or wording remain that Skill's job and are
31
+ reported as `DEFER_DOC_PRUNE`.
32
+
33
+ ## Invocation
34
+
35
+ Requires explicit invocation: `imm-test-prune` or `/imm-test-prune`. Ordinary
36
+ "is this test redundant?" questions and routine test maintenance during a
37
+ change stay host-native and do not enter this Skill.
38
+
39
+ - `imm-test-prune audit`: read-only. Produce the manifest and stop.
40
+ - `imm-test-prune`: produce the manifest, then wait for exact manifest
41
+ approval before any mutation.
42
+ - An optional path argument narrows inventory to the named test files or
43
+ directories. The evidence rules still read the whole repository.
44
+
45
+ No automatic invocation. No daemon, no cron, no CI gate, no allowlist, no
46
+ runtime, no persistent report, no dependency installation, and no automatic
47
+ commit.
48
+
49
+ ## Ordered Pruning Protocol
50
+
51
+ ### Inventory and Manifest
52
+
53
+ 1. **Establish repository safety.** Mutation requires a Git worktree. A
54
+ non-Git repository or an untracked candidate is audit-only. For each
55
+ candidate, record:
56
+ - path;
57
+ - blob/content hash;
58
+ - tracked status;
59
+ - candidate-local worktree status;
60
+ - line count;
61
+ - test-case count.
62
+
63
+ Unrelated dirty files do not block the run; a dirty candidate is `BLOCKED`.
64
+
65
+ 2. **Discover the repository's commands.** Read existing scripts, task files,
66
+ CI configuration, and runner configuration to identify the following,
67
+ without installing anything:
68
+ - the test command;
69
+ - its single-file and single-test selection syntax;
70
+ - its coverage command and report format;
71
+ - the static checks a contributor runs locally.
72
+
73
+ Record the result as the coverage capability:
74
+ - `isolated`: coverage can be collected for one selected test;
75
+ - `file`: coverage can be collected only for one test file;
76
+ - `unavailable`: no coverage tool is already configured or installed, or
77
+ collection fails.
78
+
79
+ Never add a coverage tool, plugin, or configuration to obtain coverage.
80
+
81
+ 3. **Record the baseline.** Run the discovered test command over the
82
+ inventoried scope once and record pass/fail per file and wall time. A file
83
+ already failing at baseline is `BLOCKED` for mutation and reported. This
84
+ Skill never repairs or deletes a failing test to make the suite green. When
85
+ coverage capability is not `unavailable`, also record baseline line
86
+ coverage for the source files the candidates exercise.
87
+
88
+ 4. **Inventory tests and support code.** Enumerate tracked test files,
89
+ fixtures, helpers, and snapshots. Exclude dependency, vendor, build-output,
90
+ and cache trees.
91
+
92
+ 5. **Classify test roles.**
93
+ - behavior: asserts runtime or public-surface behavior;
94
+ - documentation contract: asserts document existence, wording, links, or
95
+ sections;
96
+ - packaging and mirror consistency: asserts that registries, generated
97
+ output, and packaged copies agree;
98
+ - historical evidence: protects readers of frozen or archived records;
99
+ - `UNCLASSIFIED`: grouped, not interrogated file by file.
100
+
101
+ Historical-evidence and packaging-consistency tests are `KEEP` unless the
102
+ protected reader or consumer is proven retired.
103
+
104
+ 6. **Mechanically narrow candidates.**
105
+ - Find structurally identical cases that differ only in literal inputs.
106
+ - Find repeated setup blocks across cases or files.
107
+ - Find hard-coded lists that duplicate a canonical registry or manifest.
108
+ - Find assertions whose subject (symbol, path, command, or public surface)
109
+ no longer exists in current source.
110
+ - Find orphaned fixtures and helpers with no remaining importer.
111
+ - Find tests that assert private implementation detail where a
112
+ public-surface assertion already covers the same behavior.
113
+
114
+ 7. **Apply evidence rules.** Age, file length, test count, and intermittent
115
+ failure alone never prove a test redundant.
116
+
117
+ `DELETE` requires one of the following:
118
+ - **Retirement**: the protected behavior is retired, with the retiring
119
+ commit or a current owner showing it removed.
120
+ - **Subsumption**: a named surviving test covers the same behavior with
121
+ equal or stronger assertions, and coverage evidence supports it. With
122
+ `isolated` or `file` capability, the surviving test's covered lines must
123
+ be a superset of the removed test's covered lines. Collect this only for
124
+ candidate entries, at the finest available granularity.
125
+
126
+ Line coverage is necessary, not sufficient: the assertion comparison is
127
+ still required.
128
+
129
+ A subsumption claim is `UNVERIFIED` and not mutable when any of these holds:
130
+ - coverage capability is `unavailable`;
131
+ - collection fails;
132
+ - repeated runs disagree.
133
+
134
+ A `MERGE` that drops any case follows the same subsumption rule. `MERGE` and
135
+ `PARAMETERIZE` that keep every distinct input and assertion need no coverage
136
+ evidence.
137
+
138
+ `RELAX_TO_STRUCTURE` is allowed only where the asserted text is not a
139
+ machine contract consumed by code, a host, or a packaged surface.
140
+
141
+ 8. **Produce one exact manifest.** State the discovered commands and coverage
142
+ capability first. Classify each entry as one of:
143
+ - `MERGE`
144
+ - `PARAMETERIZE`
145
+ - `EXTRACT_HELPER`
146
+ - `DERIVE_FROM_SOURCE`
147
+ - `RELAX_TO_STRUCTURE`
148
+ - `DELETE`
149
+ - `KEEP`
150
+ - `BLOCKED`
151
+ - `BLOCKED_ACTIVE_SCOPE`
152
+ - `DEFER_DOC_PRUNE`
153
+ - `UNVERIFIED`
154
+
155
+ Each entry includes:
156
+ - evidence;
157
+ - the exact file, case, or helper action;
158
+ - for every `DELETE`, the retirement proof, or the surviving owner with its
159
+ coverage evidence;
160
+ - the expected change in case count and line count;
161
+ - the candidate hash.
162
+
163
+ Group `UNCLASSIFIED` files.
164
+
165
+ 9. **Gate mutation.** `audit` mode stops after the manifest. Mutation mode
166
+ also stops until the literal user approves exact manifest entries (for
167
+ example, "all recommendations except 4 and 7"). Broad approval such as
168
+ "clean up the tests" is insufficient. Interruption starts a fresh scan; no
169
+ manifest is persisted.
170
+
171
+ ### Approved Mutation
172
+
173
+ 10. **Revalidate and mutate minimally.** Before each approved change, re-read
174
+ the candidate bytes, Git status, importers, and active scope. Drift blocks
175
+ that item. Apply one manifest entry at a time, then run that entry's
176
+ focused tests before the next. A failing focused check stops further
177
+ mutation and leaves the inspectable diff.
178
+
179
+ ## Mutation Envelope
180
+
181
+ This Skill may modify, merge, parameterize, or delete approved test files,
182
+ fixtures, helpers, and snapshots, and may add shared helpers beside the
183
+ repository's existing test helpers. It must stop when completion requires
184
+ changing any of the following:
185
+ - production source;
186
+ - public API;
187
+ - package exports;
188
+ - registries or generated output;
189
+ - dependencies, lockfiles, or coverage configuration;
190
+ - credentials or network writes;
191
+ - Git history;
192
+ - any Managed authority mutation.
193
+
194
+ **Never weaken a live guarantee.** Never do any of the following to make a
195
+ check pass or to reduce counts:
196
+ - skip, focus, or mark a test pending;
197
+ - loosen an assertion's strength (exact to partial, equality to existence,
198
+ specific error to any error);
199
+ - widen a timeout;
200
+ - delete a negative assertion that still guards a live boundary.
201
+
202
+ Snapshot updates are allowed only for cases whose structure the approved entry
203
+ changed, never as a blanket refresh.
204
+
205
+ ## Verify and Report
206
+
207
+ 11. **Verify and report.**
208
+ - Re-run every touched test file plus the baseline scope, the discovered
209
+ static checks, and `git diff --check`.
210
+ - The baseline pass set must be preserved: every previously passing
211
+ behavior keeps a passing owner.
212
+ - When coverage capability is not `unavailable`, re-collect line coverage
213
+ for the baseline's source files. Any decrease blocks the run: name the
214
+ responsible entry and leave the diff for the user. Report coverage as
215
+ unavailable rather than inferring it.
216
+ - This Skill does not commit.
217
+ - Report only these sections:
218
+ - `Changed` (with entry IDs);
219
+ - `Deleted` (each with its retirement proof, or its surviving owner and
220
+ coverage evidence);
221
+ - `Blocked`;
222
+ - `Deferred to imm-doc-prune`;
223
+ - `Unverified`;
224
+ - `Delta` (case count, line count, wall time, and line coverage before
225
+ and after, or `coverage unavailable`);
226
+ - `Verification`;
227
+ - `Recovery: git log -- <path>`.
228
+
229
+ ## Recovery
230
+
231
+ Git history is the archive for removed tests. Every `DELETE` entry reports
232
+ `Recovery: git log -- <path>`. Untracked, dirty, baseline-failing, or non-Git
233
+ candidates are never mutated.
@@ -56,6 +56,15 @@ skills:
56
56
  output_artifacts: [maintain_report]
57
57
  next_actions: []
58
58
  boundary: Minimize tracked agent-instruction context after explicit manifest approval; no Managed authority mutation, contract installation, or reference-document creation.
59
+ - name: imm-test-prune
60
+ path: skills/imm-test-prune/SKILL.md
61
+ role: execute
62
+ title: Test Prune
63
+ role_class: repair
64
+ canonical: true
65
+ output_artifacts: [test_prune_report]
66
+ next_actions: []
67
+ boundary: Audit and prune redundant tests after explicit manifest approval; no Managed authority mutation, production-source change, or assertion weakening.
59
68
  - name: imm-retro
60
69
  path: skills/imm-retro/SKILL.md
61
70
  role: execute
@@ -26,6 +26,11 @@ material task-local maintenance risks. Pure naming, length, complexity
26
26
  thresholds, formatting, and design preference are not findings and must not
27
27
  cause style-only rework.
28
28
 
29
+ Test-suite growth is advisory, never blocking: note a delivered test that
30
+ duplicates an existing assertion, asserts only private implementation, or
31
+ leaves a test protecting behavior the change retired. Weakened or missing
32
+ tests for an acceptance remain blocking under the rules above.
33
+
29
34
  When a finding repeats an acceptance id or anchor that already produced rework in
30
35
  this task, do not file it as a fresh single-trigger defect. Name the invariant
31
36
  class it belongs to and state in `evidence.trigger` why the previously accepted
@@ -68,6 +68,14 @@ mock or hard-coded success, swallowed unexpected errors, missing validation at
68
68
  external trust boundaries, invented dependencies or APIs, unauthorized
69
69
  observable behavior changes, and production paths without a current caller.
70
70
  Do not weaken tests or hide an incomplete result to make Verification pass.
71
+
72
+ Keep the test suite lean. Each added test pins one acceptance invariant or
73
+ finding case at its public seam; do not mirror private calls, mock order or
74
+ internal return values that a public assertion already covers. Before adding a
75
+ test, search existing tests for the same behavior and extend or parameterize
76
+ them instead of duplicating setup. When the change retires or replaces a
77
+ behavior, update or delete the tests that protected it within scope and name
78
+ the retired behavior or continuing owner in Delivery Evidence.
71
79
  Treat naming, function length, parameter count, nesting, and abstraction taste
72
80
  as contextual signals, never as automatic failure thresholds.
73
81
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "description": "Observe Claude Code Review and session lifecycle for Immune-Brain, keep a batch Lane's file edits inside its Lane, and announce an active Managed task without resuming it. Hooks never mint authority.",
2
+ "description": "Observe Claude Code Review and session lifecycle for Immune-Brain, keep a batch Lane's file edits inside its Lane, require a literal-user phase entry before Enrollment, batch start or the imm-run Skill, and announce an active Managed task without resuming it. Hooks never mint authority.",
3
3
  "hooks": {
4
4
  "PreToolUse": [
5
5
  {
@@ -10,6 +10,15 @@
10
10
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/dist/claude/mcp-server.mjs\" --hook"
11
11
  }
12
12
  ]
13
+ },
14
+ {
15
+ "matcher": "Skill|mcp__.*immune-brain.*__(enroll|start_unattended_batch)",
16
+ "hooks": [
17
+ {
18
+ "type": "command",
19
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/dist/claude/mcp-server.mjs\" --hook"
20
+ }
21
+ ]
13
22
  }
14
23
  ],
15
24
  "UserPromptSubmit": [
@@ -0,0 +1,24 @@
1
+ // Reads one user command alias for phase entry recognition. An alias may be a
2
+ // symlink, so the size bound is taken from the opened file, never from the link.
3
+
4
+ import { closeSync, constants, fstatSync, openSync, readSync } from "node:fs";
5
+
6
+ export const MAX_ALIAS_BYTES = 64 * 1024;
7
+
8
+ /** The alias body, or null when it is absent, not a regular file, or over the bound. */
9
+ export function readAliasFile(path: string, maxBytes = MAX_ALIAS_BYTES): string | null {
10
+ let fd: number;
11
+ try { fd = openSync(path, constants.O_RDONLY | constants.O_NONBLOCK); } catch { return null; }
12
+ try {
13
+ const stat = fstatSync(fd);
14
+ if (!stat.isFile() || stat.size > maxBytes) return null;
15
+ // One byte past the bound: a file that grew after the stat is refused too.
16
+ const buf = Buffer.alloc(maxBytes + 1);
17
+ const read = readSync(fd, buf, 0, buf.length, 0);
18
+ return read > maxBytes ? null : buf.toString("utf8", 0, read);
19
+ } catch {
20
+ return null;
21
+ } finally {
22
+ closeSync(fd);
23
+ }
24
+ }