movehat 0.2.2 → 0.2.4

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 (74) hide show
  1. package/dist/cli.js +4 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/compile.d.ts.map +1 -1
  4. package/dist/commands/compile.js +19 -10
  5. package/dist/commands/compile.js.map +1 -1
  6. package/dist/commands/test.js +12 -19
  7. package/dist/commands/test.js.map +1 -1
  8. package/dist/core/Publisher.d.ts.map +1 -1
  9. package/dist/core/Publisher.js +20 -14
  10. package/dist/core/Publisher.js.map +1 -1
  11. package/dist/core/config.d.ts.map +1 -1
  12. package/dist/core/config.js +8 -5
  13. package/dist/core/config.js.map +1 -1
  14. package/dist/core/deployments.d.ts.map +1 -1
  15. package/dist/core/deployments.js +4 -2
  16. package/dist/core/deployments.js.map +1 -1
  17. package/dist/fork/manager.d.ts +1 -1
  18. package/dist/fork/manager.js +11 -11
  19. package/dist/fork/manager.js.map +1 -1
  20. package/dist/fork/server.d.ts.map +1 -1
  21. package/dist/fork/server.js +21 -15
  22. package/dist/fork/server.js.map +1 -1
  23. package/dist/fork/test.d.ts.map +1 -1
  24. package/dist/fork/test.js +3 -2
  25. package/dist/fork/test.js.map +1 -1
  26. package/dist/harness/codeObject.js +11 -8
  27. package/dist/harness/codeObject.js.map +1 -1
  28. package/dist/harness/script.d.ts.map +1 -1
  29. package/dist/harness/script.js +9 -6
  30. package/dist/harness/script.js.map +1 -1
  31. package/dist/helpers/setupLocalTesting.js +5 -5
  32. package/dist/helpers/setupLocalTesting.js.map +1 -1
  33. package/dist/node/LocalNodeManager.d.ts +1 -1
  34. package/dist/node/LocalNodeManager.d.ts.map +1 -1
  35. package/dist/node/LocalNodeManager.js +61 -23
  36. package/dist/node/LocalNodeManager.js.map +1 -1
  37. package/dist/node/__tests__/LocalNodeManager.test.js +110 -11
  38. package/dist/node/__tests__/LocalNodeManager.test.js.map +1 -1
  39. package/dist/ui/__tests__/logger.test.d.ts +2 -0
  40. package/dist/ui/__tests__/logger.test.d.ts.map +1 -0
  41. package/dist/ui/__tests__/logger.test.js +75 -0
  42. package/dist/ui/__tests__/logger.test.js.map +1 -0
  43. package/dist/ui/formatters.d.ts +0 -16
  44. package/dist/ui/formatters.d.ts.map +1 -1
  45. package/dist/ui/formatters.js +1 -1
  46. package/dist/ui/formatters.js.map +1 -1
  47. package/dist/ui/logger.d.ts +41 -0
  48. package/dist/ui/logger.d.ts.map +1 -1
  49. package/dist/ui/logger.js +49 -0
  50. package/dist/ui/logger.js.map +1 -1
  51. package/dist/ui/spinner.d.ts +25 -0
  52. package/dist/ui/spinner.d.ts.map +1 -1
  53. package/dist/ui/spinner.js +44 -0
  54. package/dist/ui/spinner.js.map +1 -1
  55. package/package.json +1 -1
  56. package/src/cli.ts +4 -0
  57. package/src/commands/compile.ts +24 -15
  58. package/src/commands/test.ts +12 -19
  59. package/src/core/Publisher.ts +49 -34
  60. package/src/core/config.ts +9 -6
  61. package/src/core/deployments.ts +5 -4
  62. package/src/fork/manager.ts +11 -11
  63. package/src/fork/server.ts +21 -15
  64. package/src/fork/test.ts +3 -2
  65. package/src/harness/codeObject.ts +8 -5
  66. package/src/harness/script.ts +7 -4
  67. package/src/helpers/setupLocalTesting.ts +5 -5
  68. package/src/node/LocalNodeManager.ts +64 -25
  69. package/src/node/__tests__/LocalNodeManager.test.ts +140 -14
  70. package/src/types/config.ts +1 -1
  71. package/src/ui/__tests__/logger.test.ts +89 -0
  72. package/src/ui/formatters.ts +1 -1
  73. package/src/ui/logger.ts +62 -0
  74. package/src/ui/spinner.ts +47 -0
@@ -2,6 +2,13 @@
2
2
  * Available log levels
3
3
  */
4
4
  export type LogLevel = 'info' | 'success' | 'error' | 'warning' | 'debug';
5
+ /**
6
+ * Verbosity level for subprocess output and gray-prefixed chatter.
7
+ * - `quiet` — reserved; currently behaves like `normal`
8
+ * - `normal` — default; system logs only, subprocess chatter hidden
9
+ * - `verbose` — surface subprocess stdout with a muted gray `›` prefix
10
+ */
11
+ export type Verbosity = 'quiet' | 'normal' | 'verbose';
5
12
  /**
6
13
  * Logger configuration options
7
14
  */
