magus-cli 7.8.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 (78) hide show
  1. package/README.md +1 -1
  2. package/package.json +4 -4
  3. package/src/__tests__/blackbox-parity.test.ts +16 -11
  4. package/src/__tests__/blind/plugin-deps/doctor.test.ts +622 -0
  5. package/src/__tests__/blind/plugin-deps/helpers.ts +340 -0
  6. package/src/__tests__/blind/plugin-deps/hook.test.ts +328 -0
  7. package/src/__tests__/blind/plugin-deps/probe.test.ts +694 -0
  8. package/src/__tests__/blind/plugin-deps/read-only.test.ts +96 -0
  9. package/src/__tests__/blind/plugin-deps/schema.test.ts +390 -0
  10. package/src/__tests__/blind-780-cli-tools.test.ts +36 -48
  11. package/src/__tests__/blind-780-review2.test.ts +0 -25
  12. package/src/__tests__/cli-apply-seams.test.ts +2 -67
  13. package/src/__tests__/cli-tool-commands.test.ts +131 -6
  14. package/src/__tests__/cli-tools-adapter.test.ts +52 -2
  15. package/src/__tests__/cli-tools-plugin-managed.test.tsx +83 -0
  16. package/src/__tests__/deps-adapter.test.ts +191 -0
  17. package/src/__tests__/deps-check-hook.test.ts +220 -0
  18. package/src/__tests__/deps-plan.test.ts +896 -0
  19. package/src/__tests__/deps-report.test.ts +197 -0
  20. package/src/__tests__/doctor-bins.test.ts +134 -36
  21. package/src/__tests__/doctor-json.test.ts +261 -0
  22. package/src/__tests__/failure-popup-review2.test.tsx +1 -25
  23. package/src/__tests__/final-fixes-780.test.tsx +25 -9
  24. package/src/__tests__/fixtures/bins.ts +55 -0
  25. package/src/__tests__/install-plan.test.ts +15 -1
  26. package/src/__tests__/marketplace-refresh.test.ts +9 -3
  27. package/src/__tests__/no-shell-spawn.test.ts +77 -0
  28. package/src/__tests__/npm-package-name.test.ts +6 -9
  29. package/src/__tests__/plugin-requires.test.ts +138 -153
  30. package/src/__tests__/requires-probe.test.ts +858 -0
  31. package/src/__tests__/resolver.test.ts +129 -52
  32. package/src/__tests__/run.test.ts +108 -0
  33. package/src/__tests__/tool-probe.test.ts +1 -1
  34. package/src/__tests__/toolchain.test.ts +123 -52
  35. package/src/__tests__/update-plan.test.ts +1 -1
  36. package/src/cli/ansi.ts +2 -7
  37. package/src/cli/deps-view.ts +213 -0
  38. package/src/cli/doctor.ts +169 -24
  39. package/src/cli/install.ts +51 -66
  40. package/src/cli/profile.ts +20 -2
  41. package/src/cli/router.ts +6 -2
  42. package/src/cli/update.ts +28 -7
  43. package/src/data/cli-tools.ts +24 -9
  44. package/src/services/active-closure.ts +3 -3
  45. package/src/services/claude-settings.ts +4 -348
  46. package/src/services/cli-tool-commands.ts +104 -3
  47. package/src/services/deps-plan.ts +962 -0
  48. package/src/services/deps-report.ts +265 -0
  49. package/src/services/doctor-bins.ts +115 -43
  50. package/src/services/install-plan.ts +11 -1
  51. package/src/services/local-marketplace.ts +12 -206
  52. package/src/services/marketplace-refresh.ts +4 -4
  53. package/src/services/plugin-manager.ts +4 -18
  54. package/src/services/plugin-requires.ts +93 -162
  55. package/src/services/resolver.ts +168 -58
  56. package/src/services/tool-probe.ts +18 -25
  57. package/src/services/toolchain.ts +117 -111
  58. package/src/services/update-engine.ts +19 -14
  59. package/src/services/update-plan.ts +3 -3
  60. package/src/shared/plugin/hooks/bun-missing.sh +39 -0
  61. package/src/shared/plugin/hooks/deps-check.ts +224 -0
  62. package/src/shared/plugin/hooks/lib/requires-probe.ts +1183 -0
  63. package/src/types/index.ts +53 -16
  64. package/src/ui/App.tsx +6 -40
  65. package/src/ui/adapters/cliToolsAdapter.ts +75 -37
  66. package/src/ui/adapters/depsAdapter.ts +129 -0
  67. package/src/ui/adapters/startupReports.ts +0 -22
  68. package/src/ui/renderers/cliToolRenderers.tsx +135 -2
  69. package/src/ui/screens/CliToolsScreen.tsx +141 -51
  70. package/src/ui/screens/PluginsScreen.tsx +12 -48
  71. package/src/utils/command-utils.ts +4 -5
  72. package/src/utils/run.ts +123 -52
  73. package/src/utils/string-utils.ts +9 -0
  74. package/src/__tests__/go-module.test.ts +0 -43
  75. package/src/__tests__/plugin-setup.test.ts +0 -1016
  76. package/src/__tests__/shell-script-callers.test.ts +0 -92
  77. package/src/services/plugin-setup.ts +0 -965
  78. package/src/utils/go-module.ts +0 -36
