magus-cli 7.7.0 → 7.9.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 (140) hide show
  1. package/README.md +1 -1
  2. package/package.json +4 -4
  3. package/src/__tests__/blackbox-parity.test.ts +45 -26
  4. package/src/__tests__/blackbox-plugin-state.test.ts +25 -6
  5. package/src/__tests__/blind/plugin-deps/doctor.test.ts +622 -0
  6. package/src/__tests__/blind/plugin-deps/helpers.ts +340 -0
  7. package/src/__tests__/blind/plugin-deps/hook.test.ts +328 -0
  8. package/src/__tests__/blind/plugin-deps/probe.test.ts +694 -0
  9. package/src/__tests__/blind/plugin-deps/read-only.test.ts +96 -0
  10. package/src/__tests__/blind/plugin-deps/schema.test.ts +390 -0
  11. package/src/__tests__/blind-780-cli-tools.test.ts +796 -0
  12. package/src/__tests__/blind-780-deprecated.test.ts +631 -0
  13. package/src/__tests__/blind-780-failure-reasons.test.ts +1004 -0
  14. package/src/__tests__/blind-780-plugin-resolution.test.ts +431 -0
  15. package/src/__tests__/blind-780-review2.test.ts +1178 -0
  16. package/src/__tests__/cli-apply-seams.test.ts +2 -67
  17. package/src/__tests__/cli-tool-commands.test.ts +131 -6
  18. package/src/__tests__/cli-tools-adapter.test.ts +52 -2
  19. package/src/__tests__/cli-tools-plugin-managed.test.tsx +83 -0
  20. package/src/__tests__/cli-update-view.test.ts +3 -3
  21. package/src/__tests__/deprecated-remove.test.ts +827 -0
  22. package/src/__tests__/deps-adapter.test.ts +191 -0
  23. package/src/__tests__/deps-check-hook.test.ts +220 -0
  24. package/src/__tests__/deps-plan.test.ts +896 -0
  25. package/src/__tests__/deps-report.test.ts +197 -0
  26. package/src/__tests__/doctor-bins.test.ts +134 -36
  27. package/src/__tests__/doctor-json.test.ts +261 -0
  28. package/src/__tests__/doctor.test.ts +159 -1
  29. package/src/__tests__/failure-popup-review2.test.tsx +896 -0
  30. package/src/__tests__/failure-popup.test.tsx +419 -0
  31. package/src/__tests__/final-fixes-780.test.tsx +740 -0
  32. package/src/__tests__/fixtures/bins.ts +55 -0
  33. package/src/__tests__/format-update-outcome.test.ts +6 -32
  34. package/src/__tests__/gitignore-profile.test.ts +1 -9
  35. package/src/__tests__/install-plan.test.ts +15 -1
  36. package/src/__tests__/marketplace-refresh.test.ts +9 -3
  37. package/src/__tests__/models-screen-state.test.ts +18 -40
  38. package/src/__tests__/no-shell-spawn.test.ts +77 -0
  39. package/src/__tests__/npm-package-name.test.ts +6 -9
  40. package/src/__tests__/plugin-requires.test.ts +138 -153
  41. package/src/__tests__/plugin-resolution.test.ts +52 -13
  42. package/src/__tests__/plugin-row-text.test.ts +30 -37
  43. package/src/__tests__/profile-dependencies.test.ts +7 -0
  44. package/src/__tests__/profile-startup-old-format.test.ts +0 -3
  45. package/src/__tests__/profile-startup.test.ts +40 -12
  46. package/src/__tests__/requires-probe.test.ts +858 -0
  47. package/src/__tests__/resolver.test.ts +129 -52
  48. package/src/__tests__/run.test.ts +108 -0
  49. package/src/__tests__/stale-load-repair.test.ts +31 -23
  50. package/src/__tests__/tool-probe.test.ts +1 -1
  51. package/src/__tests__/toolchain.test.ts +123 -52
  52. package/src/__tests__/update-apply.test.ts +13 -29
  53. package/src/__tests__/update-plan.test.ts +24 -18
  54. package/src/__tests__/useStaleLoadModal.test.ts +1 -57
  55. package/src/__tests__/version-unknown-state.test.ts +15 -17
  56. package/src/cli/ansi.ts +2 -7
  57. package/src/cli/deps-view.ts +213 -0
  58. package/src/cli/doctor.ts +320 -54
  59. package/src/cli/install.ts +55 -71
  60. package/src/cli/profile.ts +20 -2
  61. package/src/cli/router.ts +6 -2
  62. package/src/cli/update-view.ts +58 -15
  63. package/src/cli/update.ts +55 -12
  64. package/src/data/cli-tools.ts +24 -9
  65. package/src/services/active-closure.ts +3 -3
  66. package/src/services/catalog-cache-store.ts +8 -6
  67. package/src/services/claude-cli.ts +106 -19
  68. package/src/services/claude-settings.ts +88 -384
  69. package/src/services/cli-tool-commands.ts +104 -3
  70. package/src/services/deps-plan.ts +962 -0
  71. package/src/services/deps-report.ts +265 -0
  72. package/src/services/doctor-bins.ts +115 -43
  73. package/src/services/install-plan.ts +11 -1
  74. package/src/services/local-marketplace.ts +12 -206
  75. package/src/services/marketplace-refresh.ts +4 -4
  76. package/src/services/plugin-env-needs.ts +69 -0
  77. package/src/services/plugin-manager.ts +35 -37
  78. package/src/services/plugin-requires.ts +93 -162
  79. package/src/services/plugin-resolution.ts +34 -42
  80. package/src/services/profile-activate.ts +1 -2
  81. package/src/services/profile-startup.ts +18 -43
  82. package/src/services/profile-state.ts +72 -2
  83. package/src/services/resolver.ts +263 -59
  84. package/src/services/tool-probe.ts +18 -25
  85. package/src/services/toolchain.ts +117 -111
  86. package/src/services/update-engine.ts +345 -45
  87. package/src/services/update-plan.ts +296 -36
  88. package/src/shared/plugin/hooks/bun-missing.sh +39 -0
  89. package/src/shared/plugin/hooks/deps-check.ts +224 -0
  90. package/src/shared/plugin/hooks/lib/requires-probe.ts +1183 -0
  91. package/src/types/index.ts +60 -16
  92. package/src/ui/App.tsx +81 -171
  93. package/src/ui/adapters/cliToolsAdapter.ts +252 -12
  94. package/src/ui/adapters/depsAdapter.ts +129 -0
  95. package/src/ui/adapters/failureReport.ts +137 -0
  96. package/src/ui/adapters/pluginsAdapter.ts +297 -45
  97. package/src/ui/adapters/startupReports.ts +260 -0
  98. package/src/ui/components/modals/FailureListModal.tsx +231 -0
  99. package/src/ui/components/modals/MessageModal.tsx +7 -12
  100. package/src/ui/components/modals/ModalContainer.tsx +10 -5
  101. package/src/ui/components/modals/index.ts +1 -0
  102. package/src/ui/hooks/startupQueue.ts +56 -0
  103. package/src/ui/hooks/useGitignoreModal.ts +30 -52
  104. package/src/ui/hooks/useProfileStartupModal.ts +119 -142
  105. package/src/ui/hooks/useStaleLoadModal.ts +35 -65
  106. package/src/ui/keymap.ts +14 -1
  107. package/src/ui/renderers/cliToolRenderers.tsx +135 -2
  108. package/src/ui/renderers/mcpRenderers.tsx +110 -3
  109. package/src/ui/renderers/pluginRenderers.tsx +77 -6
  110. package/src/ui/renderers/pluginRowText.ts +25 -25
  111. package/src/ui/renderers/pluginStatusText.ts +18 -1
  112. package/src/ui/screens/AliasScreen.tsx +38 -45
  113. package/src/ui/screens/CliToolsScreen.tsx +199 -98
  114. package/src/ui/screens/EnvVarsScreen.tsx +17 -5
  115. package/src/ui/screens/GitignoreScreen.tsx +48 -67
  116. package/src/ui/screens/McpRegistryScreen.tsx +67 -38
  117. package/src/ui/screens/McpScreen.tsx +46 -19
  118. package/src/ui/screens/ModelsScreen.tsx +46 -86
  119. package/src/ui/screens/PluginsScreen.tsx +315 -259
  120. package/src/ui/screens/ProfilesScreen.tsx +79 -40
  121. package/src/ui/screens/SkillsScreen.tsx +83 -80
  122. package/src/ui/screens/StylesScreen.tsx +211 -275
  123. package/src/ui/state/AppContext.tsx +66 -44
  124. package/src/ui/state/DimensionsContext.tsx +3 -22
  125. package/src/ui/state/reducer.ts +12 -100
  126. package/src/ui/state/types.ts +48 -69
  127. package/src/utils/command-utils.ts +4 -5
  128. package/src/utils/run.ts +123 -52
  129. package/src/utils/string-utils.ts +9 -0
  130. package/src/utils/user-path.ts +60 -0
  131. package/src/__tests__/go-module.test.ts +0 -43
  132. package/src/__tests__/notices-rules.test.ts +0 -476
  133. package/src/__tests__/notices.test.tsx +0 -604
  134. package/src/__tests__/plugin-setup.test.ts +0 -1016
  135. package/src/__tests__/shell-script-callers.test.ts +0 -92
  136. package/src/__tests__/styles-status-line.test.ts +0 -72
  137. package/src/__tests__/version-snapshot.test.ts +0 -212
  138. package/src/services/plugin-setup.ts +0 -965
  139. package/src/services/version-snapshot.ts +0 -189
  140. package/src/utils/go-module.ts +0 -36