@@ -12,7 +19,16 @@ export interface LoggerConfig {
12
19
  level?: LogLevel;
13
20
  /** Include timestamps in log messages */
14
21
  timestamp?: boolean;
22
+ /** Verbosity level for subprocess output */
23
+ verbosity?: Verbosity;
15
24
  }
25
+ /**
26
+ * Whether subprocess chatter should reach the user's terminal.
27
+ * Honors both the in-process config (set by the `-v` CLI flag's
28
+ * preAction hook) and the `MOVEHAT_VERBOSE=1` env var (which lets
29
+ * callers opt in before the CLI parses args, e.g. in shell scripts).
30
+ */
31
+ export declare const isVerbose: () => boolean;
16
32
  /**
17
33
  * Configure logger globally
18
34
  *
@@ -124,6 +140,28 @@ export declare const newline: () => void;
124
140
  * logger.kv('Network', 'testnet', 2);
125
141
  */
126
142
  export declare const section: (title: string) => void;
143
+ /**
144
+ * Single muted horizontal rule. Use to close out a phase or to
145
+ * visually separate output sections.
146
+ */
147
+ export declare const divider: () => void;
148
+ /**
149
+ * Phase header — renders a muted top rule, a bold brand-colored title
150
+ * indented two spaces, and a muted bottom rule. Use at top-level phase
151
+ * boundaries (local node start, deploy flow, test orchestrator
152
+ * sections) so the user can visually anchor where one phase ends and
153
+ * the next begins.
154
+ *
155
+ * @param title - Phase title (e.g. "Local Movement node")
156
+ *
157
+ * @example
158
+ * logger.phase('Local Movement node');
159
+ * // Renders:
160
+ * // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
161
+ * // Local Movement node
162
+ * // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
163
+ */
164
+ export declare const phase: (title: string) => void;
127
165
  /**
128
166
  * Key-value pair
129
167
  * Use for displaying structured data
@@ -163,6 +201,7 @@ export declare const item: (text: string, indent?: number) => void;
163
201
  */
