@happier-dev/stack 0.1.0-preview.5.1

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 (439) hide show
  1. package/README.md +501 -0
  2. package/bin/hstack.mjs +348 -0
  3. package/docs/codex-mcp-resume.md +129 -0
  4. package/docs/edison.md +74 -0
  5. package/docs/forking-and-branding.md +189 -0
  6. package/docs/happy-development.md +22 -0
  7. package/docs/isolated-linux-vm.md +243 -0
  8. package/docs/menubar.md +244 -0
  9. package/docs/mobile-ios.md +322 -0
  10. package/docs/monorepo-migration.md +20 -0
  11. package/docs/paths-and-env.md +154 -0
  12. package/docs/remote-access.md +43 -0
  13. package/docs/server-flavors.md +147 -0
  14. package/docs/stacks.md +330 -0
  15. package/docs/tauri.md +60 -0
  16. package/docs/worktrees-and-forks.md +133 -0
  17. package/extras/swiftbar/auth-login.sh +29 -0
  18. package/extras/swiftbar/git-cache-refresh.sh +122 -0
  19. package/extras/swiftbar/hstack-term.sh +133 -0
  20. package/extras/swiftbar/hstack.5s.sh +296 -0
  21. package/extras/swiftbar/hstack.sh +35 -0
  22. package/extras/swiftbar/icons/happy-green.png +0 -0
  23. package/extras/swiftbar/icons/happy-orange.png +0 -0
  24. package/extras/swiftbar/icons/happy-red.png +0 -0
  25. package/extras/swiftbar/icons/logo-white.png +0 -0
  26. package/extras/swiftbar/install.sh +265 -0
  27. package/extras/swiftbar/lib/git.sh +629 -0
  28. package/extras/swiftbar/lib/icons.sh +92 -0
  29. package/extras/swiftbar/lib/render.sh +999 -0
  30. package/extras/swiftbar/lib/system.sh +244 -0
  31. package/extras/swiftbar/lib/utils.sh +717 -0
  32. package/extras/swiftbar/set-interval.sh +65 -0
  33. package/extras/swiftbar/set-server-flavor.sh +61 -0
  34. package/extras/swiftbar/wt-pr.sh +140 -0
  35. package/node_modules/@happier-dev/cli-common/README.md +6 -0
  36. package/node_modules/@happier-dev/cli-common/dist/index.d.ts +4 -0
  37. package/node_modules/@happier-dev/cli-common/dist/index.d.ts.map +1 -0
  38. package/node_modules/@happier-dev/cli-common/dist/index.js +4 -0
  39. package/node_modules/@happier-dev/cli-common/dist/index.js.map +1 -0
  40. package/node_modules/@happier-dev/cli-common/dist/links/index.d.ts +18 -0
  41. package/node_modules/@happier-dev/cli-common/dist/links/index.d.ts.map +1 -0
  42. package/node_modules/@happier-dev/cli-common/dist/links/index.js +25 -0
  43. package/node_modules/@happier-dev/cli-common/dist/links/index.js.map +1 -0
  44. package/node_modules/@happier-dev/cli-common/dist/links.d.ts +2 -0
  45. package/node_modules/@happier-dev/cli-common/dist/links.d.ts.map +1 -0
  46. package/node_modules/@happier-dev/cli-common/dist/links.js +2 -0
  47. package/node_modules/@happier-dev/cli-common/dist/links.js.map +1 -0
  48. package/node_modules/@happier-dev/cli-common/dist/update/index.d.ts +67 -0
  49. package/node_modules/@happier-dev/cli-common/dist/update/index.d.ts.map +1 -0
  50. package/node_modules/@happier-dev/cli-common/dist/update/index.js +259 -0
  51. package/node_modules/@happier-dev/cli-common/dist/update/index.js.map +1 -0
  52. package/node_modules/@happier-dev/cli-common/dist/workspaces/index.d.ts +17 -0
  53. package/node_modules/@happier-dev/cli-common/dist/workspaces/index.d.ts.map +1 -0
  54. package/node_modules/@happier-dev/cli-common/dist/workspaces/index.js +80 -0
  55. package/node_modules/@happier-dev/cli-common/dist/workspaces/index.js.map +1 -0
  56. package/node_modules/@happier-dev/cli-common/package.json +26 -0
  57. package/package.json +77 -0
  58. package/scripts/auth.mjs +1829 -0
  59. package/scripts/auth_copy_from_pglite_lock_in_use.integration.test.mjs +90 -0
  60. package/scripts/auth_copy_from_runCapture.integration.test.mjs +447 -0
  61. package/scripts/auth_help_cmd.test.mjs +28 -0
  62. package/scripts/auth_login_flow_in_tty.test.mjs +100 -0
  63. package/scripts/auth_login_force_default.test.mjs +66 -0
  64. package/scripts/auth_login_guided_server_no_expo.test.mjs +126 -0
  65. package/scripts/auth_login_method_override.test.mjs +67 -0
  66. package/scripts/auth_login_print_includes_configure_links.test.mjs +99 -0
  67. package/scripts/auth_status_server_validation.integration.test.mjs +140 -0
  68. package/scripts/build.mjs +266 -0
  69. package/scripts/bundleWorkspaceDeps.mjs +38 -0
  70. package/scripts/bundleWorkspaceDeps.test.mjs +77 -0
  71. package/scripts/ci.mjs +135 -0
  72. package/scripts/ci.test.mjs +50 -0
  73. package/scripts/cli-link.mjs +57 -0
  74. package/scripts/completion.mjs +395 -0
  75. package/scripts/contrib.mjs +333 -0
  76. package/scripts/daemon.mjs +1160 -0
  77. package/scripts/daemon.status_scope.test.mjs +51 -0
  78. package/scripts/daemon_cmd.mjs +26 -0
  79. package/scripts/daemon_dist_guard.test.mjs +171 -0
  80. package/scripts/daemon_invalid_auth_reseed_stack_name.integration.test.mjs +608 -0
  81. package/scripts/daemon_server_scoped_state.test.mjs +49 -0
  82. package/scripts/daemon_start_verification.integration.test.mjs +296 -0
  83. package/scripts/dev.mjs +545 -0
  84. package/scripts/doctor.mjs +340 -0
  85. package/scripts/doctor_cmd.test.mjs +22 -0
  86. package/scripts/doctor_ui_index_missing.test.mjs +37 -0
  87. package/scripts/eas.mjs +367 -0
  88. package/scripts/eas_platform_parsing.test.mjs +63 -0
  89. package/scripts/edison.mjs +1848 -0
  90. package/scripts/env.mjs +149 -0
  91. package/scripts/env_cmd.test.mjs +118 -0
  92. package/scripts/exit_cleanup_kills_detached_children_on_crash.integration.test.mjs +80 -0
  93. package/scripts/happier.mjs +82 -0
  94. package/scripts/import.mjs +1327 -0
  95. package/scripts/init.mjs +464 -0
  96. package/scripts/install.mjs +550 -0
  97. package/scripts/lint.mjs +177 -0
  98. package/scripts/menubar.mjs +202 -0
  99. package/scripts/migrate.mjs +318 -0
  100. package/scripts/mobile.mjs +353 -0
  101. package/scripts/mobile_dev_client.mjs +87 -0
  102. package/scripts/monorepo.mjs +2234 -0
  103. package/scripts/monorepo_port.apply.integration.test.mjs +680 -0
  104. package/scripts/monorepo_port.conflicts.integration.test.mjs +454 -0
  105. package/scripts/monorepo_port.validation.integration.test.mjs +486 -0
  106. package/scripts/orchestrated_stack_auth_flow.test.mjs +134 -0
  107. package/scripts/orchestrated_stack_auth_flow_resolve_port.test.mjs +98 -0
  108. package/scripts/orchestrated_stack_auth_flow_webapp_url.test.mjs +119 -0
  109. package/scripts/pack.mjs +257 -0
  110. package/scripts/pack.test.mjs +68 -0
  111. package/scripts/pglite_lock.integration.test.mjs +152 -0
  112. package/scripts/provision/linux-ubuntu-e2e.sh +132 -0
  113. package/scripts/provision/linux-ubuntu-review-pr.sh +66 -0
  114. package/scripts/provision/macos-lima-happy-vm.sh +192 -0
  115. package/scripts/provision/macos-lima-hstack-e2e.sh +100 -0
  116. package/scripts/release.mjs +53 -0
  117. package/scripts/release_binary_smoke.integration.test.mjs +159 -0
  118. package/scripts/review.mjs +1752 -0
  119. package/scripts/review_pr.mjs +435 -0
  120. package/scripts/run.mjs +561 -0
  121. package/scripts/run_script_with_stack_env.restart_port_reuse.test.mjs +30 -0
  122. package/scripts/self.mjs +465 -0
  123. package/scripts/self_host.mjs +9 -0
  124. package/scripts/self_host_binary_smoke.integration.test.mjs +94 -0
  125. package/scripts/self_host_runtime.mjs +883 -0
  126. package/scripts/self_host_runtime.test.mjs +82 -0
  127. package/scripts/self_host_systemd.real.integration.test.mjs +367 -0
  128. package/scripts/server_flavor.mjs +148 -0
  129. package/scripts/service.mjs +868 -0
  130. package/scripts/service_mode_help.test.mjs +27 -0
  131. package/scripts/setup.mjs +1324 -0
  132. package/scripts/setup_non_interactive_flag.test.mjs +60 -0
  133. package/scripts/setup_pr.mjs +605 -0
  134. package/scripts/setup_pr_orchestrated_auth_flow_util_import.test.mjs +117 -0
  135. package/scripts/stack/command_arguments.mjs +91 -0
  136. package/scripts/stack/copy_auth_from_stack.mjs +111 -0
  137. package/scripts/stack/delegated_script_commands.mjs +92 -0
  138. package/scripts/stack/help_text.mjs +110 -0
  139. package/scripts/stack/port_reservation.mjs +74 -0
  140. package/scripts/stack/repo_checkout_resolution.mjs +31 -0
  141. package/scripts/stack/run_script_with_stack_env.mjs +634 -0
  142. package/scripts/stack/stack_daemon_command.mjs +219 -0
  143. package/scripts/stack/stack_delegated_help.mjs +81 -0
  144. package/scripts/stack/stack_environment.mjs +151 -0
  145. package/scripts/stack/stack_environment.sanitization.test.mjs +75 -0
  146. package/scripts/stack/stack_happier_passthrough_command.mjs +63 -0
  147. package/scripts/stack/stack_info_snapshot.mjs +167 -0
  148. package/scripts/stack/stack_mobile_install_command.mjs +61 -0
  149. package/scripts/stack/stack_resume_command.mjs +76 -0
  150. package/scripts/stack/stack_stop_command.mjs +34 -0
  151. package/scripts/stack/stack_workspace_command.mjs +83 -0
  152. package/scripts/stack/transient_repo_overrides.mjs +29 -0
  153. package/scripts/stack.mjs +2388 -0
  154. package/scripts/stack_archive_cmd.integration.test.mjs +31 -0
  155. package/scripts/stack_audit_fix_light_env.test.mjs +129 -0
  156. package/scripts/stack_background_pinned_stack_json.test.mjs +81 -0
  157. package/scripts/stack_copy_auth_server_scoped.test.mjs +243 -0
  158. package/scripts/stack_daemon_cmd.integration.test.mjs +484 -0
  159. package/scripts/stack_eas_help.test.mjs +72 -0
  160. package/scripts/stack_editor_workspace_monorepo_root.test.mjs +102 -0
  161. package/scripts/stack_env_cmd.test.mjs +107 -0
  162. package/scripts/stack_guided_login_bundle_error_parse.test.mjs +20 -0
  163. package/scripts/stack_guided_login_inner_invocation.test.mjs +46 -0
  164. package/scripts/stack_happy_cmd.integration.test.mjs +263 -0
  165. package/scripts/stack_info_snapshot_running_status.test.mjs +186 -0
  166. package/scripts/stack_interactive_monorepo_group.test.mjs +128 -0
  167. package/scripts/stack_monorepo_defaults.test.mjs +31 -0
  168. package/scripts/stack_monorepo_repo_dev_token.test.mjs +32 -0
  169. package/scripts/stack_monorepo_server_light_from_happy_spec.test.mjs +37 -0
  170. package/scripts/stack_new_name_normalize_cmd.test.mjs +38 -0
  171. package/scripts/stack_pr_name_normalize_cmd.test.mjs +84 -0
  172. package/scripts/stack_resume_cmd.integration.test.mjs +134 -0
  173. package/scripts/stack_server_flavors_defaults.test.mjs +64 -0
  174. package/scripts/stack_shorthand_cmd.integration.test.mjs +74 -0
  175. package/scripts/stack_stop_sweeps_legacy_infra_without_kind.integration.test.mjs +44 -0
  176. package/scripts/stack_stop_sweeps_when_runtime_missing.integration.test.mjs +42 -0
  177. package/scripts/stack_stop_sweeps_when_runtime_stale.integration.test.mjs +50 -0
  178. package/scripts/stack_wt_list.test.mjs +117 -0
  179. package/scripts/start_ui_required_default.test.mjs +63 -0
  180. package/scripts/stop.mjs +190 -0
  181. package/scripts/stopStackWithEnv_no_autosweep_when_runtime_missing.integration.test.mjs +95 -0
  182. package/scripts/swiftbar_git_monorepo_cmd.test.mjs +75 -0
  183. package/scripts/swiftbar_render_monorepo_wt_actions.integration.test.mjs +116 -0
  184. package/scripts/swiftbar_utils_cmd.test.mjs +92 -0
  185. package/scripts/swiftbar_wt_pr_backcompat.test.mjs +162 -0
  186. package/scripts/systemd_unit_info.test.mjs +24 -0
  187. package/scripts/tailscale.mjs +490 -0
  188. package/scripts/test_ci.mjs +36 -0
  189. package/scripts/test_cmd.mjs +274 -0
  190. package/scripts/test_cmd.test.mjs +133 -0
  191. package/scripts/test_integration.mjs +33 -0
  192. package/scripts/testkit/auth_testkit.mjs +121 -0
  193. package/scripts/testkit/doctor_testkit.mjs +68 -0
  194. package/scripts/testkit/monorepo_port_testkit.mjs +157 -0
  195. package/scripts/testkit/stack_archive_command_testkit.mjs +55 -0
  196. package/scripts/testkit/stack_new_monorepo_testkit.mjs +83 -0
  197. package/scripts/testkit/stack_script_command_testkit.mjs +27 -0
  198. package/scripts/testkit/stack_stop_sweeps_testkit.mjs +172 -0
  199. package/scripts/testkit/worktrees_monorepo_testkit.mjs +53 -0
  200. package/scripts/tools.mjs +70 -0
  201. package/scripts/tui.mjs +914 -0
  202. package/scripts/tui_stopStackForTuiExit_no_autosweep.integration.test.mjs +95 -0
  203. package/scripts/typecheck.mjs +178 -0
  204. package/scripts/ui_gateway.mjs +247 -0
  205. package/scripts/uninstall.mjs +179 -0
  206. package/scripts/utils/auth/credentials_paths.mjs +181 -0
  207. package/scripts/utils/auth/credentials_paths.test.mjs +187 -0
  208. package/scripts/utils/auth/daemon_gate.mjs +66 -0
  209. package/scripts/utils/auth/daemon_gate.test.mjs +116 -0
  210. package/scripts/utils/auth/decode_jwt_payload_unsafe.mjs +16 -0
  211. package/scripts/utils/auth/dev_key.mjs +163 -0
  212. package/scripts/utils/auth/files.mjs +56 -0
  213. package/scripts/utils/auth/guided_pr_auth.mjs +86 -0
  214. package/scripts/utils/auth/guided_stack_web_login.mjs +56 -0
  215. package/scripts/utils/auth/handy_master_secret.mjs +42 -0
  216. package/scripts/utils/auth/interactive_stack_auth.mjs +70 -0
  217. package/scripts/utils/auth/login_ux.mjs +105 -0
  218. package/scripts/utils/auth/orchestrated_stack_auth_flow.mjs +291 -0
  219. package/scripts/utils/auth/sources.mjs +28 -0
  220. package/scripts/utils/auth/stable_scope_id.mjs +91 -0
  221. package/scripts/utils/auth/stable_scope_id.test.mjs +51 -0
  222. package/scripts/utils/auth/stack_guided_login.mjs +438 -0
  223. package/scripts/utils/cli/arg_values.mjs +23 -0
  224. package/scripts/utils/cli/arg_values.test.mjs +43 -0
  225. package/scripts/utils/cli/args.mjs +17 -0
  226. package/scripts/utils/cli/cli.mjs +24 -0
  227. package/scripts/utils/cli/cli_registry.mjs +440 -0
  228. package/scripts/utils/cli/cwd_scope.mjs +158 -0
  229. package/scripts/utils/cli/cwd_scope.test.mjs +154 -0
  230. package/scripts/utils/cli/flags.mjs +17 -0
  231. package/scripts/utils/cli/log_forwarder.mjs +157 -0
  232. package/scripts/utils/cli/normalize.mjs +16 -0
  233. package/scripts/utils/cli/prereqs.mjs +103 -0
  234. package/scripts/utils/cli/prereqs.test.mjs +33 -0
  235. package/scripts/utils/cli/progress.mjs +141 -0
  236. package/scripts/utils/cli/smoke_help.mjs +44 -0
  237. package/scripts/utils/cli/verbosity.mjs +11 -0
  238. package/scripts/utils/cli/wizard.mjs +139 -0
  239. package/scripts/utils/cli/wizard_promptSelect.test.mjs +44 -0
  240. package/scripts/utils/cli/wizard_prompt_worktree_source_lazy.test.mjs +132 -0
  241. package/scripts/utils/cli/wizard_worktree_slug.test.mjs +33 -0
  242. package/scripts/utils/crypto/tokens.mjs +14 -0
  243. package/scripts/utils/dev/daemon.mjs +232 -0
  244. package/scripts/utils/dev/daemon_watch_resilience.test.mjs +224 -0
  245. package/scripts/utils/dev/expo_dev.buildEnv.test.mjs +35 -0
  246. package/scripts/utils/dev/expo_dev.mjs +478 -0
  247. package/scripts/utils/dev/expo_dev.test.mjs +89 -0
  248. package/scripts/utils/dev/expo_dev_restart_port_reservation.test.mjs +120 -0
  249. package/scripts/utils/dev/expo_dev_verbose_logs.test.mjs +60 -0
  250. package/scripts/utils/dev/server.mjs +180 -0
  251. package/scripts/utils/dev_auth_key.mjs +7 -0
  252. package/scripts/utils/edison/git_roots.mjs +30 -0
  253. package/scripts/utils/edison/git_roots.test.mjs +49 -0
  254. package/scripts/utils/env/config.mjs +52 -0
  255. package/scripts/utils/env/dotenv.mjs +32 -0
  256. package/scripts/utils/env/dotenv.test.mjs +32 -0
  257. package/scripts/utils/env/env.mjs +130 -0
  258. package/scripts/utils/env/env_file.mjs +98 -0
  259. package/scripts/utils/env/env_file.test.mjs +49 -0
  260. package/scripts/utils/env/env_local.mjs +25 -0
  261. package/scripts/utils/env/load_env_file.mjs +34 -0
  262. package/scripts/utils/env/read.mjs +30 -0
  263. package/scripts/utils/env/sandbox.mjs +13 -0
  264. package/scripts/utils/env/scrub_env.mjs +69 -0
  265. package/scripts/utils/env/scrub_env.test.mjs +102 -0
  266. package/scripts/utils/env/values.mjs +13 -0
  267. package/scripts/utils/expo/command.mjs +65 -0
  268. package/scripts/utils/expo/expo.mjs +139 -0
  269. package/scripts/utils/expo/expo_state_running.test.mjs +48 -0
  270. package/scripts/utils/expo/metro_ports.mjs +101 -0
  271. package/scripts/utils/expo/metro_ports.test.mjs +35 -0
  272. package/scripts/utils/fs/atomic_dir_swap.mjs +55 -0
  273. package/scripts/utils/fs/atomic_dir_swap.test.mjs +54 -0
  274. package/scripts/utils/fs/file_has_content.mjs +10 -0
  275. package/scripts/utils/fs/fs.mjs +11 -0
  276. package/scripts/utils/fs/json.mjs +25 -0
  277. package/scripts/utils/fs/ops.mjs +29 -0
  278. package/scripts/utils/fs/package_json.mjs +8 -0
  279. package/scripts/utils/fs/tail.mjs +12 -0
  280. package/scripts/utils/git/dev_checkout.mjs +127 -0
  281. package/scripts/utils/git/dev_checkout.test.mjs +115 -0
  282. package/scripts/utils/git/git.mjs +67 -0
  283. package/scripts/utils/git/parse_name_status_z.mjs +21 -0
  284. package/scripts/utils/git/refs.mjs +26 -0
  285. package/scripts/utils/git/worktrees.mjs +323 -0
  286. package/scripts/utils/git/worktrees_monorepo.test.mjs +60 -0
  287. package/scripts/utils/git/worktrees_pathstyle.test.mjs +53 -0
  288. package/scripts/utils/llm/assist.mjs +260 -0
  289. package/scripts/utils/llm/codex_exec.mjs +61 -0
  290. package/scripts/utils/llm/codex_exec.test.mjs +46 -0
  291. package/scripts/utils/llm/hstack_runner.mjs +59 -0
  292. package/scripts/utils/llm/tools.mjs +56 -0
  293. package/scripts/utils/llm/tools.test.mjs +67 -0
  294. package/scripts/utils/menubar/swiftbar.mjs +121 -0
  295. package/scripts/utils/menubar/swiftbar.test.mjs +85 -0
  296. package/scripts/utils/mobile/config.mjs +35 -0
  297. package/scripts/utils/mobile/dev_client_links.mjs +59 -0
  298. package/scripts/utils/mobile/identifiers.mjs +46 -0
  299. package/scripts/utils/mobile/identifiers.test.mjs +41 -0
  300. package/scripts/utils/mobile/ios_xcodeproj_patch.mjs +128 -0
  301. package/scripts/utils/mobile/ios_xcodeproj_patch.test.mjs +131 -0
  302. package/scripts/utils/net/bind_mode.mjs +39 -0
  303. package/scripts/utils/net/dns.mjs +10 -0
  304. package/scripts/utils/net/lan_ip.mjs +24 -0
  305. package/scripts/utils/net/ports.mjs +110 -0
  306. package/scripts/utils/net/tcp_forward.mjs +162 -0
  307. package/scripts/utils/net/url.mjs +30 -0
  308. package/scripts/utils/net/url.test.mjs +29 -0
  309. package/scripts/utils/paths/canonical_home.mjs +15 -0
  310. package/scripts/utils/paths/canonical_home.test.mjs +28 -0
  311. package/scripts/utils/paths/localhost_host.mjs +112 -0
  312. package/scripts/utils/paths/localhost_host.test.mjs +58 -0
  313. package/scripts/utils/paths/paths.mjs +302 -0
  314. package/scripts/utils/paths/paths_env_win32.test.mjs +36 -0
  315. package/scripts/utils/paths/paths_monorepo.test.mjs +58 -0
  316. package/scripts/utils/paths/paths_server_flavors.test.mjs +50 -0
  317. package/scripts/utils/paths/runtime.mjs +41 -0
  318. package/scripts/utils/pglite_lock.mjs +107 -0
  319. package/scripts/utils/proc/commands.mjs +33 -0
  320. package/scripts/utils/proc/exit_cleanup.mjs +57 -0
  321. package/scripts/utils/proc/happy_monorepo_deps.mjs +37 -0
  322. package/scripts/utils/proc/happy_monorepo_deps.test.mjs +89 -0
  323. package/scripts/utils/proc/ownership.mjs +217 -0
  324. package/scripts/utils/proc/ownership_killProcessGroupOwnedByStack.test.mjs +216 -0
  325. package/scripts/utils/proc/ownership_listPidsWithEnvNeedles.test.mjs +88 -0
  326. package/scripts/utils/proc/package_scripts.mjs +38 -0
  327. package/scripts/utils/proc/package_scripts.test.mjs +58 -0
  328. package/scripts/utils/proc/parallel.mjs +25 -0
  329. package/scripts/utils/proc/pids.mjs +11 -0
  330. package/scripts/utils/proc/pm.mjs +478 -0
  331. package/scripts/utils/proc/pm_spawn.integration.test.mjs +131 -0
  332. package/scripts/utils/proc/pm_stack_cache_env.test.mjs +313 -0
  333. package/scripts/utils/proc/proc.mjs +331 -0
  334. package/scripts/utils/proc/proc.test.mjs +85 -0
  335. package/scripts/utils/proc/terminate.mjs +69 -0
  336. package/scripts/utils/proc/terminate.test.mjs +54 -0
  337. package/scripts/utils/proc/watch.mjs +63 -0
  338. package/scripts/utils/review/augment_runner_integration.test.mjs +105 -0
  339. package/scripts/utils/review/base_ref.mjs +82 -0
  340. package/scripts/utils/review/base_ref.test.mjs +89 -0
  341. package/scripts/utils/review/chunks.mjs +55 -0
  342. package/scripts/utils/review/chunks.test.mjs +107 -0
  343. package/scripts/utils/review/detached_worktree.mjs +61 -0
  344. package/scripts/utils/review/detached_worktree.test.mjs +61 -0
  345. package/scripts/utils/review/findings.mjs +278 -0
  346. package/scripts/utils/review/findings.test.mjs +203 -0
  347. package/scripts/utils/review/head_slice.mjs +132 -0
  348. package/scripts/utils/review/head_slice.test.mjs +117 -0
  349. package/scripts/utils/review/instructions/deep.md +20 -0
  350. package/scripts/utils/review/prompts.mjs +279 -0
  351. package/scripts/utils/review/prompts.test.mjs +77 -0
  352. package/scripts/utils/review/run_reviewers_safe.mjs +12 -0
  353. package/scripts/utils/review/run_reviewers_safe.test.mjs +45 -0
  354. package/scripts/utils/review/runners/augment.mjs +91 -0
  355. package/scripts/utils/review/runners/augment.test.mjs +64 -0
  356. package/scripts/utils/review/runners/claude.mjs +92 -0
  357. package/scripts/utils/review/runners/claude.test.mjs +47 -0
  358. package/scripts/utils/review/runners/coderabbit.mjs +105 -0
  359. package/scripts/utils/review/runners/coderabbit.test.mjs +32 -0
  360. package/scripts/utils/review/runners/codex.mjs +129 -0
  361. package/scripts/utils/review/runners/codex.test.mjs +115 -0
  362. package/scripts/utils/review/slice_mode.mjs +20 -0
  363. package/scripts/utils/review/slice_mode.test.mjs +69 -0
  364. package/scripts/utils/review/sliced_runner.mjs +39 -0
  365. package/scripts/utils/review/sliced_runner.test.mjs +57 -0
  366. package/scripts/utils/review/slices.mjs +140 -0
  367. package/scripts/utils/review/slices.test.mjs +41 -0
  368. package/scripts/utils/review/targets.mjs +23 -0
  369. package/scripts/utils/review/targets.test.mjs +31 -0
  370. package/scripts/utils/review/tool_home_seed.mjs +106 -0
  371. package/scripts/utils/review/tool_home_seed.test.mjs +124 -0
  372. package/scripts/utils/review/uncommitted_ops.mjs +77 -0
  373. package/scripts/utils/review/uncommitted_ops.test.mjs +117 -0
  374. package/scripts/utils/sandbox/review_pr_sandbox.mjs +105 -0
  375. package/scripts/utils/server/apply_server_light_env_defaults.mjs +14 -0
  376. package/scripts/utils/server/flavor_scripts.mjs +138 -0
  377. package/scripts/utils/server/flavor_scripts.test.mjs +115 -0
  378. package/scripts/utils/server/infra/happy_server_infra.mjs +444 -0
  379. package/scripts/utils/server/mobile_api_url.mjs +60 -0
  380. package/scripts/utils/server/mobile_api_url.test.mjs +58 -0
  381. package/scripts/utils/server/port.mjs +55 -0
  382. package/scripts/utils/server/prisma_import.mjs +36 -0
  383. package/scripts/utils/server/prisma_import.test.mjs +78 -0
  384. package/scripts/utils/server/server.mjs +109 -0
  385. package/scripts/utils/server/ui_build_check.mjs +37 -0
  386. package/scripts/utils/server/ui_build_check.test.mjs +70 -0
  387. package/scripts/utils/server/ui_env.mjs +13 -0
  388. package/scripts/utils/server/ui_env.test.mjs +57 -0
  389. package/scripts/utils/server/urls.mjs +100 -0
  390. package/scripts/utils/server/validate.mjs +60 -0
  391. package/scripts/utils/server/validate.test.mjs +76 -0
  392. package/scripts/utils/service/autostart_darwin.mjs +198 -0
  393. package/scripts/utils/service/autostart_darwin.test.mjs +49 -0
  394. package/scripts/utils/service/autostart_darwin_keepalive.test.mjs +19 -0
  395. package/scripts/utils/stack/cli_identities.mjs +29 -0
  396. package/scripts/utils/stack/context.mjs +19 -0
  397. package/scripts/utils/stack/dirs.mjs +26 -0
  398. package/scripts/utils/stack/editor_workspace.mjs +126 -0
  399. package/scripts/utils/stack/interactive_stack_config.mjs +266 -0
  400. package/scripts/utils/stack/interactive_stack_config.port_validation.test.mjs +93 -0
  401. package/scripts/utils/stack/interactive_stack_config.remote_validation.test.mjs +122 -0
  402. package/scripts/utils/stack/interactive_stack_config.stack_name_validation.test.mjs +76 -0
  403. package/scripts/utils/stack/interactive_stack_config_testkit.mjs +18 -0
  404. package/scripts/utils/stack/names.mjs +27 -0
  405. package/scripts/utils/stack/names.test.mjs +26 -0
  406. package/scripts/utils/stack/pr_stack_name.mjs +16 -0
  407. package/scripts/utils/stack/runtime_state.mjs +88 -0
  408. package/scripts/utils/stack/stacks.mjs +40 -0
  409. package/scripts/utils/stack/startup.mjs +370 -0
  410. package/scripts/utils/stack/startup_server_light_dirs.test.mjs +119 -0
  411. package/scripts/utils/stack/startup_server_light_generate.test.mjs +20 -0
  412. package/scripts/utils/stack/startup_server_light_legacy.test.mjs +79 -0
  413. package/scripts/utils/stack/startup_server_light_testkit.mjs +106 -0
  414. package/scripts/utils/stack/stop.mjs +284 -0
  415. package/scripts/utils/stack_context.mjs +1 -0
  416. package/scripts/utils/stack_runtime_state.mjs +1 -0
  417. package/scripts/utils/stacks.mjs +1 -0
  418. package/scripts/utils/tailscale/ip.mjs +116 -0
  419. package/scripts/utils/tauri/stack_overrides.mjs +22 -0
  420. package/scripts/utils/test/collect_test_files.mjs +29 -0
  421. package/scripts/utils/time/get_today_ymd.mjs +7 -0
  422. package/scripts/utils/tui/cleanup.mjs +38 -0
  423. package/scripts/utils/ui/ansi.mjs +47 -0
  424. package/scripts/utils/ui/browser.mjs +31 -0
  425. package/scripts/utils/ui/browser.test.mjs +56 -0
  426. package/scripts/utils/ui/clipboard.mjs +38 -0
  427. package/scripts/utils/ui/layout.mjs +44 -0
  428. package/scripts/utils/ui/qr.mjs +17 -0
  429. package/scripts/utils/ui/terminal_launcher.mjs +129 -0
  430. package/scripts/utils/ui/text.mjs +16 -0
  431. package/scripts/utils/update/auto_update_notice.mjs +93 -0
  432. package/scripts/utils/validate.mjs +5 -0
  433. package/scripts/where.mjs +138 -0
  434. package/scripts/worktrees.mjs +2174 -0
  435. package/scripts/worktrees_archive_cmd.integration.test.mjs +228 -0
  436. package/scripts/worktrees_cursor_monorepo_root.test.mjs +23 -0
  437. package/scripts/worktrees_list_specs_no_recurse.test.mjs +32 -0
  438. package/scripts/worktrees_monorepo_testkit.test.mjs +29 -0
  439. package/scripts/worktrees_monorepo_use_group.test.mjs +41 -0
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # End-to-end (best-effort) smoke test for hstack on Ubuntu.
5
+ #
6
+ # Intended usage (inside a Lima VM):
7
+ # curl -fsSL https://raw.githubusercontent.com/<org>/<repo>/<ref>/apps/stack/scripts/provision/linux-ubuntu-review-pr.sh -o /tmp/linux-ubuntu-review-pr.sh \
8
+ # && chmod +x /tmp/linux-ubuntu-review-pr.sh \
9
+ # && /tmp/linux-ubuntu-review-pr.sh
10
+ #
11
+ # curl -fsSL https://raw.githubusercontent.com/<org>/<repo>/<ref>/apps/stack/scripts/provision/linux-ubuntu-e2e.sh -o /tmp/linux-ubuntu-e2e.sh \
12
+ # && chmod +x /tmp/linux-ubuntu-e2e.sh \
13
+ # && HSTACK_VERSION=latest /tmp/linux-ubuntu-e2e.sh
14
+ #
15
+ # Notes:
16
+ # - This uses `npx` by default (no reliance on global installs).
17
+ # - All state is isolated under a hstack sandbox dir so it can be deleted cleanly.
18
+ # - Authentication / Tailscale / autostart / menubar are intentionally skipped.
19
+ #
20
+ # Env overrides:
21
+ # - HSTACK_VERSION: npm dist-tag or semver for @happier-dev/stack (default: latest)
22
+ # - HSTACK_TGZ: path to a local @happier-dev/stack tarball inside the VM (overrides HSTACK_VERSION)
23
+ # - HSTACK_E2E_DIR: where to store the sandbox + logs (default: /tmp/hstack-e2e-<timestamp>)
24
+ # - HSTACK_E2E_KEEP: set to 1 to keep the sandbox dir on exit (default: 0)
25
+
26
+ require_cmd() {
27
+ command -v "$1" >/dev/null 2>&1
28
+ }
29
+
30
+ fail() {
31
+ echo "[e2e] failed: $*" >&2
32
+ exit 1
33
+ }
34
+
35
+ say() {
36
+ echo ""
37
+ echo "==> $*"
38
+ }
39
+
40
+ timestamp() {
41
+ date +"%Y%m%d-%H%M%S"
42
+ }
43
+
44
+ for cmd in bash curl git node npx jq; do
45
+ require_cmd "$cmd" || fail "missing required command: $cmd"
46
+ done
47
+
48
+ STACK_VERSION="${HSTACK_VERSION:-latest}"
49
+ STACK_TGZ="${HSTACK_TGZ:-}"
50
+ E2E_DIR="${HSTACK_E2E_DIR:-/tmp/hstack-e2e-$(timestamp)}"
51
+ KEEP="${HSTACK_E2E_KEEP:-0}"
52
+
53
+ SANDBOX_DIR="${E2E_DIR}/sandbox"
54
+ NPM_CACHE="${E2E_DIR}/npm-cache"
55
+ LOG_DIR="${E2E_DIR}/logs"
56
+
57
+ mkdir -p "$LOG_DIR" "$NPM_CACHE"
58
+
59
+ hstack() {
60
+ local spec
61
+ if [[ -n "$STACK_TGZ" ]]; then
62
+ spec="$STACK_TGZ"
63
+ else
64
+ spec="-p @happier-dev/stack@${STACK_VERSION}"
65
+ fi
66
+ # shellcheck disable=SC2086
67
+ npm_config_cache="$NPM_CACHE" \
68
+ npm_config_update_notifier=false \
69
+ npx --yes ${spec} hstack "$@"
70
+ }
71
+
72
+ cleanup() {
73
+ if [[ "$KEEP" == "1" ]]; then
74
+ echo ""
75
+ echo "[e2e] keeping sandbox dir: $E2E_DIR"
76
+ return
77
+ fi
78
+ rm -rf "$E2E_DIR" >/dev/null 2>&1 || true
79
+ }
80
+ trap cleanup EXIT
81
+
82
+ say "system info"
83
+ echo "[e2e] node: $(node --version)"
84
+ echo "[e2e] npm: $(npm --version)"
85
+ echo "[e2e] git: $(git --version)"
86
+ echo "[e2e] jq: $(jq --version)"
87
+ echo "[e2e] pkg: @happier-dev/stack@${STACK_VERSION}"
88
+
89
+ say "hstack help (sanity)"
90
+ hstack --help >/dev/null
91
+
92
+ say "hstack where --json (sandbox wiring)"
93
+ WHERE_JSON="$(hstack --sandbox-dir "$SANDBOX_DIR" where --json | tee "$LOG_DIR/where.json")"
94
+ echo "$WHERE_JSON" | jq -e '.sandbox.enabled == true' >/dev/null || fail "expected sandbox.enabled=true"
95
+ echo "$WHERE_JSON" | jq -e '.repoDir | startswith("/tmp/") or startswith("/var/") or startswith("/home/")' >/dev/null || true
96
+
97
+ say "selfhost setup (no auth/tailscale/autostart/menubar)"
98
+ export HAPPIER_STACK_UPDATE_CHECK=0
99
+ hstack --sandbox-dir "$SANDBOX_DIR" setup \
100
+ --profile=selfhost \
101
+ --no-auth \
102
+ --no-tailscale \
103
+ --no-autostart \
104
+ --no-menubar \
105
+ --bind=loopback \
106
+ 2>&1 | tee "$LOG_DIR/setup-selfhost.log"
107
+
108
+ say "resolve server URL"
109
+ START_JSON="$(hstack --sandbox-dir "$SANDBOX_DIR" start --json | tee "$LOG_DIR/start.json")"
110
+ INTERNAL_URL="$(echo "$START_JSON" | jq -r '.internalServerUrl')"
111
+ if [[ -z "$INTERNAL_URL" || "$INTERNAL_URL" == "null" ]]; then
112
+ fail "missing internalServerUrl from start --json"
113
+ fi
114
+ echo "[e2e] internal url: $INTERNAL_URL"
115
+
116
+ say "health check"
117
+ curl -fsS "${INTERNAL_URL}/health" | tee "$LOG_DIR/health.json" | jq -e '.status == "ok"' >/dev/null
118
+
119
+ say "UI served by server-light"
120
+ HTML_HEAD="$(curl -fsS "${INTERNAL_URL}/" | head -n 5 || true)"
121
+ echo "$HTML_HEAD" | tee "$LOG_DIR/ui.head.txt" | grep -Eqi '<!doctype html|<html' || fail "expected HTML from ${INTERNAL_URL}/"
122
+
123
+ say "worktree smoke (monorepo-only)"
124
+ # Create a throwaway worktree based on the default remote (keeps this test stable even if upstream remotes vary).
125
+ hstack --sandbox-dir "$SANDBOX_DIR" wt new "tmp/e2e-$(timestamp)" --from=origin --use --json | tee "$LOG_DIR/wt-new.json" >/dev/null
126
+ hstack --sandbox-dir "$SANDBOX_DIR" wt status --json | tee "$LOG_DIR/wt-status.json" >/dev/null
127
+
128
+ say "stop main stack (clean shutdown)"
129
+ hstack --sandbox-dir "$SANDBOX_DIR" stop --yes --aggressive --sweep-owned --no-service 2>&1 | tee "$LOG_DIR/stop-main.log"
130
+
131
+ say "done"
132
+ echo "[e2e] ok"
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Provision an Ubuntu VM for running hstack (Happier Stack) in an isolated Linux environment.
5
+ #
6
+ # Intended usage (inside a Lima VM):
7
+ # curl -fsSL https://raw.githubusercontent.com/happier-dev/happier/main/apps/stack/scripts/provision/linux-ubuntu-review-pr.sh -o /tmp/linux-ubuntu-review-pr.sh \
8
+ # && chmod +x /tmp/linux-ubuntu-review-pr.sh \
9
+ # && /tmp/linux-ubuntu-review-pr.sh
10
+ #
11
+ # After provisioning, run:
12
+ # npx --yes -p @happier-dev/stack@latest hstack setup --profile=dev --bind=loopback
13
+
14
+ require_cmd() {
15
+ command -v "$1" >/dev/null 2>&1
16
+ }
17
+
18
+ as_root() {
19
+ if [[ "$(id -u)" == "0" ]]; then
20
+ "$@"
21
+ return
22
+ fi
23
+ if require_cmd sudo; then
24
+ sudo "$@"
25
+ return
26
+ fi
27
+ echo "[provision] missing sudo; re-run as root" >&2
28
+ exit 1
29
+ }
30
+
31
+ echo "[provision] updating apt..."
32
+ as_root apt-get update -y
33
+
34
+ echo "[provision] installing base packages..."
35
+ as_root apt-get install -y --no-install-recommends \
36
+ ca-certificates \
37
+ curl \
38
+ git \
39
+ gnupg \
40
+ jq \
41
+ build-essential \
42
+ python3
43
+
44
+ if ! require_cmd node; then
45
+ echo "[provision] installing Node.js (NodeSource 24.x)..."
46
+ as_root bash -lc 'curl -fsSL https://deb.nodesource.com/setup_24.x | bash -'
47
+ as_root apt-get install -y nodejs
48
+ fi
49
+
50
+ echo "[provision] node: $(node --version)"
51
+
52
+ if ! require_cmd corepack; then
53
+ echo "[provision] corepack not found (expected with Node >=16)."
54
+ exit 1
55
+ fi
56
+
57
+ echo "[provision] enabling corepack + yarn..."
58
+ corepack enable
59
+ corepack prepare yarn@1.22.22 --activate
60
+ yarn --version
61
+
62
+ echo ""
63
+ echo "[provision] done."
64
+ echo ""
65
+ echo "Next:"
66
+ echo " npx --yes -p @happier-dev/stack@latest hstack setup --profile=dev --bind=loopback"
@@ -0,0 +1,192 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Create/configure a Lima VM for testing hstack in an isolated Linux environment,
5
+ # while still opening the Expo web UI on the macOS host via localhost port forwarding
6
+ # (required for WebCrypto/secure-context APIs).
7
+ #
8
+ # Usage:
9
+ # ./scripts/provision/macos-lima-happy-vm.sh [vm-name]
10
+ #
11
+ # Defaults:
12
+ # vm-name: happy-test
13
+ # template: ubuntu-24.04
14
+ #
15
+ # What it does:
16
+ # - creates the VM (if missing)
17
+ # - injects port forwarding rules for the hstack VM port ranges
18
+ # - restarts the VM so the rules take effect
19
+ # - prints next steps (provision script + hstack commands)
20
+
21
+ if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
22
+ cat <<'EOF'
23
+ Usage:
24
+ ./scripts/provision/macos-lima-happy-vm.sh [vm-name]
25
+
26
+ Examples:
27
+ ./scripts/provision/macos-lima-happy-vm.sh # uses "happy-test"
28
+ ./scripts/provision/macos-lima-happy-vm.sh happy # uses "happy"
29
+ ./scripts/provision/macos-lima-happy-vm.sh happy-vm # uses "happy-vm"
30
+
31
+ Notes:
32
+ - This is intended to be run on the macOS host (not inside the VM).
33
+ - It configures localhost port forwarding so you can open http://localhost / http://*.localhost
34
+ in your macOS browser (required for WebCrypto APIs used by Expo web).
35
+ EOF
36
+ exit 0
37
+ fi
38
+
39
+ if [[ "$(uname -s)" != "Darwin" ]]; then
40
+ echo "[lima] expected macOS (Darwin); got: $(uname -s)" >&2
41
+ exit 1
42
+ fi
43
+
44
+ if ! command -v limactl >/dev/null 2>&1; then
45
+ echo "[lima] limactl not found. Install Lima first (example: brew install lima)." >&2
46
+ exit 1
47
+ fi
48
+
49
+ VM_NAME="${1:-happy-test}"
50
+ TEMPLATE="${LIMA_TEMPLATE:-ubuntu-24.04}"
51
+ LIMA_MEMORY="${LIMA_MEMORY:-8GiB}"
52
+ LIMA_VM_TYPE="${LIMA_VM_TYPE:-}" # optional: vz|qemu|krunkit (see: limactl create --list-drivers)
53
+ TEMPLATE_LOCATOR="${TEMPLATE}"
54
+ if [[ "${TEMPLATE_LOCATOR}" == template://* ]]; then
55
+ TEMPLATE_LOCATOR="template:${TEMPLATE_LOCATOR#template://}"
56
+ elif [[ "${TEMPLATE_LOCATOR}" != template:* ]]; then
57
+ TEMPLATE_LOCATOR="template:${TEMPLATE_LOCATOR}"
58
+ fi
59
+ LIMA_HOME_DIR="${LIMA_HOME:-${HOME}/.lima}"
60
+ export LIMA_HOME="${LIMA_HOME_DIR}"
61
+ LIMA_DIR="${LIMA_HOME_DIR}/${VM_NAME}"
62
+ LIMA_YAML="${LIMA_DIR}/lima.yaml"
63
+
64
+ echo "[lima] vm: ${VM_NAME}"
65
+ echo "[lima] template: ${TEMPLATE}"
66
+ echo "[lima] memory: ${LIMA_MEMORY} (override with LIMA_MEMORY=...)"
67
+ echo "[lima] LIMA_HOME: ${LIMA_HOME_DIR}"
68
+ if [[ -n "${LIMA_VM_TYPE}" ]]; then
69
+ echo "[lima] vmType: ${LIMA_VM_TYPE}"
70
+ fi
71
+
72
+ if [[ ! -f "${LIMA_YAML}" ]]; then
73
+ echo "[lima] creating VM..."
74
+ if [[ "${LIMA_VM_TYPE}" == "qemu" ]]; then
75
+ if ! command -v qemu-system-aarch64 >/dev/null 2>&1; then
76
+ echo "[lima] qemu vmType requested but qemu-system-aarch64 is missing." >&2
77
+ echo "[lima] Fix: brew install qemu" >&2
78
+ exit 1
79
+ fi
80
+ fi
81
+ create_args=(create --name "${VM_NAME}" --tty=false)
82
+ if [[ -n "${LIMA_VM_TYPE}" ]]; then
83
+ create_args+=(--vm-type "${LIMA_VM_TYPE}")
84
+ fi
85
+ create_args+=("${TEMPLATE_LOCATOR}")
86
+ limactl "${create_args[@]}"
87
+ fi
88
+
89
+ if [[ ! -f "${LIMA_YAML}" ]]; then
90
+ echo "[lima] expected instance config at: ${LIMA_YAML}" >&2
91
+ exit 1
92
+ fi
93
+
94
+ echo "[lima] stopping VM (if running)..."
95
+ limactl stop "${VM_NAME}" >/dev/null 2>&1 || true
96
+
97
+ echo "[lima] configuring port forwarding (localhost)..."
98
+ cp -a "${LIMA_YAML}" "${LIMA_YAML}.bak.$(date +%Y%m%d-%H%M%S)"
99
+
100
+ VM_NAME="${VM_NAME}" LIMA_YAML="${LIMA_YAML}" LIMA_MEMORY="${LIMA_MEMORY}" python3 - <<'PY'
101
+ import os, re
102
+ from pathlib import Path
103
+
104
+ vm_name = os.environ["VM_NAME"]
105
+ path = Path(os.environ["LIMA_YAML"])
106
+ memory = os.environ.get("LIMA_MEMORY", "8GiB")
107
+ text = path.read_text(encoding="utf-8")
108
+
109
+ MEM_MARK_BEGIN = "# --- hstack vm sizing (managed by hstack) ---"
110
+ MEM_MARK_END = "# --- /hstack vm sizing ---"
111
+ MARK_BEGIN = "# --- hstack port forwards (managed by hstack) ---"
112
+ MARK_END = "# --- /hstack port forwards ---"
113
+
114
+ entries = [
115
+ " - guestPortRange: [13000, 13999]\n hostPortRange: [13000, 13999]\n",
116
+ " - guestPortRange: [18000, 19099]\n hostPortRange: [18000, 19099]\n",
117
+ ]
118
+
119
+ mem_block = (
120
+ f"\n{MEM_MARK_BEGIN}\n"
121
+ f'memory: "{memory}"\n'
122
+ f"{MEM_MARK_END}\n"
123
+ )
124
+
125
+ block_as_section = (
126
+ f"\n{MARK_BEGIN}\n"
127
+ "portForwards:\n"
128
+ + "".join(entries) +
129
+ f"{MARK_END}\n"
130
+ )
131
+
132
+ block_as_list_items = (
133
+ f" # --- hstack port forwards (managed by hstack) ---\n"
134
+ + "".join(entries) +
135
+ f" # --- /hstack port forwards ---\n"
136
+ )
137
+
138
+ if MEM_MARK_BEGIN in text and MEM_MARK_END in text:
139
+ text = re.sub(
140
+ re.escape(MEM_MARK_BEGIN) + r"[\\s\\S]*?" + re.escape(MEM_MARK_END) + r"\\n?",
141
+ mem_block.strip("\n") + "\n",
142
+ text,
143
+ flags=re.MULTILINE,
144
+ )
145
+ else:
146
+ m = re.search(r"^memory:\\s*.*$", text, flags=re.MULTILINE)
147
+ if m:
148
+ text = re.sub(r"^memory:\\s*.*$", f'memory: "{memory}"', text, flags=re.MULTILINE)
149
+ else:
150
+ text = text.rstrip() + mem_block
151
+
152
+ if MARK_BEGIN in text and MARK_END in text:
153
+ text = re.sub(
154
+ re.escape(MARK_BEGIN) + r"[\\s\\S]*?" + re.escape(MARK_END) + r"\\n?",
155
+ block_as_section.strip("\n") + "\n",
156
+ text,
157
+ flags=re.MULTILINE,
158
+ )
159
+ else:
160
+ m = re.search(r"^portForwards:\\s*$", text, flags=re.MULTILINE)
161
+ if m:
162
+ insert_at = m.end()
163
+ text = text[:insert_at] + "\n" + block_as_list_items + text[insert_at:]
164
+ else:
165
+ text = text.rstrip() + block_as_section
166
+
167
+ path.write_text(text, encoding="utf-8")
168
+ print(f"[lima] updated {path} ({vm_name})")
169
+ PY
170
+
171
+ echo "[lima] starting VM..."
172
+ limactl start "${VM_NAME}"
173
+
174
+ cat <<EOF
175
+
176
+ [lima] done.
177
+
178
+ Next steps:
179
+ limactl shell ${VM_NAME}
180
+
181
+ Inside the VM:
182
+ curl -fsSL https://raw.githubusercontent.com/happier-dev/happier/main/apps/stack/scripts/provision/linux-ubuntu-review-pr.sh -o /tmp/linux-ubuntu-review-pr.sh \\
183
+ && chmod +x /tmp/linux-ubuntu-review-pr.sh \\
184
+ && /tmp/linux-ubuntu-review-pr.sh
185
+
186
+ Then:
187
+ npx --yes -p @happier-dev/stack@latest hstack setup --profile=dev --bind=loopback
188
+
189
+ Tip:
190
+ Open the printed URLs on your macOS host via http://localhost:<port> or http://*.localhost:<port>.
191
+ For `npx --yes -p @happier-dev/stack hstack review-pr ...` inside the VM, pass `--vm-ports` so stack ports land in the forwarded ranges.
192
+ EOF
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Automated Lima VM E2E smoke test runner for hstack.
5
+ #
6
+ # Usage (macOS host):
7
+ # ./scripts/provision/macos-lima-hstack-e2e.sh [vm-name]
8
+ #
9
+ # Env:
10
+ # HSTACK_VERSION=latest # @happier-dev/stack version to test (default: latest)
11
+ # HSTACK_E2E_KEEP=1 # keep sandbox dir in the VM (default: 0)
12
+ # HSTACK_RAW_BASE=... # override raw github base (default: happier-dev/happier main)
13
+ #
14
+ # This script:
15
+ # - creates/configures a Lima VM (via macos-lima-happy-vm.sh)
16
+ # - provisions Node/Yarn inside the VM
17
+ # - runs a sandboxed `hstack` selfhost+worktree smoke test inside the VM
18
+
19
+ if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
20
+ cat <<'EOF'
21
+ Usage:
22
+ ./scripts/provision/macos-lima-hstack-e2e.sh [vm-name]
23
+
24
+ Examples:
25
+ ./scripts/provision/macos-lima-hstack-e2e.sh
26
+ HSTACK_VERSION=latest ./scripts/provision/macos-lima-hstack-e2e.sh happy-e2e
27
+
28
+ Notes:
29
+ - Run on macOS (Darwin) host.
30
+ - Uses a fully isolated sandbox inside the VM (does not touch ~/.happier-stack on the VM).
31
+ EOF
32
+ exit 0
33
+ fi
34
+
35
+ if [[ "$(uname -s)" != "Darwin" ]]; then
36
+ echo "[lima-e2e] expected macOS (Darwin); got: $(uname -s)" >&2
37
+ exit 1
38
+ fi
39
+
40
+ if ! command -v limactl >/dev/null 2>&1; then
41
+ echo "[lima-e2e] limactl not found. Install Lima first (example: brew install lima)." >&2
42
+ exit 1
43
+ fi
44
+
45
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
46
+ VM_NAME="${1:-happy-e2e}"
47
+
48
+ HSTACK_VERSION="${HSTACK_VERSION:-latest}"
49
+ HSTACK_E2E_KEEP="${HSTACK_E2E_KEEP:-0}"
50
+
51
+ pick_raw_base() {
52
+ if [[ -n "${HSTACK_RAW_BASE:-}" ]]; then
53
+ echo "${HSTACK_RAW_BASE}"
54
+ return 0
55
+ fi
56
+ local candidates=(
57
+ "https://raw.githubusercontent.com/happier-dev/happier/main/apps/stack"
58
+ )
59
+ local c
60
+ for c in "${candidates[@]}"; do
61
+ if curl -fsSL "${c}/scripts/provision/linux-ubuntu-review-pr.sh" -o /dev/null >/dev/null 2>&1; then
62
+ echo "$c"
63
+ return 0
64
+ fi
65
+ done
66
+ return 1
67
+ }
68
+
69
+ HSTACK_RAW_BASE="$(pick_raw_base || true)"
70
+ if [[ -z "${HSTACK_RAW_BASE}" ]]; then
71
+ echo "[lima-e2e] failed to auto-detect raw GitHub base URL for scripts." >&2
72
+ echo "[lima-e2e] Fix: set HSTACK_RAW_BASE=https://raw.githubusercontent.com/<org>/<repo>/<ref>/apps/stack" >&2
73
+ exit 1
74
+ fi
75
+
76
+ echo "[lima-e2e] vm: ${VM_NAME}"
77
+ echo "[lima-e2e] @happier-dev/stack: ${HSTACK_VERSION}"
78
+ echo "[lima-e2e] raw base: ${HSTACK_RAW_BASE}"
79
+
80
+ echo "[lima-e2e] ensure VM exists + port forwarding..."
81
+ "${SCRIPT_DIR}/macos-lima-happy-vm.sh" "${VM_NAME}"
82
+
83
+ echo "[lima-e2e] running provisioning + e2e inside VM..."
84
+ limactl shell "${VM_NAME}" -- bash -lc "
85
+ set -euo pipefail
86
+ echo '[vm] downloading provision + e2e scripts...'
87
+ curl -fsSL '${HSTACK_RAW_BASE}/scripts/provision/linux-ubuntu-review-pr.sh' -o /tmp/linux-ubuntu-review-pr.sh
88
+ chmod +x /tmp/linux-ubuntu-review-pr.sh
89
+ /tmp/linux-ubuntu-review-pr.sh
90
+
91
+ curl -fsSL '${HSTACK_RAW_BASE}/scripts/provision/linux-ubuntu-e2e.sh' -o /tmp/linux-ubuntu-e2e.sh
92
+ chmod +x /tmp/linux-ubuntu-e2e.sh
93
+
94
+ export HSTACK_VERSION='${HSTACK_VERSION}'
95
+ export HSTACK_E2E_KEEP='${HSTACK_E2E_KEEP}'
96
+ /tmp/linux-ubuntu-e2e.sh
97
+ "
98
+
99
+ echo ""
100
+ echo "[lima-e2e] done."
@@ -0,0 +1,53 @@
1
+ import { spawnSync } from "node:child_process";
2
+
3
+ function run(cmd, args) {
4
+ const result = spawnSync(cmd, args, { stdio: "inherit" });
5
+ if (result.error) throw result.error;
6
+ if (typeof result.status === "number" && result.status !== 0) process.exit(result.status);
7
+ }
8
+
9
+ function usageAndExit() {
10
+ // Keep this very short; this is an internal dev script.
11
+ console.error("Usage: npm run release -- <patch|minor|major>");
12
+ console.error("");
13
+ console.error("Options:");
14
+ console.error(" --no-git Skip git commit/tag (allows dirty working tree).");
15
+ console.error(" --dry-run Run npm publish with --dry-run.");
16
+ process.exit(2);
17
+ }
18
+
19
+ const args = process.argv.slice(2);
20
+ if (args[0] === "--") args.shift();
21
+
22
+ const noGit = args.includes("--no-git");
23
+ const dryRun = args.includes("--dry-run");
24
+
25
+ const bump = args.find((a) => ["patch", "minor", "major"].includes(a));
26
+ if (!bump) usageAndExit();
27
+
28
+ // Ensure we're authenticated before doing anything that creates a version commit/tag.
29
+ const whoami = spawnSync("npm", ["whoami"], { stdio: "ignore" });
30
+ if (typeof whoami.status === "number" && whoami.status !== 0) {
31
+ run("npm", ["login"]);
32
+ }
33
+
34
+ if (!noGit) {
35
+ // `npm version` makes a git commit + tag by default; it requires a clean working tree.
36
+ const status = spawnSync("git", ["status", "--porcelain"], { encoding: "utf8" });
37
+ if (typeof status.status === "number" && status.status === 0) {
38
+ const out = (status.stdout ?? "").trim();
39
+ if (out.length > 0) {
40
+ console.error("Refusing to version: git working tree is not clean.");
41
+ console.error("`npm version` creates a commit + tag, so it requires a clean tree.");
42
+ console.error("Commit/stash your changes, or re-run with --no-git if you accept publishing uncommitted files.");
43
+ process.exit(1);
44
+ }
45
+ }
46
+
47
+ run("npm", ["version", bump, "-m", "chore(release): %s"]);
48
+ } else {
49
+ // Allow dirty working trees by skipping commit/tagging.
50
+ run("npm", ["version", bump, "--no-git-tag-version", "--force"]);
51
+ }
52
+
53
+ run("npm", ["publish", ...(dryRun ? ["--dry-run"] : [])]);