@@ -137,7 +137,7 @@ describe("detectProfileStartupNeed", () => {
137
137
  expect(describeNeed(need).message).toContain('"gone"');
138
138
  });
139
139
 
140
- test("the TUI startup runs the gate first and reports what it absorbed", async () => {
140
+ test("the TUI startup runs the gate first, absorbing edits into the profile", async () => {
141
141
  await fs.outputJson(join(project, ".claude", "profiles.json"), LEAN);
142
142
  await activateProfile(LEAN, "lean", project, { onDisplace: () => {} });
143
143
  const live = join(project, ".claude", "settings.json");
@@ -145,10 +145,13 @@ describe("detectProfileStartupNeed", () => {
145
145
  settings.enabledPlugins["code-search@magus"] = true;
146
146
  await fs.writeFile(live, JSON.stringify(settings));
147
147
 
148
- const { need, notices } = await prepareProfileStartup(project);
148
+ const { need } = await prepareProfileStartup(project);
149
149
 
150
150
  expect(need.state).toBe("ok");
151
- expect(notices).toEqual(['Added code-search@magus to profile "lean"']);
151
+ const manifest = await fs.readJson(
152
+ join(project, ".claude", "profiles.json"),
153
+ );
154
+ expect(manifest.profiles.lean.plugins["code-search@magus"]).toBeTruthy();
152
155
  });
153
156
 
154
157
  test("what is enabled never changes the answer", async () => {
@@ -403,46 +406,71 @@ describe("a failure that already moved something", () => {
403
406
  link: `/p/.claude/${name}`,
404
407
  savedTo: `/p/.claude/.magus-backups/S/${name}`,
405
408
  });
409
+ const lean = { kind: "activate" as const, id: "lean" };
410
+ /** Everything the failure popup says, as one string. */
411
+ const said = (report: ReturnType<typeof describeFailure>): string =>
412
+ [
413
+ report.headline,
414
+ ...report.rows.map((r) => `${r.subject} ${r.reason} ${r.fix ?? ""}`),
415
+ report.fix ?? "",
416
+ ].join("\n");
406
417
 
407
418
  test("a true no-op says so", () => {
408
- const msg = describeFailure(new Error("boom"), [], "/p", null);
419
+ const report = describeFailure(new Error("boom"), [], "/p", null, lean);
420
+ expect(report.headline).toBe('Profile "lean" was not activated');
421
+ const msg = said(report);
409
422
  expect(msg).toContain("boom");
410
423
  expect(msg).toContain("exactly as it was");
411
424
  });
412
425
 
426
+ test("an adoption that failed says the profile was not created", () => {
427
+ const report = describeFailure(new Error("boom"), [], "/p", null, {
428
+ kind: "adopt",
429
+ id: "default",
430
+ name: "Mine",
431
+ });
432
+ expect(report.headline).toBe('Profile "Mine" was not created');
433
+ });
434
+
413
435
  test("a partial failure never claims nothing happened", () => {
414
436
  // Activation moves up to four artifacts in sequence and settings.json goes
415
437
  // FIRST, so a throw on the second leaves it already in the backup. The old
416
438
  // message said "Nothing was activated" unconditionally — false about the
417
439
  // user's own file, and `.magus-backups/` is gitignored, so git status
418
440
  // showed the deletion with no sign of the copy.
419
- const msg = describeFailure(
441
+ const report = describeFailure(
420
442
  new Error("EACCES: skills"),
421
443
  [at("settings.json")],
422
444
  "/p",
423
445
  "lean",
446
+ lean,
424
447
  );
448
+ const msg = said(report);
425
449
 
426
- expect(msg).not.toContain("Nothing was moved");
450
+ expect(msg.toLowerCase()).not.toContain("nothing was moved");
427
451
  expect(msg).not.toContain("exactly as it was");
428
- // It must name where the file went, project-relative.
429
- expect(msg).toContain(".claude/settings.json");
430
- expect(msg).toContain(".claude/.magus-backups/S/settings.json");
452
+ // It must name where the file went, project-relative: one row per file.
453
+ expect(report.rows).toContainEqual({
454
+ subject: ".claude/settings.json",
455
+ reason: "is kept at .claude/.magus-backups/S/settings.json",
456
+ });
431
457
  });
432
458
 
433
459
  test("it warns against the re-attempt that would capture an empty set", () => {
434
460
  // Re-choosing save-what-you-have runs adoption again, and adoption reads
435
461
  // settings.json — now in the backup. It would capture an empty plugin set
436
462
  // into a second profile and call that the user's setup.
437
- const msg = describeFailure(
463
+ const report = describeFailure(
438
464
  new Error("boom"),
439
465
  [at("settings.json")],
440
466
  "/p",
441
467
  "lean",
468
+ lean,
442
469
  );
443
470
 
444
- expect(msg).toContain("Do NOT save-what-you-have");
445
- expect(msg).toContain("Activating lean again is safe");
471
+ // The fix line, said once under the rows.
472
+ expect(report.fix).toContain("Do NOT save-what-you-have");
473
+ expect(report.fix).toContain("Activating lean again is safe");
446
474
  });
447
475
  });
448
476