164
202
  export declare const logger: {
165
203
  configure: (newConfig: Partial<LoggerConfig>) => void;
204
+ isVerbose: () => boolean;
166
205
  info: (message: string, indent?: number) => void;
167
206
  success: (message: string, indent?: number) => void;
168
207
  error: (message: string, indent?: number) => void;
@@ -171,6 +210,8 @@ export declare const logger: {
171
210
  plain: (message: string) => void;
172
211
  newline: () => void;
173
212
  section: (title: string) => void;
213
+ phase: (title: string) => void;
214
+ divider: () => void;
174
215
  kv: (key: string, value: string, indent?: number) => void;
175
216
  item: (text: string, indent?: number) => void;
176
217
  };
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/ui/logger.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,mCAAmC;IACnC,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,yCAAyC;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAWD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,GAAI,WAAW,OAAO,CAAC,YAAY,CAAC,KAAG,IAElE,CAAC;AAUF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,IAAI,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI1D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI7D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI3D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI7D,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,IAAI,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI1D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,GAAI,SAAS,MAAM,KAAG,IAGvC,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,QAAO,IAG1B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,GAAI,OAAO,MAAM,KAAG,IAGvC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,EAAE,GAAI,KAAK,MAAM,EAAE,OAAO,MAAM,EAAE,SAAQ,MAAU,KAAG,IAInE,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,EAAE,SAAQ,MAAU,KAAG,IAIvD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM;2BAlMwB,OAAO,CAAC,YAAY,CAAC,KAAG,IAAI;oBAuBzC,MAAM,WAAU,MAAM,KAAO,IAAI;uBAiB9B,MAAM,WAAU,MAAM,KAAO,IAAI;qBAiBnC,MAAM,WAAU,MAAM,KAAO,IAAI;uBAiB/B,MAAM,WAAU,MAAM,KAAO,IAAI;oBAqBpC,MAAM,WAAU,MAAM,KAAO,IAAI;qBAiBhC,MAAM,KAAG,IAAI;mBAcjB,IAAI;qBAgBA,MAAM,KAAG,IAAI;cAiBpB,MAAM,SAAS,MAAM,WAAU,MAAM,KAAO,IAAI;iBAmB7C,MAAM,WAAU,MAAM,KAAO,IAAI;CA4B3D,CAAC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/ui/logger.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,mCAAmC;IACnC,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,yCAAyC;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAYD;;;;;GAKG;AACH,eAAO,MAAM,SAAS,QAAO,OAC0C,CAAC;AAExE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,GAAI,WAAW,OAAO,CAAC,YAAY,CAAC,KAAG,IAElE,CAAC;AAUF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,IAAI,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI1D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI7D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI3D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI7D,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,IAAI,GAAI,SAAS,MAAM,EAAE,SAAQ,MAAU,KAAG,IAI1D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,GAAI,SAAS,MAAM,KAAG,IAGvC,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,QAAO,IAG1B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,GAAI,OAAO,MAAM,KAAG,IAGvC,CAAC;AAQF;;;GAGG;AACH,eAAO,MAAM,OAAO,QAAO,IAG1B,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,KAAG,IAMrC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,EAAE,GAAI,KAAK,MAAM,EAAE,OAAO,MAAM,EAAE,SAAQ,MAAU,KAAG,IAInE,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,EAAE,SAAQ,MAAU,KAAG,IAIvD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM;2BAzOwB,OAAO,CAAC,YAAY,CAAC,KAAG,IAAI;qBAf1C,OAAO;oBAsCN,MAAM,WAAU,MAAM,KAAO,IAAI;uBAiB9B,MAAM,WAAU,MAAM,KAAO,IAAI;qBAiBnC,MAAM,WAAU,MAAM,KAAO,IAAI;uBAiB/B,MAAM,WAAU,MAAM,KAAO,IAAI;oBAqBpC,MAAM,WAAU,MAAM,KAAO,IAAI;qBAiBhC,MAAM,KAAG,IAAI;mBAcjB,IAAI;qBAgBA,MAAM,KAAG,IAAI;mBAoCf,MAAM,KAAG,IAAI;mBArBf,IAAI;cAyCP,MAAM,SAAS,MAAM,WAAU,MAAM,KAAO,IAAI;iBAmB7C,MAAM,WAAU,MAAM,KAAO,IAAI;CA+B3D,CAAC"}
package/dist/ui/logger.js CHANGED
@@ -7,7 +7,15 @@ let config = {
7
7
  silent: false,
8
8
  level: 'info',
9
9
  timestamp: false,
10
+ verbosity: process.env.MOVEHAT_VERBOSE === '1' ? 'verbose' : 'normal',
10
11
  };
12
+ /**
13
+ * Whether subprocess chatter should reach the user's terminal.
14
+ * Honors both the in-process config (set by the `-v` CLI flag's
15
+ * preAction hook) and the `MOVEHAT_VERBOSE=1` env var (which lets
16
+ * callers opt in before the CLI parses args, e.g. in shell scripts).
17
+ */
18
+ export const isVerbose = () => config.verbosity === 'verbose' || process.env.MOVEHAT_VERBOSE === '1';
11
19
  /**
12
20
  * Configure logger globally
13
21
  *
@@ -165,6 +173,44 @@ export const section = (title) => {
165
173
  return;
166
174
  console.log(`\n${colors.brandBright(title)}`);
167
175
  };
176
+ /**
177
+ * Width of the `━` rule used by `phase` and `divider`. Matched to a
178
+ * comfortable terminal width that fits in a side-by-side dev layout.
179
+ */
180
+ const PHASE_RULE_WIDTH = 52;
181
+ /**
182
+ * Single muted horizontal rule. Use to close out a phase or to
183
+ * visually separate output sections.
184
+ */
185
+ export const divider = () => {
186
+ if (config.silent)
187
+ return;
188
+ console.log(colors.muted('━'.repeat(PHASE_RULE_WIDTH)));
189
+ };
190
+ /**
191
+ * Phase header — renders a muted top rule, a bold brand-colored title
192
+ * indented two spaces, and a muted bottom rule. Use at top-level phase
193
+ * boundaries (local node start, deploy flow, test orchestrator
194
+ * sections) so the user can visually anchor where one phase ends and
195
+ * the next begins.
196
+ *
197
+ * @param title - Phase title (e.g. "Local Movement node")
198
+ *
199
+ * @example
200
+ * logger.phase('Local Movement node');
201
+ * // Renders:
202
+ * // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
203
+ * // Local Movement node
204
+ * // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
205
+ */
206
+ export const phase = (title) => {
207
+ if (config.silent)
208
+ return;
209
+ const rule = colors.muted('━'.repeat(PHASE_RULE_WIDTH));
210
+ console.log(rule);
211
+ console.log(` ${colors.brandBright(title)}`);
212
+ console.log(rule);
213
+ };
168
214
  /**
169
215
  * Key-value pair
170
216
  * Use for displaying structured data
@@ -214,6 +260,7 @@ export const item = (text, indent = 0) => {
214
260
  */
215
261
  export const logger = {
216
262
  configure: configureLogger,
263
+ isVerbose,
217
264
  info,
218
265
  success,
219
266
  error,
@@ -222,6 +269,8 @@ export const logger = {
222
269
  plain,
223
270
  newline,
224
271
  section,
272
+ phase,
273
+ divider,
225
274
  kv,
226
275
  item,
227
276
  };
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/ui/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAmBtD;;GAEG;AACH,IAAI,MAAM,GAAiB;IACzB,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,MAAM;IACb,SAAS,EAAE,KAAK;CACjB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,SAAgC,EAAQ,EAAE;IACxE,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;AACvC,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,aAAa,GAAG,CAAC,OAAe,EAAE,SAAiB,CAAC,EAAU,EAAE;IACpE,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnE,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,OAAe,EAAE,SAAiB,CAAC,EAAQ,EAAE;IAChE,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO;IAC1B,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC;AACvD,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,OAAe,EAAE,SAAiB,CAAC,EAAQ,EAAE;IACnE,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO;IAC1B,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,SAAS,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC;AAC1D,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,OAAe,EAAE,SAAiB,CAAC,EAAQ,EAAE;IACjE,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO;IAC1B,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACjD,OAAO,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC;AAC1D,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,OAAe,EAAE,SAAiB,CAAC,EAAQ,EAAE;IACnE,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO;IAC1B,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACjD,OAAO,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,SAAS,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC;AAC3D,CAAC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,OAAe,EAAE,SAAiB,CAAC,EAAQ,EAAE;IAChE,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO;IAC1B,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC;AAC1D,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,OAAe,EAAQ,EAAE;IAC7C,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO;IAC1B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACvB,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,GAAS,EAAE;IAChC,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO;IAC1B,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,KAAa,EAAQ,EAAE;IAC7C,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO;IAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAChD,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAW,EAAE,KAAa,EAAE,SAAiB,CAAC,EAAQ,EAAE;IACzE,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO;IAC1B,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;AACvD,CAAC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,SAAiB,CAAC,EAAQ,EAAE;IAC7D,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO;IAC1B,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;AACpD,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,SAAS,EAAE,eAAe;IAC1B,IAAI;IACJ,OAAO;IACP,KAAK;IACL,OAAO;IACP,IAAI;IACJ,KAAK;IACL,OAAO;IACP,OAAO;IACP,EAAE;IACF,IAAI;CACL,CAAC"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/ui/logger.ts"],"names":[],"mappings":"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"}
@@ -65,6 +65,31 @@ export declare const spinner: (options: SpinnerOptions) => Ora;
65
65
  * );
