immune-brain 4.6.0 → 5.1.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 (75) hide show
  1. package/README.md +374 -46
  2. package/README.zh-CN.md +384 -47
  3. package/package.json +2 -1
  4. package/plugins/immune-brain/.claude-plugin/plugin.json +1 -1
  5. package/plugins/immune-brain/.pi-extension/imm-canary-enroll.ts +42 -44
  6. package/plugins/immune-brain/.pi-extension/imm-canary-work.ts +143 -474
  7. package/plugins/immune-brain/.pi-extension/imm-unattended-batch.ts +78 -87
  8. package/plugins/immune-brain/.pi-extension/pi-canary-assurance-progression.ts +7 -2
  9. package/plugins/immune-brain/.pi-extension/tsconfig.json +2 -2
  10. package/plugins/immune-brain/agents/immune-brain-advisory-reviewer.md +23 -0
  11. package/plugins/immune-brain/agents/immune-brain-qa.md +42 -0
  12. package/plugins/immune-brain/agents/immune-brain-reviewer.md +90 -1
  13. package/plugins/immune-brain/agents/immune-brain-ui-review.md +21 -0
  14. package/plugins/immune-brain/dist/BASELINE.md +4 -4
  15. package/plugins/immune-brain/dist/claude/mcp-server.mjs +8601 -6975
  16. package/plugins/immune-brain/dist/docs/reference/immune-brain-config.md +27 -0
  17. package/plugins/immune-brain/dist/docs/reference/planning-quality-gate.md +3 -3
  18. package/plugins/immune-brain/dist/docs/reference/subagent-dispatch-protocol.md +30 -1
  19. package/plugins/immune-brain/dist/imm-brainstorm.md +1 -1
  20. package/plugins/immune-brain/dist/imm-doc-prune.md +2 -2
  21. package/plugins/immune-brain/dist/{imm-agent-doc-maintain.md → imm-doc-slim.md} +9 -9
  22. package/plugins/immune-brain/dist/imm-planner.md +23 -8
  23. package/plugins/immune-brain/dist/imm-pr-fix.md +1 -1
  24. package/plugins/immune-brain/dist/{imm-review-retro.md → imm-retro.md} +26 -13
  25. package/plugins/immune-brain/dist/{imm-loop.md → imm-run.md} +231 -10
  26. package/plugins/immune-brain/dist/registry.yaml +9 -9
  27. package/plugins/immune-brain/dist/role-prompts/code-review.md +7 -0
  28. package/plugins/immune-brain/dist/role-prompts/executor.md +35 -2
  29. package/plugins/immune-brain/dist/role-prompts/lane-steward.md +44 -0
  30. package/plugins/immune-brain/runtime/assurance/coordinator.ts +83 -67
  31. package/plugins/immune-brain/runtime/assurance/host_port.ts +20 -0
  32. package/plugins/immune-brain/runtime/assurance/qa.ts +2 -2
  33. package/plugins/immune-brain/runtime/assurance/verdict_authority.ts +347 -0
  34. package/plugins/immune-brain/runtime/claude/interaction.ts +6 -0
  35. package/plugins/immune-brain/runtime/claude/kernel_ports.ts +78 -373
  36. package/plugins/immune-brain/runtime/claude/mcp_server.ts +26 -2
  37. package/plugins/immune-brain/runtime/claude/review_host.ts +48 -16
  38. package/plugins/immune-brain/runtime/claude/role_agents.ts +84 -0
  39. package/plugins/immune-brain/runtime/commands/kernel.ts +3 -6
  40. package/plugins/immune-brain/runtime/kernel/application.ts +6 -3
  41. package/plugins/immune-brain/runtime/kernel/assurance_projection.ts +15 -8
  42. package/plugins/immune-brain/runtime/kernel/canary_application.ts +5 -3
  43. package/plugins/immune-brain/runtime/kernel/enrollment.ts +149 -5
  44. package/plugins/immune-brain/runtime/kernel/index.ts +3 -1
  45. package/plugins/immune-brain/runtime/kernel/storage.ts +170 -11
  46. package/plugins/immune-brain/runtime/kernel/storage_paths.ts +13 -0
  47. package/plugins/immune-brain/runtime/local_initiative.ts +94 -0
  48. package/plugins/immune-brain/runtime/loop_contract.ts +77 -24
  49. package/plugins/immune-brain/runtime/plugin_version.ts +1 -1
  50. package/plugins/immune-brain/runtime/prompts/code-review.md +7 -0
  51. package/plugins/immune-brain/runtime/prompts/executor.md +35 -2
  52. package/plugins/immune-brain/runtime/prompts/lane-steward.md +44 -0
  53. package/plugins/immune-brain/runtime/role_prompt_bridge.ts +42 -2
  54. package/plugins/immune-brain/runtime/unattended/batch_git.ts +57 -27
  55. package/plugins/immune-brain/runtime/unattended/batch_integration.ts +387 -0
  56. package/plugins/immune-brain/runtime/unattended/batch_kernel_port.ts +106 -0
  57. package/plugins/immune-brain/runtime/unattended/batch_lanes.ts +909 -0
  58. package/plugins/immune-brain/runtime/unattended/batch_plan.ts +36 -11
  59. package/plugins/immune-brain/runtime/unattended/batch_preflight.ts +53 -36
  60. package/plugins/immune-brain/runtime/unattended/batch_reconfirmation.ts +34 -29
  61. package/plugins/immune-brain/runtime/unattended/batch_runner.ts +46 -91
  62. package/plugins/immune-brain/runtime/unattended/batch_schedule.ts +162 -0
  63. package/plugins/immune-brain/runtime/unattended/batch_state.ts +356 -8
  64. package/plugins/immune-brain/runtime/unattended/types.ts +21 -2
  65. package/plugins/immune-brain/runtime/workspace_scope.ts +34 -0
  66. package/plugins/immune-brain/skills/BASELINE.md +4 -4
  67. package/plugins/immune-brain/skills/imm-doc-prune/SKILL.md +1 -1
  68. package/plugins/immune-brain/skills/{imm-agent-doc-maintain → imm-doc-slim}/SKILL.md +9 -9
  69. package/plugins/immune-brain/skills/imm-planner/SKILL.md +4 -2
  70. package/plugins/immune-brain/skills/imm-pr-fix/SKILL.md +1 -1
  71. package/plugins/immune-brain/skills/{imm-review-retro → imm-retro}/SKILL.md +7 -7
  72. package/plugins/immune-brain/skills/{imm-review-retro → imm-retro}/scripts/review_retro.ts +46 -21
  73. package/plugins/immune-brain/skills/{imm-loop → imm-run}/SKILL.md +11 -7
  74. package/plugins/immune-brain/skills/registry.yaml +9 -9
  75. package/plugins/immune-brain/.pi-extension/runtime-stub.ts +0 -581