@@ -1,92 +0,0 @@
1
- /**
2
- * `runShellScript` has exactly one legitimate caller, and this pins it.
3
- *
4
- * The whole of item 3 is the split between two ways of running a child process:
5
- * argv (`runCommand`), which no shell ever sees, and a script (`runShellScript`),
6
- * which `/bin/sh` parses. Every installer command belongs to the first, because
7
- * it is assembled from package names that arrive in `.claude/profiles.json` and
8
- * plugin `requires.bin` — hand-authored, committed by teammates, fetched from
9
- * marketplaces, validated by nothing. The second exists only for the two
10
- * `TOOLCHAIN_BOOTSTRAP` values, which are constants in this repo copied from
11
- * bun.sh and brew.sh and which genuinely contain a pipe and a command
12
- * substitution.
13
- *
14
- * Nothing in the type system distinguishes them — both are strings — so after
15
- * the commit lands, the design decision is enforced by this test or by nothing.
16
- * A branded `ShellScript` type would enforce it at compile time and was
17
- * considered; for one map, two entries and one call site it is more machinery
18
- * than the rule is worth, and unlike a brand this is greppable.
19
- *
20
- * Source-scanning precedent in this suite: `uppercase-keybindings.test.ts`.
21
- */
22
-
23
- import { describe, expect, test } from "bun:test";
24
- import path from "node:path";
25
- import fs from "fs-extra";
26
-
27
- const SRC_DIR = path.join(import.meta.dir, "..");
28
-
29
- /** Files permitted to call `runShellScript`, relative to `src/`. */
30
- const ALLOWED = ["cli/install.ts"];
31
-
32
- /** The definition itself, plus this test, are not callers. */
33
- const NOT_CALLERS = ["utils/run.ts", "__tests__/shell-script-callers.test.ts"];
34
-
35
- async function sourceFiles(dir: string): Promise<string[]> {
36
- const out: string[] = [];
37
- for (const entry of await fs.readdir(dir, { withFileTypes: true })) {
38
- const full = path.join(dir, entry.name);
39
- if (entry.isDirectory()) out.push(...(await sourceFiles(full)));
40
- else if (/\.tsx?$/.test(entry.name)) out.push(full);
41
- }
42
- return out;
43
- }
44
-
45
- const isComment = (line: string) => {
46
- const t = line.trim();
47
- return t.startsWith("//") || t.startsWith("*") || t.startsWith("/*");
48
- };
49
-
50
- async function callersOf(pattern: RegExp): Promise<string[]> {
51
- const found = new Set<string>();
52
- for (const file of await sourceFiles(SRC_DIR)) {
53
- const rel = path.relative(SRC_DIR, file);
54
- if (NOT_CALLERS.includes(rel)) continue;
55
- const text = await fs.readFile(file, "utf8");
56
- for (const line of text.split("\n")) {
57
- if (isComment(line)) continue;
58
- if (pattern.test(line)) found.add(rel);
59
- }
60
- }
61
- return [...found].sort();
62
- }
63
-
64
- describe("only the toolchain bootstrap goes through a shell", () => {
65
- test("runShellScript is called from exactly the allowed files", async () => {
66
- expect(await callersOf(/\brunShellScript\(/)).toEqual(ALLOWED);
67
- });
68
-
69
- test("nothing spawns with a shell outside utils/run.ts", async () => {
70
- // Catches someone reaching for `spawn`/`exec` directly rather than
71
- // through the seam — a second shell path that never names
72
- // `runShellScript`.
73
- //
74
- // Both spellings: `shell: true` and a named shell (`shell: "/bin/bash"`).
75
- // The CLI Tools screen used the second for its version probe (`which -a`
76
- // pipelines, a string-form `exec` of each check command); that probe now
77
- // lives in services/tool-probe.ts and runs argv only. `shell: false` and
78
- // the alias writer's `shell: ShellKind` values are not spawn options and
79
- // do not match.
80
- expect(await callersOf(/shell:\s*(true|["'`])/)).toEqual([]);
81
- });
82
-
83
- test("the scan can actually fail", async () => {
84
- // Negative control. The two assertions above pass trivially if the walk
85
- // finds nothing or the pattern never matches, and a check that cannot
86
- // fail is not evidence. `runCommand(` is known to be called from several
87
- // files, so a working scan must find them.
88
- const runCommandCallers = await callersOf(/\brunCommand\(/);
89
- expect(runCommandCallers.length).toBeGreaterThan(0);
90
- expect(runCommandCallers).toContain("cli/install.ts");
91
- });
92
- });