66
66
  */
67
67
  export declare const withSpinner: <T>(startText: string, task: () => Promise<T>, successText?: string, errorText?: string, indent?: number) => Promise<T>;
68
+ /**
69
+ * Execute async task with a spinner that updates its label with
70
+ * elapsed seconds while the task runs. Use for long-running phases
71
+ * (local node startup, publish + tx wait) where the user wants
72
+ * visible progress feedback in lieu of subprocess chatter.
73
+ *
74
+ * Pairs with the `§9` console-UX convention: any phase that
75
+ * empirically takes ≥3s in normal use should wrap its body in
76
+ * `withTimedSpinner` so the terminal never goes silent while work
77
+ * happens.
78
+ *
79
+ * @param label - Stable label shown next to the spinner (e.g. "Starting node")
80
+ * @param task - Async function to execute
81
+ * @param indent - Number of spaces to indent (default: 0)
82
+ * @returns Promise resolving to task result
83
+ *
84
+ * @example
85
+ * await withTimedSpinner('Starting local node', async () => {
86
+ * await this.waitForReady(60_000);
87
+ * });
88
+ * // Renders: ⠋ Starting local node — 0.0s ... ⠼ Starting local node — 14.2s
89
+ * // On success: ✔ Starting local node (14.2s)
90
+ * // On error: ✖ <error.message>
91
+ */
92
+ export declare const withTimedSpinner: <T>(label: string, task: () => Promise<T>, indent?: number) => Promise<T>;
68
93
  /**
69
94
  * Spinner chain for sequential operations
70
95
  * Manages multiple spinners in sequence
@@ -1 +1 @@
1
- {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA,OAAY,EAAE,KAAK,GAAG,EAAE,KAAK,OAAO,IAAI,UAAU,EAAE,MAAM,KAAK,CAAC;AAGhE;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAEvG;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAChC,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,OAAO,GAAI,SAAS,cAAc,KAAG,GAcjD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,WAAW,GAAU,CAAC,EACjC,WAAW,MAAM,EACjB,MAAM,MAAM,OAAO,CAAC,CAAC,CAAC,EACtB,cAAc,MAAM,EACpB,YAAY,MAAM,EAClB,SAAQ,MAAU,KACjB,OAAO,CAAC,CAAC,CAYX,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAE1E;;OAEG;IACH,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,kBAAkB,QAAO,YA0BrC,CAAC"}
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA,OAAY,EAAE,KAAK,GAAG,EAAE,KAAK,OAAO,IAAI,UAAU,EAAE,MAAM,KAAK,CAAC;AAGhE;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAEvG;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAChC,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,OAAO,GAAI,SAAS,cAAc,KAAG,GAcjD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,WAAW,GAAU,CAAC,EACjC,WAAW,MAAM,EACjB,MAAM,MAAM,OAAO,CAAC,CAAC,CAAC,EACtB,cAAc,MAAM,EACpB,YAAY,MAAM,EAClB,SAAQ,MAAU,KACjB,OAAO,CAAC,CAAC,CAYX,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,gBAAgB,GAAU,CAAC,EACtC,OAAO,MAAM,EACb,MAAM,MAAM,OAAO,CAAC,CAAC,CAAC,EACtB,SAAQ,MAAU,KACjB,OAAO,CAAC,CAAC,CAiBX,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAE1E;;OAEG;IACH,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,kBAAkB,QAAO,YA0BrC,CAAC"}
@@ -72,6 +72,50 @@ export const withSpinner = async (startText, task, successText, errorText, inden
72
72
  throw error;
73
73
  }
74
74
  };
75
+ /**
76
+ * Execute async task with a spinner that updates its label with
77
+ * elapsed seconds while the task runs. Use for long-running phases
78
+ * (local node startup, publish + tx wait) where the user wants
79
+ * visible progress feedback in lieu of subprocess chatter.
80
+ *
81
+ * Pairs with the `§9` console-UX convention: any phase that
82
+ * empirically takes ≥3s in normal use should wrap its body in
83
+ * `withTimedSpinner` so the terminal never goes silent while work
84
+ * happens.
85
+ *
86
+ * @param label - Stable label shown next to the spinner (e.g. "Starting node")
87
+ * @param task - Async function to execute
88
+ * @param indent - Number of spaces to indent (default: 0)
89
+ * @returns Promise resolving to task result
90
+ *
91
+ * @example
92
+ * await withTimedSpinner('Starting local node', async () => {
93
+ * await this.waitForReady(60_000);
94
+ * });
95
+ * // Renders: ⠋ Starting local node — 0.0s ... ⠼ Starting local node — 14.2s
96
+ * // On success: ✔ Starting local node (14.2s)
97
+ * // On error: ✖ <error.message>
98
+ */
99
+ export const withTimedSpinner = async (label, task, indent = 0) => {
100
+ const start = Date.now();
101
+ const spin = spinner({ text: `${label} — 0.0s`, indent });
102
+ const timer = setInterval(() => {
103
+ spin.text = `${label} — ${((Date.now() - start) / 1000).toFixed(1)}s`;
104
+ }, 500);
105
+ try {
106
+ const result = await task();
107
+ spin.succeed(`${label} (${((Date.now() - start) / 1000).toFixed(1)}s)`);
108
+ return result;
109
+ }
110
+ catch (error) {
111
+ const errMsg = error instanceof Error ? error.message : String(error);
112
+ spin.fail(errMsg);
113
+ throw error;
114
+ }
115
+ finally {
116
+ clearInterval(timer);
117
+ }
118
+ };
75
119
  /**
76
120
  * Create a sequential spinner chain
77
121
  * Useful for multi-step processes like initialization
@@ -1 +1 @@
1
- {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"AAAA,OAAO,GAA6C,MAAM,KAAK,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAqB7C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,OAAuB,EAAO,EAAE;IACtD,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,QAAQ,EAAE,OAAO,GAAG,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC;IAEzE,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAExC,MAAM,UAAU,GAAe;QAC7B,IAAI,EAAE,YAAY,GAAG,IAAI;QACzB,KAAK;QACL,OAAO;QACP,6DAA6D;QAC7D,SAAS,EAAE,cAAc,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;KAC7D,CAAC;IAEF,OAAO,GAAG,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,CAAC;AACjC,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAC9B,SAAiB,EACjB,IAAsB,EACtB,WAAoB,EACpB,SAAkB,EAClB,SAAiB,CAAC,EACN,EAAE;IACd,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IAElD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,CAAC,WAAW,IAAI,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;QAC/D,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,WAAW,MAAM,EAAE,CAAC,CAAC;QAC5C,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAkBF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAiB,EAAE;IACnD,IAAI,cAAc,GAAe,IAAI,CAAC;IAEtC,OAAO;QACL,KAAK,CAAC,GAAG,CACP,IAAY,EACZ,IAAsB,EACtB,SAAiB,CAAC;YAElB,cAAc,GAAG,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YAC3C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;gBAC5B,cAAc,CAAC,OAAO,EAAE,CAAC;gBACzB,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,cAAc,CAAC,IAAI,EAAE,CAAC;gBACtB,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;QAED,QAAQ;YACN,IAAI,cAAc,EAAE,CAAC;gBACnB,cAAc,CAAC,IAAI,EAAE,CAAC;YACxB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/ui/spinner.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "movehat",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "type": "module",
5
5
  "description": "Hardhat-like development framework for Movement L1 smart contracts",
6
6
  "bin": {
package/src/cli.ts CHANGED
@@ -50,6 +50,7 @@ program
50
50
  .version(version)
51
51
  .option('--network <name>', 'Network to use (testnet, mainnet, local, etc.)')
52
52
  .option('--redeploy', 'Force redeploy even if already deployed')
53
+ .option('-v, --verbose', 'Show subprocess output (movement node, aptos move) for debugging')
53
54
  .hook('preAction', (thisCommand) => {
54
55
  // Store network option in environment for commands to access
55
56
  const options = thisCommand.opts();
@@ -59,6 +60,9 @@ program
59
60
  if (options.redeploy) {
60
61
  process.env.MH_CLI_REDEPLOY = 'true';
61
62
  }
63
+ if (options.verbose) {
64
+ process.env.MOVEHAT_VERBOSE = '1';
65
+ }
62
66
  });
63
67
 
64
68
  program
@@ -2,7 +2,8 @@ import fs from "fs";
2
2
  import path from "path";
3
3
  import { loadUserConfig } from "../core/config.js";
4
4
  import { validatePathSafety } from "../core/shell.js";
5
- import { logger } from "../ui/index.js";
5
+ import { logger, isVerbose } from "../ui/index.js";
6
+ import { withSpinner } from "../ui/spinner.js";
6
7
  import { runCli } from "../utils/runCli.js";
7
8
 
8
9
  /**
@@ -195,25 +196,33 @@ async function runMovementBuild(
195
196
  args: readonly string[],
196
197
  cwd: string
197
198
  ): Promise<void> {
198
- // Use throwOnNonZeroExit:false so we can log stdout/stderr in both
199
- // success and failure paths, matching the behavior of the previous
200
- // exec-based helper.
201
- const result = await runCli(
202
- {
203
- command: "movement",
204
- args,
205
- cwd,
206
- timeoutMs: 120000, // 2 minutes for git dependency downloads
207
- },
208
- { throwOnNonZeroExit: false }
199
+ // Use throwOnNonZeroExit:false so we can route stdout/stderr through
200
+ // the §9 verbosity gate ourselves. On failure we surface everything;
201
+ // on success the chatter is hidden unless isVerbose().
202
+ const result = await withSpinner("Compiling Move package", () =>
203
+ runCli(
204
+ {
205
+ command: "movement",
206
+ args,
207
+ cwd,
208
+ timeoutMs: 120000, // 2 minutes for git dependency downloads
209
+ },
210
+ { throwOnNonZeroExit: false }
211
+ ),
209
212
  );
210
213
 
211
- if (result.stdout) console.log(result.stdout.trim());
212
- if (result.stderr) console.error(result.stderr.trim());
213
-
214
214
  if (result.exitCode !== 0) {
215
+ // Build failed — show the user everything we have so they can debug.
216
+ if (result.stdout) logger.plain(result.stdout.trim());
217
+ if (result.stderr) logger.plain(result.stderr.trim());
215
218
  throw new Error(`movement move build exited with code ${result.exitCode}`);
216
219
  }
220
+
221
+ // Success path: route output through the verbosity gate.
222
+ if (isVerbose()) {
223
+ if (result.stdout) logger.info(result.stdout.trim(), 2);
224
+ if (result.stderr) logger.info(result.stderr.trim(), 2);
225
+ }
217
226
  }
218
227
 
219
228
  /**
@@ -97,8 +97,7 @@ async function showTestMenu(): Promise<TestType | undefined> {
97
97
  */
