immune-brain 3.6.8 → 4.0.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 (82) hide show
  1. package/README.md +11 -4
  2. package/README.zh-CN.md +10 -3
  3. package/package.json +3 -2
  4. package/plugins/immune-brain/.claude-plugin/plugin.json +1 -1
  5. package/plugins/immune-brain/.pi-extension/imm-canary-enroll.ts +18 -2
  6. package/plugins/immune-brain/.pi-extension/imm-canary-work.ts +76 -121
  7. package/plugins/immune-brain/.pi-extension/imm-unattended-batch.ts +106 -600
  8. package/plugins/immune-brain/.pi-extension/pi-canary-assurance-progression.ts +1 -0
  9. package/plugins/immune-brain/.pi-extension/pi-canary-verification.ts +3 -3
  10. package/plugins/immune-brain/.pi-extension/runtime-stub.ts +17 -43
  11. package/plugins/immune-brain/dist/claude/mcp-server.mjs +7581 -5042
  12. package/plugins/immune-brain/dist/docs/reference/planning-artifact-retention.md +11 -12
  13. package/plugins/immune-brain/dist/docs/reference/subagent-dispatch-protocol.md +1 -1
  14. package/plugins/immune-brain/dist/imm-loop.md +27 -25
  15. package/plugins/immune-brain/dist/imm-planner.md +53 -32
  16. package/plugins/immune-brain/dist/imm-review-retro.md +123 -0
  17. package/plugins/immune-brain/dist/registry.yaml +9 -0
  18. package/plugins/immune-brain/dist/role-prompts/code-review.md +3 -1
  19. package/plugins/immune-brain/dist/role-prompts/executor.md +4 -4
  20. package/plugins/immune-brain/runtime/assurance/coordinator.ts +183 -40
  21. package/plugins/immune-brain/runtime/assurance/delivery_workspace.ts +240 -0
  22. package/plugins/immune-brain/runtime/assurance/qa.ts +132 -58
  23. package/plugins/immune-brain/runtime/assurance/review_evidence.ts +15 -7
  24. package/plugins/immune-brain/runtime/assurance/verification.ts +246 -206
  25. package/plugins/immune-brain/runtime/authorization_operation.ts +20 -0
  26. package/plugins/immune-brain/runtime/claude/kernel_ports.ts +288 -721
  27. package/plugins/immune-brain/runtime/commands/kernel.ts +158 -67
  28. package/plugins/immune-brain/runtime/github_issue_tracker.ts +254 -29
  29. package/plugins/immune-brain/runtime/kernel/actor_identity.ts +33 -0
  30. package/plugins/immune-brain/runtime/kernel/application.ts +22 -6
  31. package/plugins/immune-brain/runtime/kernel/assurance_projection.ts +94 -5
  32. package/plugins/immune-brain/runtime/kernel/authority_port.ts +27 -6
  33. package/plugins/immune-brain/runtime/kernel/backend_claim.ts +43 -16
  34. package/plugins/immune-brain/runtime/kernel/batch_authority.ts +10 -6
  35. package/plugins/immune-brain/runtime/kernel/canary_application.ts +50 -63
  36. package/plugins/immune-brain/runtime/kernel/canary_eligibility.ts +13 -4
  37. package/plugins/immune-brain/runtime/kernel/completion.ts +5 -14
  38. package/plugins/immune-brain/runtime/kernel/enrollment.ts +124 -34
  39. package/plugins/immune-brain/runtime/kernel/enrollment_authority.ts +13 -5
  40. package/plugins/immune-brain/runtime/kernel/index.ts +3 -1
  41. package/plugins/immune-brain/runtime/kernel/intent.ts +7 -11
  42. package/plugins/immune-brain/runtime/kernel/legacy_audit.ts +4 -1
  43. package/plugins/immune-brain/runtime/kernel/legacy_task_record.ts +323 -0
  44. package/plugins/immune-brain/runtime/kernel/pi_canary_prepare.ts +10 -1
  45. package/plugins/immune-brain/runtime/kernel/reducer.ts +32 -31
  46. package/plugins/immune-brain/runtime/kernel/run_identity.ts +121 -0
  47. package/plugins/immune-brain/runtime/kernel/spec_binding.ts +100 -0
  48. package/plugins/immune-brain/runtime/kernel/sqlite_migration.ts +950 -0
  49. package/plugins/immune-brain/runtime/kernel/sqlite_store.ts +1193 -0
  50. package/plugins/immune-brain/runtime/kernel/storage.ts +1254 -1206
  51. package/plugins/immune-brain/runtime/kernel/storage_layout_migration.ts +129 -755
  52. package/plugins/immune-brain/runtime/kernel/storage_paths.ts +419 -46
  53. package/plugins/immune-brain/runtime/kernel/types.ts +12 -43
  54. package/plugins/immune-brain/runtime/kernel/validation.ts +60 -274
  55. package/plugins/immune-brain/runtime/managed_task_routing_policy.ts +0 -1
  56. package/plugins/immune-brain/runtime/plan_core.ts +27 -65
  57. package/plugins/immune-brain/runtime/plugin_version.ts +1 -1
  58. package/plugins/immune-brain/runtime/prompts/code-review.md +3 -1
  59. package/plugins/immune-brain/runtime/prompts/executor.md +4 -4
  60. package/plugins/immune-brain/runtime/staged_intent.ts +58 -0
  61. package/plugins/immune-brain/runtime/unattended/batch_git.ts +37 -7
  62. package/plugins/immune-brain/runtime/unattended/batch_plan.ts +42 -2
  63. package/plugins/immune-brain/runtime/unattended/batch_preflight.ts +771 -0
  64. package/plugins/immune-brain/runtime/unattended/batch_reasons.ts +189 -0
  65. package/plugins/immune-brain/runtime/unattended/batch_runner.ts +35 -0
  66. package/plugins/immune-brain/runtime/unattended/confirmation_deadline.ts +33 -0
  67. package/plugins/immune-brain/runtime/unattended/types.ts +14 -1
  68. package/plugins/immune-brain/runtime/v4_runtime.ts +19 -23
  69. package/plugins/immune-brain/runtime/verification_descriptor.ts +92 -136
  70. package/plugins/immune-brain/runtime/workspace_scope.ts +98 -13
  71. package/plugins/immune-brain/skills/imm-planner/SKILL.md +3 -3
  72. package/plugins/immune-brain/skills/imm-review-retro/SKILL.md +23 -0
  73. package/plugins/immune-brain/skills/imm-review-retro/scripts/review_retro.ts +355 -0
  74. package/plugins/immune-brain/skills/registry.yaml +9 -0
  75. package/plugins/immune-brain/bin/imm-retire-stale-wrapper +0 -4
  76. package/plugins/immune-brain/bin/imm-retired +0 -4
  77. package/plugins/immune-brain/runtime/authority_commit_receipts.ts +0 -716
  78. package/plugins/immune-brain/runtime/kernel/automatic_observations.ts +0 -451
  79. package/plugins/immune-brain/runtime/kernel/legacy.ts +0 -299
  80. package/plugins/immune-brain/runtime/kernel/observation.ts +0 -397
  81. package/plugins/immune-brain/runtime/kernel/readiness.ts +0 -282
  82. package/plugins/immune-brain/runtime/kernel/readiness_evidence.ts +0 -132