@@ -1,581 +0,0 @@
1
- // Extension-local runtime adapter: type-isolated, executable stub.
2
- // Extensions import this file directly (relative path, resolvable by the Pi
3
- // extension loader); it forwards to the real Kernel modules via dynamic
4
- // import. Shared contracts are re-exported as types from the real Kernel
5
- // modules: `export type` is erased at compile time, so the extension still
6
- // carries no static runtime import, but a Kernel contract change now breaks
7
- // the extension's build instead of silently drifting from it.
8
-
9
- // --- Kernel constants the extension must carry as values ---
10
- // The literal-user authority identity. Mirrored here because extensions cannot
11
- // statically import Kernel modules; tests/dual-host-assurance-conformance.test.ts
12
- // pins this value to runtime/kernel/actor_identity.ts, so the two cannot drift.
13
- export const LITERAL_USER_ACTOR_ID = "literal-user";
14
-
15
- // --- Types (structural contracts, no runtime import) ---
16
- export interface EnrollmentCapabilityBinding {
17
- task_id: string;
18
- intent_path: string;
19
- intent_revision: number;
20
- intent_content_hash: string;
21
- preparation_digest: string;
22
- actor_id: string;
23
- confirmation_ref: string;
24
- nonce: string;
25
- }
26
- export interface EnrollmentAuthorityRegistry {
27
- issue(binding: EnrollmentCapabilityBinding, issuedAt?: string): object;
28
- inspect(capability: object, expected: EnrollmentCapabilityBinding, now?: number): unknown;
29
- consume(capability: object, expected: EnrollmentCapabilityBinding, now?: number): unknown;
30
- isConsumed(capability: object): boolean;
31
- }
32
- export interface CanaryWaiver {
33
- gate: "observation_window_days";
34
- task_id: string;
35
- reason: string;
36
- actor: string;
37
- confirmation_ref: string;
38
- nonce: string;
39
- }
40
- export interface PiCanaryPrepareInput {
41
- task_id: string;
42
- now: string;
43
- }
44
- export type PiCanaryPreparation = import("../runtime/kernel/pi_canary_prepare").PiCanaryPreparation;
45
- export type EnrollmentGitBase = import("../runtime/assurance/enrollment_git_base").EnrollmentGitBase;
46
- export interface EnrollCanaryInput {
47
- task_id: string;
48
- intent_path: string;
49
- intent_revision: number;
50
- preparation_digest: string;
51
- capability: object;
52
- capability_binding: Record<string, unknown>;
53
- now: string;
54
- }
55
-
56
- // --- P2B2 mutation authority / canary application types (structural) ---
57
- export interface CapabilityBindingV2 {
58
- authority_kind: "review" | "qa" | "user";
59
- task_id: string;
60
- action_digest: string;
61
- expected_record_hash: string;
62
- intent_revision: number;
63
- intent_content_hash: string;
64
- diff_hash: string;
65
- actor_id: string;
66
- confirmation_ref: string;
67
- findings_digest: string | null;
68
- }
69
- export interface MutationAuthorityRegistry {
70
- readonly brand: symbol;
71
- issue(binding: CapabilityBindingV2, issuedAt?: string): object;
72
- inspect(capability: object | undefined, expected: unknown, now?: number): unknown;
73
- consume(capability: object, expected: unknown, now?: number): unknown;
74
- isConsumed(capability: object): boolean;
75
- }
76
- export interface CanaryApplication {
77
- readonly registry: MutationAuthorityRegistry;
78
- execute(input: unknown): unknown;
79
- beginDrain(input: {
80
- root: string;
81
- task_id: string;
82
- capability: object;
83
- now?: string;
84
- }): unknown;
85
- }
86
- export interface StoredTaskMutation {
87
- revision: string;
88
- record: {
89
- contract: "assurance_kernel/task_record/v3" | "assurance_kernel/task_record/v4";
90
- task_id: string;
91
- /** Present only on TaskRecord v4: the immutable Enrollment commit. */
92
- git_base_head?: string;
93
- intent_snapshot: { revision: number; [key: string]: unknown };
94
- intent_ref: { path: string; content_hash: string };
95
- lifecycle: "active" | "done" | "stopped";
96
- artifact_state: "active" | "frozen";
97
- attestations: unknown[];
98
- findings: unknown[];
99
- history: unknown[];
100
- };
101
- workspace: { revision: string; state: { contract: string; current_working: string | null } };
102
- }
103
- export interface BackendClaim {
104
- contract: string;
105
- backend: "kernel";
106
- task_id: string;
107
- intent_revision: number;
108
- intent_content_hash: string;
109
- enrollment_event_id: string;
110
- lifecycle_status: "active" | "draining";
111
- created_at: string;
112
- updated_at: string;
113
- }
114
- export interface KernelAuthorityProjection {
115
- contract: "assurance_kernel/authority_projection/v1";
116
- requested_task_id: string;
117
- state: "unowned" | "active_owner" | "terminal_owner" | "repairable_stale_claim" | "authority_conflict";
118
- owner_task_id: string | null;
119
- owner_run_id: string | null;
120
- owner_lifecycle: string | null;
121
- claim_lifecycle_status: "active" | "draining" | null;
122
- diagnostic: string | null;
123
- revision: string;
124
- }
125
- export interface TaskTombstone {
126
- contract: string;
127
- task_id: string;
128
- lifecycle_status: "terminal";
129
- terminal_lifecycle: string;
130
- terminal_event_id: string;
131
- final_record_hash: string;
132
- terminalized_at: string;
133
- }
134
- export type TaskRecordContract =
135
- | "assurance_kernel/task_record/v3"
136
- | "assurance_kernel/task_record/v4";
137
-
138
- export interface TaskRecordRead {
139
- revision: string;
140
- record: {
141
- contract: TaskRecordContract;
142
- task_id: string;
143
- /** Present only on TaskRecord v4: the immutable Enrollment commit. */
144
- git_base_head?: string;
145
- intent_snapshot: {
146
- task_id: string;
147
- revision: number;
148
- risk: "routine" | "material" | "critical";
149
- acceptance: Array<{ id: string; assertion: string; verification: string }>;
150
- scope_hint: string[];
151
- };
152
- intent_ref: { path: string; content_hash: string };
153
- lifecycle: "active" | "done" | "stopped";
154
- artifact_state: "active" | "frozen";
155
- attestations: Array<{
156
- id: string;
157
- kind: "qa" | "review" | "user";
158
- task_revision: number;
159
- intent_content_hash: string;
160
- diff_hash: string;
161
- actor_id: string;
162
- acceptance_results: Array<{ acceptance_id: string; status: "passed" | "failed" | "blocked"; summary: string }>;
163
- review_revision?: {
164
- contract: "assurance_kernel/review_revision_identity/v1";
165
- base_head: string;
166
- review_commit: string;
167
- review_tree: string;
168
- manifest_digest: string;
169
- };
170
- }>;
171
- history: import("../runtime/kernel/types").TaskRecord["history"];
172
- findings: Array<{
173
- id: string;
174
- kind: string;
175
- status: string;
176
- acceptance_id?: string | null;
177
- summary?: string;
178
- anchor?: string | null;
179
- evidence?: unknown;
180
- counterevidence?: { attestation_id: string; acceptance_id: string } | null;
181
- }>;
182
- } | null;
183
- }
184
-
185
- // --- Assurance projection (host-neutral Kernel facts, not exported from the
186
- // public Kernel index) ---
187
- export type {
188
- AssuranceAuthorizationReadiness,
189
- AssuranceProjection,
190
- AssuranceProjectionResult,
191
- } from "../runtime/kernel/assurance_projection";
192
- import type {
193
- AssuranceAuthorizationReadiness,
194
- AssuranceProjectionResult,
195
- } from "../runtime/kernel/assurance_projection";
196
-
197
- // --- Runtime forwarding (dynamic import keeps the graph out of tsc) ---
198
- function kernelPath(module: string): string {
199
- return `../runtime/kernel/${module}.ts`;
200
- }
201
- function runtimePath(module: string): string {
202
- return `../runtime/${module}.ts`;
203
- }
204
-
205
- export interface GithubTrackerResult {
206
- contract: "immune_brain/github_issue_tracker_result/v1";
207
- operation: "create-initiative" | "upsert-task" | "mark-terminal";
208
- status: "created" | "updated" | "already_current" | "retryable_failure" | "permanent_failure" | "ambiguous_remote_state";
209
- association_found: boolean;
210
- issue_number?: number;
211
- issue_url?: string;
212
- message: string;
213
- }
214
-
215
- export async function buildLoopAction(input: unknown): Promise<unknown> {
216
- const mod = await import(/* @vite-ignore */ runtimePath("loop_contract"));
217
- return mod.buildLoopAction(input);
218
- }
219
- export async function buildLoopRoleDispatch(input: unknown): Promise<unknown> {
220
- const mod = await import(/* @vite-ignore */ runtimePath("loop_contract"));
221
- return mod.buildLoopRoleDispatch(input);
222
- }
223
- export async function markGithubTaskTerminal(
224
- root: string,
225
- input: { task_id: string; phase: "done" | "stopped"; terminal_event_id: string },
226
- ): Promise<GithubTrackerResult> {
227
- const mod = await import(/* @vite-ignore */ runtimePath("github_issue_tracker"));
228
- return mod.runGithubTrackerOperation(root, { op: "mark-terminal", ...input }) as Promise<GithubTrackerResult>;
229
- }
230
- export async function createEnrollmentAuthorityRegistry(): Promise<EnrollmentAuthorityRegistry> {
231
- const mod = await import(/* @vite-ignore */ kernelPath("enrollment_authority"));
232
- return mod.createEnrollmentAuthorityRegistry();
233
- }
234
- export async function inspectEnrollmentGitBase(root: string): Promise<EnrollmentGitBase> {
235
- const mod = await import(/* @vite-ignore */ runtimePath("assurance/enrollment_git_base"));
236
- return mod.inspectEnrollmentGitBase(root);
237
- }
238
- export async function enrollmentGitBaseNotice(base: EnrollmentGitBase): Promise<string | undefined> {
239
- const mod = await import(/* @vite-ignore */ runtimePath("assurance/enrollment_git_base"));
240
- return mod.enrollmentGitBaseNotice(base);
241
- }
242
- export async function initializeEnrollmentGitBase(root: string, input: PiCanaryPrepareInput, previous: PiCanaryPreparation, base: EnrollmentGitBase, signal?: AbortSignal): Promise<PiCanaryPreparation> {
243
- const mod = await import(/* @vite-ignore */ runtimePath("assurance/enrollment_git_base"));
244
- return mod.initializeEnrollmentGitBase(root, input, previous, base, signal);
245
- }
246
- export async function preparePiCanary(
247
- root: string,
248
- input: PiCanaryPrepareInput,
249
- ): Promise<PiCanaryPreparation> {
250
- const mod = await import(/* @vite-ignore */ runtimePath("assurance/enrollment"));
251
- return mod.preparePiCanary(root, input) as unknown as PiCanaryPreparation;
252
- }
253
- export async function revalidatePiCanary(
254
- root: string,
255
- input: PiCanaryPrepareInput,
256
- previous: PiCanaryPreparation,
257
- ): Promise<{ unchanged: boolean; current: PiCanaryPreparation }> {
258
- const mod = await import(/* @vite-ignore */ runtimePath("assurance/enrollment"));
259
- return mod.revalidatePiCanary(root, input, previous as never) as unknown as { unchanged: boolean; current: PiCanaryPreparation };
260
- }
261
- export async function evaluateCanaryEligibility(input: {
262
- task: { id: string; intent_path: string; intent_revision: number; intent_content_hash: string };
263
- waiver?: CanaryWaiver;
264
- now: string;
265
- }): Promise<{ eligible: boolean; waived_gates: string[]; unmet_non_waivable: string[]; rejections: string[] }> {
266
- const mod = await import(/* @vite-ignore */ kernelPath("canary_eligibility"));
267
- return mod.evaluateCanaryEligibility(input as never);
268
- }
269
- export async function runEnrollmentRehearsal(
270
- root: string,
271
- input: EnrollCanaryInput,
272
- capability: object,
273
- registry: EnrollmentAuthorityRegistry,
274
- ): Promise<{ rehearsed: boolean; writes_performed: boolean; evidence: { outcome: "ready" | "not_ready"; blockers: string[] } }> {
275
- const mod = await import(/* @vite-ignore */ kernelPath("enrollment"));
276
- return mod.runEnrollmentRehearsal(root, input as never, capability, registry as never);
277
- }
278
- export async function enrollCanaryTask(
279
- root: string,
280
- input: EnrollCanaryInput,
281
- registry: EnrollmentAuthorityRegistry,
282
- ): Promise<{ record: { task_id: string; lifecycle: string; artifact_state: string }; backend_claim: { backend: string } }> {
283
- const mod = await import(/* @vite-ignore */ kernelPath("enrollment"));
284
- return mod.enrollCanaryTask(root, input as never, registry as never);
285
- }
286
-
287
- export async function createMutationAuthorityRegistry(): Promise<MutationAuthorityRegistry> {
288
- const mod = await import(/* @vite-ignore */ kernelPath("authority_port"));
289
- return mod.createMutationAuthorityRegistry();
290
- }
291
- export async function createCanaryApplication(
292
- registry: MutationAuthorityRegistry,
293
- ): Promise<CanaryApplication> {
294
- const mod = await import(/* @vite-ignore */ kernelPath("canary_application"));
295
- return mod.createCanaryApplication(registry as never);
296
- }
297
- export async function readTaskRecord(
298
- root: string,
299
- taskId: string,
300
- ): Promise<TaskRecordRead> {
301
- const mod = await import(/* @vite-ignore */ kernelPath("storage"));
302
- // Lock-free read only. `storage.readTaskRecord` wraps this in
303
- // withKernelStoreLock, which first runs pending-transaction recovery, so a
304
- // decline, a cancel, or a rejected preflight would otherwise mutate Kernel
305
- // state before the literal user ever approved anything. Mutating Kernel
306
- // entrypoints still take their own lock when the batch actually starts.
307
- return mod.readTaskRecordRaw(root, taskId);
308
- }
309
- export async function withKernelStoreLock<T>(root: string, operation: () => T): Promise<T> {
310
- const mod = await import(/* @vite-ignore */ kernelPath("storage"));
311
- return mod.withKernelStoreLock(root, operation);
312
- }
313
- export async function withKernelStoreLockForTask<T>(
314
- root: string,
315
- taskId: string,
316
- operation: () => T,
317
- ): Promise<T> {
318
- const mod = await import(/* @vite-ignore */ kernelPath("storage"));
319
- return mod.withKernelStoreLockForTask(root, taskId, operation);
320
- }
321
- export async function readBackendClaim(root: string): Promise<BackendClaim | null> {
322
- const mod = await import(/* @vite-ignore */ kernelPath("backend_claim"));
323
- return mod.readBackendClaim(root);
324
- }
325
- export async function reconcileKernelAuthority(
326
- root: string,
327
- taskId: string,
328
- ): Promise<KernelAuthorityProjection> {
329
- const mod = await import(/* @vite-ignore */ kernelPath("storage"));
330
- return mod.reconcileKernelAuthority(root, taskId);
331
- }
332
- export async function repairKernelAuthority(
333
- root: string,
334
- taskId: string,
335
- expectedProjectionRevision: string,
336
- ): Promise<KernelAuthorityProjection> {
337
- const mod = await import(/* @vite-ignore */ kernelPath("storage"));
338
- return mod.repairKernelAuthority(root, taskId, expectedProjectionRevision);
339
- }
340
- export async function readTaskTombstone(
341
- root: string,
342
- taskId: string,
343
- ): Promise<TaskTombstone | null> {
344
- const mod = await import(/* @vite-ignore */ kernelPath("backend_claim"));
345
- return mod.readTaskTombstone(root, taskId);
346
- }
347
-
348
- export interface TaskIntentV1 {
349
- contract: "assurance_kernel/task_intent/v1";
350
- goal: string;
351
- task_id: string;
352
- revision: number;
353
- risk: "routine" | "material" | "critical";
354
- owner: "user";
355
- acceptance: Array<{ id: string; assertion: string; verification: string }>;
356
- scope_hint: string[];
357
- }
358
- export type { ReadTaskIntentResult as TaskIntentRead } from "../runtime/kernel/intent";
359
- import type { ReadTaskIntentResult as TaskIntentRead } from "../runtime/kernel/intent";
360
- export interface WorkspaceRead {
361
- revision: string;
362
- state: { contract: string; current_working: string | null };
363
- }
364
- export async function readTaskIntent(root: string, taskId: string, path?: string): Promise<TaskIntentRead> {
365
- const [intent, storage] = await Promise.all([
366
- import(/* @vite-ignore */ kernelPath("intent")),
367
- import(/* @vite-ignore */ kernelPath("storage")),
368
- ]);
369
- const currentPath = path ?? storage.readTaskRecordRaw(root, taskId).record?.intent_ref.path;
370
- return intent.readTaskIntent(root, taskId, currentPath);
371
- }
372
- export async function parseTaskIntentV1(raw: unknown): Promise<TaskIntentV1> {
373
- const mod = await import(/* @vite-ignore */ kernelPath("intent"));
374
- return mod.parseTaskIntentV1(raw);
375
- }
376
- export async function canonicalIntentHash(intent: unknown): Promise<string> {
377
- const mod = await import(/* @vite-ignore */ kernelPath("intent"));
378
- return mod.canonicalIntentHash(intent);
379
- }
380
-
381
- export async function readWorkspaceState(root: string): Promise<WorkspaceRead> {
382
- const mod = await import(/* @vite-ignore */ kernelPath("storage"));
383
- return mod.readWorkspaceStateRaw(root);
384
- }
385
- export async function inspectStorageLayout(root: string): Promise<import("../runtime/kernel/storage_paths").StorageLayoutInspection> {
386
- const mod = await import(/* @vite-ignore */ kernelPath("storage_paths"));
387
- return mod.inspectStorageLayout(root);
388
- }
389
- export async function migrateLegacyLayout(root: string): Promise<import("../runtime/kernel/storage_layout_migration").MigrationOutcome> {
390
- const mod = await import(/* @vite-ignore */ kernelPath("storage_layout_migration"));
391
- return mod.migrateLegacyLayout(root);
392
- }
393
- export async function beginDrainCapabilityAction(
394
- taskId: string,
395
- at: string,
396
- ): Promise<{ type: string; event_id: string; at: string; actor_id: string; reason: string }> {
397
- const mod = await import(/* @vite-ignore */ kernelPath("canary_application"));
398
- return mod.beginDrainCapabilityAction(taskId, at);
399
- }
400
-
401
- export async function capabilityActionFor(input: unknown): Promise<unknown> {
402
- const mod = await import(/* @vite-ignore */ kernelPath("canary_application"));
403
- return mod.capabilityActionFor(input);
404
- }
405
-
406
- export async function digestOfAction(action: unknown): Promise<string> {
407
- const mod = await import(/* @vite-ignore */ kernelPath("authority_port"));
408
- return mod.digestOfAction(action);
409
- }
410
-
411
- export async function findingsDigestV2(findings: unknown[]): Promise<string> {
412
- const mod = await import(/* @vite-ignore */ kernelPath("reducer"));
413
- return mod.findingsDigestV2(findings);
414
- }
415
-
416
- export async function projectAssurance(
417
- root: string,
418
- taskId: string,
419
- diffProvider: (root: string, record: NonNullable<TaskRecordRead["record"]>) => {
420
- diff_hash: string;
421
- changed_paths: readonly string[];
422
- },
423
- ): Promise<AssuranceProjectionResult> {
424
- const mod = await import(/* @vite-ignore */ kernelPath("assurance_projection"));
425
- return mod.projectAssurance(root, taskId, diffProvider) as AssuranceProjectionResult;
426
- }
427
-
428
- export async function deriveAssuranceAuthorization(input: {
429
- next_obligation: AssuranceProjectionResult["projection"]["next_obligation"];
430
- open_user_decision_count: number;
431
- }): Promise<AssuranceAuthorizationReadiness> {
432
- const mod = await import(/* @vite-ignore */ kernelPath("assurance_projection"));
433
- return mod.deriveAssuranceAuthorization(input) as AssuranceAuthorizationReadiness;
434
- }
435
-
436
- // --- Batch Authority & Unattended Runner Forwarding ---
437
- function unattendedPath(module: string): string {
438
- return `../runtime/unattended/${module}.ts`;
439
- }
440
-
441
- export type {
442
- BatchPlan,
443
- BatchPlanChild,
444
- BatchPlanBudget,
445
- BatchPlanDigestChild,
446
- InitiativeObservationReader,
447
- } from "../runtime/unattended/types";
448
- export type {
449
- BatchAuthorityRegistry,
450
- BatchAuthorizationBinding,
451
- ValidatedBatchAuthorization,
452
- } from "../runtime/kernel/batch_authority";
453
- export { batchQaFailureFacts } from "../runtime/unattended/batch_runner";
454
- export type {
455
- BatchRunnerKernelPort,
456
- StartBatchInput,
457
- BatchRunReport,
458
- } from "../runtime/unattended/batch_runner";
459
- export type {
460
- BatchRunnerGitPort,
461
- BatchGitPreflightResult,
462
- } from "../runtime/unattended/batch_git";
463
-
464
- export async function projectBatchPlan(
465
- root: string,
466
- initiativeSlug: string,
467
- input: any,
468
- readInitiative?: any,
469
- ): Promise<any> {
470
- const mod = await import(/* @vite-ignore */ unattendedPath("batch_plan"));
471
- return mod.projectBatchPlan(root, initiativeSlug, input, readInitiative);
472
- }
473
-
474
- export async function computeBatchPlanDigest(children: any): Promise<string> {
475
- const mod = await import(/* @vite-ignore */ kernelPath("batch_authority"));
476
- return mod.computeBatchPlanDigest(children);
477
- }
478
-
479
- export async function createBatchAuthorityRegistry(): Promise<any> {
480
- const mod = await import(/* @vite-ignore */ kernelPath("batch_authority"));
481
- return mod.createBatchAuthorityRegistry();
482
- }
483
-
484
- export async function deriveChildEnrollment(root: string, registry: any, input: any): Promise<any> {
485
- const mod = await import(/* @vite-ignore */ kernelPath("batch_authority"));
486
- return mod.deriveChildEnrollment(root, registry, input);
487
- }
488
-
489
- export async function startBatch(input: any): Promise<any> {
490
- const mod = await import(/* @vite-ignore */ unattendedPath("batch_runner"));
491
- return mod.startBatch(input);
492
- }
493
-
494
- export async function runBatchGitPreflight(input: any): Promise<any> {
495
- const mod = await import(/* @vite-ignore */ unattendedPath("batch_git"));
496
- return mod.runBatchGitPreflight(input);
497
- }
498
-
499
- export async function readGitHead(root: string): Promise<string> {
500
- // The Pi extension must reach Kernel prepare only through the shared Enrollment
501
- // boundary, so this reads HEAD itself rather than importing the Kernel prepare
502
- // module. The unattended Git module reads HEAD the same way.
503
- const { spawnSync } = await import("node:child_process");
504
- const result = spawnSync("git", ["-C", root, "rev-parse", "HEAD"], { encoding: "utf8" });
505
- if (result.status !== 0) throw new Error(`git rev-parse HEAD is unavailable for ${root}`);
506
- return result.stdout.trim();
507
- }
508
-
509
- /**
510
- * Read the immutable terminal audit record for a settled child.
511
- *
512
- * A child reaches Kernel settlement before the batch commits it, and settlement
513
- * clears the live state record, so the batch resume preflight must resolve the
514
- * child's authorized scope from the audit pair instead. Read-only: neither the
515
- * audit pair nor this reader mutates Kernel state.
516
- */
517
- export async function readSettledTaskRecord(
518
- root: string,
519
- taskId: string,
520
- ): Promise<{ scope_hint: string[]; intent_path: string | undefined } | null> {
521
- const mod = await import(/* @vite-ignore */ kernelPath("storage"));
522
- const pair = mod.readAuditTaskPair(root, taskId);
523
- if (!pair?.record) return null;
524
- const record = pair.record as {
525
- intent_snapshot?: { scope_hint?: string[] };
526
- intent_ref?: { path?: string };
527
- };
528
- return {
529
- scope_hint: record.intent_snapshot?.scope_hint ?? [],
530
- intent_path: record.intent_ref?.path,
531
- };
532
- }
533
-
534
- export async function pathMatchesScope(path: string, scopePath: string): Promise<boolean> {
535
- const mod = await import(/* @vite-ignore */ runtimePath("workspace_scope"));
536
- return mod.pathMatchesScope(path, scopePath);
537
- }
538
-
539
- const GLOBAL_PI_PROGRESSION_KEY = Symbol.for("immune_brain.pi_assurance_progression");
540
-
541
- export async function getSharedPiProgression(): Promise<any> {
542
- let progression = (globalThis as any)[GLOBAL_PI_PROGRESSION_KEY];
543
- if (!progression) {
544
- const workMod = await import(/* @vite-ignore */ "./imm-canary-work");
545
- const ports = workMod.createPiAssuranceProgressionPorts();
546
- const progMod = await import(/* @vite-ignore */ "./pi-canary-assurance-progression");
547
- progression = new progMod.AssuranceProgression(ports);
548
- (globalThis as any)[GLOBAL_PI_PROGRESSION_KEY] = progression;
549
- }
550
- return progression;
551
- }
552
-
553
- export async function advancePiTask(root: string, taskId: string): Promise<any> {
554
- const progression = await getSharedPiProgression();
555
- const result = await progression.advance(taskId, { cwd: root });
556
- const facts = { diagnostics: result.diagnostics, environment_failure: result.environment_failure, recovery: result.recovery };
557
- if (result.state === "completed") return { state: "completed", ...facts };
558
- if (result.state === "stopped") return { state: "stopped", ...facts };
559
- if (result.state === "rework") return { state: "rework", operation: result.operation, summary: result.summary, ...facts };
560
- if (result.state === "review_ready") return { state: "review_ready", operation_id: result.operation_id, agent_params: result.agent_params, ...facts };
561
- if (result.state === "review_preparation_failed") return { state: result.state, operation: result.operation, operation_id: result.operation_id, reason: result.reason, ...facts };
562
- if (result.state === "blocked") return { state: "blocked", reason: result.reason, ...facts };
563
- return { state: "failed", reason: (result as { reason?: string }).reason ?? "advance failed", ...facts };
564
- }
565
-
566
- export async function projectAssuranceForTask(root: string, taskId: string): Promise<any> {
567
- const [assuranceMod, scopeMod] = await Promise.all([
568
- import(/* @vite-ignore */ kernelPath("assurance_projection")),
569
- import(/* @vite-ignore */ runtimePath("workspace_scope")),
570
- ]);
571
- const diffSnapshotOf = (r: string, record: any) => {
572
- if (record.contract === "assurance_kernel/task_record/v4") {
573
- if (!record.git_base_head)
574
- throw new Error("TaskRecord v4 is missing git_base_head");
575
- return scopeMod.taskRevisionIdentity(r, record.intent_snapshot.scope_hint, record.git_base_head, record.task_id);
576
- }
577
- return scopeMod.taskDiffIdentity(r, record.intent_snapshot.scope_hint, record.task_id);
578
- };
579
- return assuranceMod.projectAssurance(root, taskId, diffSnapshotOf);
580
- }
581
-