98
98
  async function runMoveTestsOnly(filter?: string): Promise<void> {
99
99
  logger.newline();
100
- console.log(colors.bold("Move Unit Tests"));
101
- console.log(colors.muted("─".repeat(50)));
100
+ logger.phase("Move Unit Tests");
102
101
  logger.newline();
103
102
 
104
103
  try {
@@ -118,8 +117,7 @@ async function runMoveTestsOnly(filter?: string): Promise<void> {
118
117
  */
119
118
  async function runTypeScriptTestsOnly(watch: boolean = false): Promise<void> {
120
119
  logger.newline();
121
- console.log(colors.bold("TypeScript Integration Tests"));
122
- console.log(colors.muted("─".repeat(50)));
120
+ logger.phase("TypeScript Integration Tests");
123
121
 
124
122
  if (!watch) {
125
123
  logger.newline();
@@ -146,13 +144,11 @@ async function runTypeScriptTestsOnly(watch: boolean = false): Promise<void> {
146
144
  */
147
145
  async function runAllTests(filter?: string): Promise<void> {
148
146
  logger.newline();
149
- console.log(colors.bold("Running All Tests"));
150
- console.log(colors.muted("═".repeat(50)));
147
+ logger.phase("Running All Tests");
151
148
 
152
149
  // Section 1: Move Tests
153
150
  logger.newline();
154
- console.log(`${colors.brandBright("1.")} ${colors.bold("Move Unit Tests")}`);
155
- console.log(colors.muted("─".repeat(50)));
151
+ logger.phase("1. Move Unit Tests");
156
152
  logger.newline();
157
153
 
158
154
  try {
@@ -163,28 +159,25 @@ async function runAllTests(filter?: string): Promise<void> {
163
159
  } catch (error) {
164
160
  logger.newline();
165
161
  logger.error("Move tests failed");
166
- console.log(colors.muted("═".repeat(50)));
162
+ logger.divider();
167
163
  process.exit(1);
168
164
  }
169
165
 
170
166
  // Section 2: TypeScript Tests
171
167
  logger.newline();
172
- console.log(colors.muted("═".repeat(50)));
173
- logger.newline();
174
- console.log(`${colors.brandBright("2.")} ${colors.bold("TypeScript Integration Tests")}`);
175
- console.log(colors.muted("─".repeat(50)));
168
+ logger.phase("2. TypeScript Integration Tests");
176
169
  logger.newline();
177
170
 
178
171
  try {
179
172
  await runTypeScriptTests(false);
180
173
  logger.newline();
181
- console.log(colors.muted("═".repeat(50)));
174
+ logger.divider();
182
175
  logger.newline();
183
176
  logger.success("All tests passed!");
184
177
  logger.newline();
185
178
  } catch (error) {
186
179
  logger.newline();
187
- console.log(colors.muted("═".repeat(50)));
180
+ logger.divider();
188
181
  const message = error instanceof Error ? error.message : String(error);
189
182
  logger.error(message);
190
183
  process.exit(1);
@@ -198,8 +191,8 @@ async function runTypeScriptTests(watch: boolean = false): Promise<void> {
198
191
  const testDir = join(process.cwd(), "tests");
199
192
 
200
193
  if (!existsSync(testDir)) {
201
- console.log(`${colors.muted(symbols.info)} No TypeScript tests found ${colors.muted("(tests/ directory not found)")}`);
202
- console.log(` ${colors.muted("Skipping TypeScript tests...")}`);
194
+ logger.plain(`${colors.muted(symbols.info)} No TypeScript tests found ${colors.muted("(tests/ directory not found)")}`);
195
+ logger.plain(` ${colors.muted("Skipping TypeScript tests...")}`);
203
196
  logger.newline();
204
197
  return;
205
198
  }
@@ -208,7 +201,7 @@ async function runTypeScriptTests(watch: boolean = false): Promise<void> {
208
201
 
209
202
  if (!existsSync(mochaPath)) {
210
203
  logger.error("Mocha not found in project dependencies");
211
- console.log(` ${colors.muted("Install it with:")} ${colors.info("npm install --save-dev mocha")}`);
204
+ logger.plain(` ${colors.muted("Install it with:")} ${colors.info("npm install --save-dev mocha")}`);
212
205
  throw new Error("Mocha not found");
213
206
  }
214
207
 
@@ -232,7 +225,7 @@ async function runTypeScriptTests(watch: boolean = false): Promise<void> {
232
225
  process.exit(1);
233
226
  });
234
227
 
235
- console.log(`${colors.info(symbols.info)} Watch mode active. Press Ctrl+C to exit.`);
228
+ logger.plain(`${colors.info(symbols.info)} Watch mode active. Press Ctrl+C to exit.`);
236
229
  logger.newline();
237
230
  return;
238
231
  }
@@ -10,7 +10,8 @@ import {
10
10
  import { validatePathSafety } from "./shell.js";
11
11
  import { CliExecutionError, ModuleAlreadyDeployedError, PostPublishError } from "../errors.js";
12
12
  import { runCli } from "../utils/runCli.js";
13
- import { logger } from "../ui/index.js";
13
+ import { logger, isVerbose } from "../ui/index.js";
14
+ import { withSpinner } from "../ui/spinner.js";
14
15
  import type { ChildProcessAdapter } from "../utils/childProcessAdapter.js";
15
16
  import {
16
17
  writeTempKeyFile,
@@ -122,19 +123,23 @@ export class Publisher {
122
123
  : [];
123
124
 
124
125
  // Build first with named addresses
125
- logger.step("Building package...");
126
- const buildResult = await runCli(
127
- {
128
- command: "movement",
129
- args: ["move", "build", "--package-dir", safeDir, ...namedAddrArgs],
130
- timeoutMs: 120000, // 2 minutes for git dependency downloads
131
- },
132
- { adapter: this.deps.adapter }
126
+ const buildResult = await withSpinner(
127
+ "Building package",
128
+ () =>
129
+ runCli(
130
+ {
131
+ command: "movement",
132
+ args: ["move", "build", "--package-dir", safeDir, ...namedAddrArgs],
133
+ timeoutMs: 120000, // 2 minutes for git dependency downloads
134
+ },
135
+ { adapter: this.deps.adapter }
136
+ ),
133
137
  );
134
- if (buildResult.stdout) console.log(buildResult.stdout.trim());
138
+ if (isVerbose() && buildResult.stdout) {
139
+ logger.info(buildResult.stdout.trim(), 2);
140
+ }
135
141
 
136
142
  // Publish using direct parameters (avoid config file issues)
137
- logger.step("Publishing to blockchain...");
138
143
 
139
144
  // Format the private key into AIP-80 shape so the Movement CLI
140
145
  // doesn't emit its raw-hex deprecation warning. `formatPrivateKey`
@@ -179,31 +184,41 @@ export class Publisher {
179
184
  // stdout/stderr redaction still applies as defense in depth
180
185
  // for any `ed25519-priv-…` substring that surfaces in CLI
181
186
  // output (Movement CLI sometimes echoes the key on error).
182
- const publishResult = await runCli(
183
- {
184
- command: "movement",
185
- args: [
186
- "move",
187
- "publish",
188
- "--package-dir",
189
- safeDir,
190
- "--url",
191
- config.rpc,
192
- "--private-key-file",
193
- keyFilePath,
194
- "--sender-account",
195
- deployerAddress,
196
- "--assume-yes",
197
- ...namedAddrArgs,
198
- ],
199
- timeoutMs: 120000, // 2 minutes for blockchain transactions
200
- },
201
- { adapter: this.deps.adapter }
187
+ const publishResult = await withSpinner(
188
+ "Publishing to blockchain",
189
+ () =>
190
+ runCli(
191
+ {
192
+ command: "movement",
193
+ args: [
194
+ "move",
195
+ "publish",
196
+ "--package-dir",
197
+ safeDir,
198
+ "--url",
199
+ config.rpc,
200
+ "--private-key-file",
201
+ keyFilePath,
202
+ "--sender-account",
203
+ deployerAddress,
204
+ "--assume-yes",
205
+ ...namedAddrArgs,
206
+ ],
207
+ timeoutMs: 120000, // 2 minutes for blockchain transactions
208
+ },
209
+ { adapter: this.deps.adapter }
210
+ ),
202
211
  );
203
212
  publishOut = publishResult.stdout;
204
213
  publishErr = publishResult.stderr;
205
- if (publishOut) console.log(publishOut.trim());
206
- if (publishErr) console.error(publishErr.trim());
214
+ // Both stdout and stderr from the publish subprocess are gated
215
+ // behind isVerbose() — Movement CLI emits progress to both
216
+ // streams ("Compiling, may take a little while..."), so a
217
+ // visible stderr line is not by itself a failure signal. The
218
+ // surrounding withSpinner converts the runCli throw on real
219
+ // failure into the visible spinner.fail() output instead.
220
+ if (isVerbose() && publishOut) logger.info(publishOut.trim(), 2);
221
+ if (isVerbose() && publishErr) logger.info(publishErr.trim(), 2);
207
222
  } finally {
208
223
  // Unlink the temp key file via the observable cleanup helper.
209
224
  // ENOENT and other already-gone outcomes are benign (null).
@@ -279,7 +294,7 @@ export class Publisher {
279
294
  if (error instanceof CliExecutionError) {
280
295
  // stdout/stderr are already redacted by runCli before reaching here,
281
296
  // so this branch is safe to log verbatim.
282
- if (error.stdoutPreview) console.log(error.stdoutPreview);
297
+ if (error.stdoutPreview) logger.info(error.stdoutPreview, 2);
283
298
  logger.error(`Failed to publish module: ${error.message}\n${error.stderr}`);
284
299
  } else {
285
300
  // Preserve existing behaviour for non-CLI errors (filesystem write
@@ -3,6 +3,7 @@ import { join } from "path";
3
3
  import { existsSync, statSync } from "fs";
4
4
  import { Account, Ed25519PrivateKey, PrivateKey, PrivateKeyVariants } from "@aptos-labs/ts-sdk";
5
5
  import { MovehatConfig, MovehatUserConfig } from "../types/config.js";
6
+ import { logger } from "../ui/index.js";
6
7
 
7
8
  interface ConfigCacheEntry {
8
9
  mtimeMs: number;
@@ -132,7 +133,7 @@ export async function resolveNetworkConfig(
132
133
  url: "https://testnet.movementnetwork.xyz/v1",
133
134
  chainId: "testnet",
134
135
  };
135
- console.log(`testnet not found in config - using default Movement testnet configuration`);
136
+ logger.info("testnet not found in config - using default Movement testnet configuration");
136
137
  }
137
138
 
138
139
  // Special case: Auto-generate config for local fork server
@@ -141,7 +142,7 @@ export async function resolveNetworkConfig(
141
142
  url: "http://localhost:8080/v1",
142
143
  chainId: "local",
143
144
  };
144
- console.log(`Local network not found in config - using default fork server configuration`);
145
+ logger.info("Local network not found in config - using default fork server configuration");
145
146
  }
146
147
 
147
148
  if (!networkConfig) {
@@ -187,8 +188,10 @@ export async function resolveNetworkConfig(
187
188
  // 3. Deterministic = consistent test results
188
189
  const testPrivateKey = "0x0000000000000000000000000000000000000000000000000000000000000001";
189
190
  accounts = [testPrivateKey];
190
- console.log(`\n[TESTNET] Using auto-generated test account (safe for testing only)`);
191
- console.log(`[TESTNET] For mainnet, set PRIVATE_KEY in .env\n`);
191
+ logger.newline();
192
+ logger.warning("[TESTNET] Using auto-generated test account (safe for testing only)");
193
+ logger.warning("[TESTNET] For mainnet, set PRIVATE_KEY in .env");
194
+ logger.newline();
192
195
  } else {
193
196
  // For any other network (especially mainnet), REQUIRE explicit configuration
194
197
  // This prevents accidentally using the test key on production networks
@@ -273,8 +276,8 @@ function deriveAccountAddress(privateKeyHex: string | undefined): string {
273
276
  // The private key may have come from several sources (network.accounts,
274
277
  // global accounts, PRIVATE_KEY env, auto-generated testnet key). Keep
275
278
  // the hint generic so it never points at the wrong source.
276
- console.warn(
277
- `[movehat] Could not derive account address from the resolved private key: ${
279
+ logger.warning(
280
+ `Could not derive account address from the resolved private key: ${
278
281
  (err as Error).message
279
282
  }. Verify the key configured for this network is a valid Ed25519 private key (with or without the "ed25519-priv-" prefix).`
280
283
  );