@@ -1,4 +1,3 @@
1
- import { createHash } from "node:crypto";
2
1
  import {
3
2
  closeSync,
4
3
  constants as fsConstants,
@@ -8,7 +7,7 @@ import {
8
7
  writeFileSync,
9
8
  } from "node:fs";
10
9
  import { execFileSync } from "node:child_process";
11
- import { join, resolve } from "node:path";
10
+ import { resolve } from "node:path";
12
11
  import process from "node:process";
13
12
  import { fileURLToPath } from "node:url";
14
13
  import {
@@ -27,6 +26,7 @@ import {
27
26
  parseTaskIntentV1,
28
27
  RISK_FLOOR_SCOPE_PREFIXES,
29
28
  } from "../kernel/intent";
29
+ import { inspectSpecBinding } from "../kernel/spec_binding";
30
30
  import { projectTask, resolveProjectedRisk } from "../kernel/completion";
31
31
  import { deriveAssuranceAuthorization } from "../kernel/assurance_projection";
32
32
  import { taskDiffIdentity, taskRevisionIdentity } from "../workspace_scope";
@@ -40,7 +40,7 @@ import { projectLegacyAudit } from "../kernel/legacy_audit";
40
40
  import { inspectStorageLayout } from "../kernel/storage_paths";
41
41
  import { migrateLegacyLayout } from "../kernel/storage_layout_migration";
42
42
  import { readBackendClaim } from "../kernel/backend_claim";
43
- import { withKernelStoreLock } from "../kernel";
43
+ import { probeKernelStore } from "../kernel";
44
44
 
45
45
  export interface KernelCommandResult {
46
46
  stdout: string;
@@ -65,12 +65,6 @@ function errorResult(code: string, message: string, returncode: number): KernelC
65
65
  return jsonResult({ error: { code, message } }, returncode);
66
66
  }
67
67
 
68
- function asRecord(value: unknown): Record<string, unknown> {
69
- return value && typeof value === "object" && !Array.isArray(value)
70
- ? (value as Record<string, unknown>)
71
- : {};
72
- }
73
-
74
68
  function journalFor(
75
69
  command: string,
76
70
  phase: TaskPhase | null,
@@ -121,16 +115,7 @@ function runStatus(root: string): KernelExecution {
121
115
  try {
122
116
  const layout = inspectStorageLayout(root);
123
117
  const claim = readBackendClaim(root);
124
- const workspace = (() => {
125
- try {
126
- const raw = JSON.parse(readSecureProjectFile(root, ".imm/state/workspace.json")) as {
127
- current_working?: unknown;
128
- };
129
- return typeof raw.current_working === "string" ? raw.current_working : null;
130
- } catch {
131
- return null;
132
- }
133
- })();
118
+ const workspace = readWorkspaceOwner(root);
134
119
  return {
135
120
  result: jsonResult({
136
121
  contract: "assurance_kernel/status/v1",
@@ -193,10 +178,7 @@ function matchingFloorEntries(intent: TaskIntentV1): string[] {
193
178
 
194
179
  function readWorkspaceOwner(root: string): string | null {
195
180
  try {
196
- const raw = JSON.parse(readSecureProjectFile(root, ".imm/state/workspace.json")) as {
197
- current_working?: unknown;
198
- };
199
- return typeof raw.current_working === "string" ? raw.current_working : null;
181
+ return readWorkspaceStateRaw(root).state.current_working;
200
182
  } catch {
201
183
  return null;
202
184
  }
@@ -292,8 +274,8 @@ function runInspect(root: string): KernelExecution {
292
274
  try {
293
275
  identity =
294
276
  record.contract === "assurance_kernel/task_record/v4"
295
- ? taskRevisionIdentity(root, intent.scope_hint, record.git_base_head)
296
- : taskDiffIdentity(root, intent.scope_hint);
277
+ ? taskRevisionIdentity(root, intent.scope_hint, record.git_base_head, intent.task_id)
278
+ : taskDiffIdentity(root, intent.scope_hint, intent.task_id);
297
279
  } catch (error) {
298
280
  return sourceFailure("inspect", error);
299
281
  }
@@ -499,7 +481,7 @@ function runIntentAuthor(args: string[], root: string): KernelExecution {
499
481
  // its frozen manifest under both locks. The original authoring is retried
500
482
  // only after the affected migration diff is committed.
501
483
  try {
502
- withKernelStoreLock(root, () => undefined);
484
+ probeKernelStore(root);
503
485
  } catch (error) {
504
486
  return {
505
487
  result: errorResult(
@@ -536,46 +518,13 @@ function runIntentAuthor(args: string[], root: string): KernelExecution {
536
518
  };
537
519
  }
538
520
  if (layout.layout === "recovery_required" || layout.layout === "migration_required") {
539
- const migration = migrateLegacyLayout(root);
540
- if (migration.outcome === "migrated") {
541
- return {
542
- result: jsonResult({
543
- contract: "assurance_kernel/migration_completed/v1",
544
- operation: "intent author",
545
- affected_paths: migration.affected_paths,
546
- next_action: "commit the affected migration paths, then retry intent author",
547
- }),
548
- journal: journalFor(
549
- "intent",
550
- null,
551
- "escalated",
552
- "migration_ambiguous",
553
- null,
554
- "Legacy evidence was relocated without Git index writes; commit and retry.",
555
- ),
556
- };
557
- }
558
- if (migration.outcome === "migration_uncommitted") {
559
- return {
560
- result: errorResult(
561
- "migration_uncommitted",
562
- `affected storage paths differ from HEAD: ${migration.affected_paths.join(", ") || "(none)"}`,
563
- 1,
564
- ),
565
- journal: journalFor(
566
- "intent",
567
- null,
568
- "rejected",
569
- "migration_ambiguous",
570
- null,
571
- "Commit or restore the affected paths before retrying.",
572
- ),
573
- };
574
- }
521
+ // Authoring never migrates implicitly: the retired layout is converted by
522
+ // the explicit claimless command only, so creating a draft cannot publish a
523
+ // database or retire historical files behind the operator's back.
575
524
  return {
576
525
  result: errorResult(
577
- layout.layout === "recovery_required" ? "layout_recovery_required" : "layout_migration_blocked",
578
- migration.reason ?? layout.reason ?? "storage layout is not ready",
526
+ layout.layout === "recovery_required" ? "layout_recovery_required" : "layout_migration_required",
527
+ `${layout.reason ?? "storage layout is not ready"}; run imm-kernel migrate --storage-layout first`,
579
528
  1,
580
529
  ),
581
530
  journal: journalFor(
@@ -584,7 +533,7 @@ function runIntentAuthor(args: string[], root: string): KernelExecution {
584
533
  "rejected",
585
534
  "source_invalid",
586
535
  null,
587
- "Resolve the reported storage layout condition before authoring.",
536
+ "Run imm-kernel migrate --storage-layout, commit the affected paths, then retry intent author.",
588
537
  ),
589
538
  };
590
539
  }
@@ -760,7 +709,7 @@ function runIntentAuthor(args: string[], root: string): KernelExecution {
760
709
  return {
761
710
  result: errorResult(
762
711
  "intent_invalid",
763
- `candidate acceptance verification failed strict verification_descriptor/v1 parsing: ${error instanceof Error ? error.message : error}`,
712
+ `candidate acceptance verification failed strict verification_descriptor/v2 parsing: ${error instanceof Error ? error.message : error}`,
764
713
  1,
765
714
  ),
766
715
  journal: journalFor(
@@ -769,7 +718,7 @@ function runIntentAuthor(args: string[], root: string): KernelExecution {
769
718
  "rejected",
770
719
  "intent_invalid",
771
720
  null,
772
- "Fix the reported verification_descriptor/v1 violations and retry.",
721
+ "Fix the reported verification_descriptor/v2 violations and retry.",
773
722
  ),
774
723
  };
775
724
  }
@@ -1132,6 +1081,29 @@ function runIntentValidate(args: string[], root: string): KernelExecution {
1132
1081
  ),
1133
1082
  };
1134
1083
  }
1084
+ const specBinding = inspectSpecBinding(intent);
1085
+ if (!specBinding.ok) {
1086
+ return {
1087
+ result: jsonResult(
1088
+ {
1089
+ contract: "assurance_kernel/intent_validation/v1",
1090
+ valid: false,
1091
+ path: relative,
1092
+ task_id: intent.task_id,
1093
+ reason: specBinding.message,
1094
+ },
1095
+ 0,
1096
+ ),
1097
+ journal: journalFor(
1098
+ "intent",
1099
+ null,
1100
+ "ok",
1101
+ "command_ok",
1102
+ null,
1103
+ null,
1104
+ ),
1105
+ };
1106
+ }
1135
1107
 
1136
1108
  const verification: Array<{ id: string; eligible: boolean; reason: string | null }> = [];
1137
1109
  let allEligible = true;
@@ -1244,6 +1216,25 @@ function executeKernelCommand(args: string[], root: string): KernelExecution {
1244
1216
  };
1245
1217
  return runInspect(root);
1246
1218
  }
1219
+ if (command === "migrate") {
1220
+ if (flags.length !== 1 || flags[0] !== "--storage-layout")
1221
+ return {
1222
+ result: errorResult(
1223
+ "invalid_command",
1224
+ "migrate accepts only --storage-layout",
1225
+ 2,
1226
+ ),
1227
+ journal: journalFor(
1228
+ command,
1229
+ null,
1230
+ "rejected",
1231
+ "invalid_command",
1232
+ null,
1233
+ "Run imm-kernel migrate --storage-layout.",
1234
+ ),
1235
+ };
1236
+ return runStorageLayoutMigration(root);
1237
+ }
1247
1238
  if (command === "audit") {
1248
1239
  if (args.length !== 2 || args[1] !== "--legacy")
1249
1240
  return {
@@ -1341,6 +1332,106 @@ function executeKernelCommand(args: string[], root: string): KernelExecution {
1341
1332
  };
1342
1333
  }
1343
1334
 
1335
+ /**
1336
+ * Explicit claimless storage-layout migration.
1337
+ *
1338
+ * The retired file store is converted here and nowhere else: this command never
1339
+ * authors an intent, never opens a task, and never needs an active claim, so a
1340
+ * worktree that is still on the retired layout has one reachable entry point.
1341
+ * Mutating commands keep their fail-closed gate; this is the command that
1342
+ * resolves it.
1343
+ */
1344
+ function runStorageLayoutMigration(root: string): KernelExecution {
1345
+ const inspection = inspectStorageLayout(root);
1346
+ // Only a live owner blocks the command. Every other diagnosis is handed to
1347
+ // the migrator, which owns the recovery decisions: an interrupted
1348
+ // publication shows both stores and must stay reachable through this CLI.
1349
+ if (inspection.layout === "migration_blocked_active")
1350
+ return {
1351
+ result: errorResult(
1352
+ "layout_migration_blocked",
1353
+ inspection.reason ?? "a live legacy task still owns work; settle or stop it on the prior runtime first",
1354
+ 1,
1355
+ ),
1356
+ journal: journalFor(
1357
+ "migrate",
1358
+ null,
1359
+ "rejected",
1360
+ "source_invalid",
1361
+ null,
1362
+ "Resolve the reported layout condition, then rerun imm-kernel migrate --storage-layout.",
1363
+ ),
1364
+ };
1365
+ const migration = migrateLegacyLayout(root);
1366
+ if (migration.outcome === "migrated")
1367
+ return {
1368
+ result: jsonResult({
1369
+ contract: "assurance_kernel/migration_completed/v1",
1370
+ operation: "storage layout migration",
1371
+ affected_paths: migration.affected_paths,
1372
+ next_action: "commit the affected migration paths, then retry the original command",
1373
+ }),
1374
+ journal: journalFor(
1375
+ "migrate",
1376
+ null,
1377
+ "escalated",
1378
+ "migration_ambiguous",
1379
+ null,
1380
+ "Commit the affected migration paths, then retry the original command.",
1381
+ ),
1382
+ };
1383
+ if (migration.outcome === "migration_uncommitted")
1384
+ return {
1385
+ result: jsonResult({
1386
+ contract: "assurance_kernel/migration_pending_commit/v1",
1387
+ operation: "storage layout migration",
1388
+ affected_paths: migration.affected_paths,
1389
+ reason: migration.reason,
1390
+ next_action: "commit the preserved audit evidence, then rerun imm-kernel migrate --storage-layout",
1391
+ }),
1392
+ journal: journalFor(
1393
+ "migrate",
1394
+ null,
1395
+ "escalated",
1396
+ "migration_ambiguous",
1397
+ null,
1398
+ "Commit the preserved audit evidence, then rerun imm-kernel migrate --storage-layout.",
1399
+ ),
1400
+ };
1401
+ if (migration.outcome === "already_migrated")
1402
+ return {
1403
+ result: jsonResult({
1404
+ contract: "assurance_kernel/migration_completed/v1",
1405
+ operation: "storage layout migration",
1406
+ affected_paths: [],
1407
+ next_action: "retry the original command",
1408
+ }),
1409
+ journal: journalFor(
1410
+ "migrate",
1411
+ null,
1412
+ "ok",
1413
+ "command_ok",
1414
+ null,
1415
+ "Retry the original command.",
1416
+ ),
1417
+ };
1418
+ return {
1419
+ result: errorResult(
1420
+ "layout_migration_blocked",
1421
+ migration.reason ?? "the storage layout migration did not complete",
1422
+ 1,
1423
+ ),
1424
+ journal: journalFor(
1425
+ "migrate",
1426
+ null,
1427
+ "rejected",
1428
+ "source_invalid",
1429
+ null,
1430
+ "Resolve the reported layout condition, then rerun imm-kernel migrate --storage-layout.",
1431
+ ),
1432
+ };
1433
+ }
1434
+
1344
1435
  export function runKernelCommand(
1345
1436
  args: string[],
1346
1437
  root = process.cwd(),