@mondaydotcomorg/z2h-cli 0.22.0 → 0.23.1-feat-z2h-beta-poc-35890fa

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 (135) hide show
  1. package/dist/auth.d.ts +3 -0
  2. package/dist/auth.d.ts.map +1 -0
  3. package/dist/auth.js +11 -0
  4. package/dist/commands/__tests__/beta.test.d.ts +2 -0
  5. package/dist/commands/__tests__/beta.test.d.ts.map +1 -0
  6. package/dist/commands/__tests__/migrate.test.d.ts +2 -0
  7. package/dist/commands/__tests__/migrate.test.d.ts.map +1 -0
  8. package/dist/commands/beta.d.ts +4 -0
  9. package/dist/commands/beta.d.ts.map +1 -0
  10. package/dist/commands/beta.js +82 -0
  11. package/dist/commands/deploy.d.ts.map +1 -1
  12. package/dist/commands/deploy.js +6 -2
  13. package/dist/commands/doctor.d.ts.map +1 -1
  14. package/dist/commands/doctor.js +32 -6
  15. package/dist/commands/migrate.d.ts +1 -0
  16. package/dist/commands/migrate.d.ts.map +1 -1
  17. package/dist/commands/migrate.js +17 -6
  18. package/dist/esm/auth.d.ts +3 -0
  19. package/dist/esm/auth.d.ts.map +1 -0
  20. package/dist/esm/auth.mjs +2 -0
  21. package/dist/esm/commands/__tests__/beta.test.d.ts +2 -0
  22. package/dist/esm/commands/__tests__/beta.test.d.ts.map +1 -0
  23. package/dist/esm/commands/__tests__/migrate.test.d.ts +2 -0
  24. package/dist/esm/commands/__tests__/migrate.test.d.ts.map +1 -0
  25. package/dist/esm/commands/beta.d.ts +4 -0
  26. package/dist/esm/commands/beta.d.ts.map +1 -0
  27. package/dist/esm/commands/beta.mjs +78 -0
  28. package/dist/esm/commands/deploy.d.ts.map +1 -1
  29. package/dist/esm/commands/deploy.mjs +6 -2
  30. package/dist/esm/commands/doctor.d.ts.map +1 -1
  31. package/dist/esm/commands/doctor.mjs +32 -6
  32. package/dist/esm/commands/migrate.d.ts +1 -0
  33. package/dist/esm/commands/migrate.d.ts.map +1 -1
  34. package/dist/esm/commands/migrate.mjs +17 -7
  35. package/dist/esm/index.mjs +36 -0
  36. package/dist/esm/s3.d.ts +3 -0
  37. package/dist/esm/s3.d.ts.map +1 -0
  38. package/dist/esm/s3.mjs +2 -0
  39. package/dist/esm/util/__tests__/dev-env.test.d.ts +2 -0
  40. package/dist/esm/util/__tests__/dev-env.test.d.ts.map +1 -0
  41. package/dist/esm/util/__tests__/tracker.test.d.ts +2 -0
  42. package/dist/esm/util/__tests__/tracker.test.d.ts.map +1 -0
  43. package/dist/esm/util/beta/__tests__/beta-client.test.d.ts +2 -0
  44. package/dist/esm/util/beta/__tests__/beta-client.test.d.ts.map +1 -0
  45. package/dist/esm/util/beta/__tests__/beta-store.test.d.ts +2 -0
  46. package/dist/esm/util/beta/__tests__/beta-store.test.d.ts.map +1 -0
  47. package/dist/esm/util/beta/__tests__/pin-host-mf-version.test.d.ts +2 -0
  48. package/dist/esm/util/beta/__tests__/pin-host-mf-version.test.d.ts.map +1 -0
  49. package/dist/esm/util/beta/beta-client.d.ts +13 -0
  50. package/dist/esm/util/beta/beta-client.d.ts.map +1 -0
  51. package/dist/esm/util/beta/beta-client.mjs +18 -0
  52. package/dist/esm/util/beta/beta-store.d.ts +7 -0
  53. package/dist/esm/util/beta/beta-store.d.ts.map +1 -0
  54. package/dist/esm/util/beta/beta-store.mjs +35 -0
  55. package/dist/esm/util/beta/pin-host-mf-version.d.ts +2 -0
  56. package/dist/esm/util/beta/pin-host-mf-version.d.ts.map +1 -0
  57. package/dist/esm/util/beta/pin-host-mf-version.mjs +11 -0
  58. package/dist/esm/util/dev-env.d.ts +3 -0
  59. package/dist/esm/util/dev-env.d.ts.map +1 -0
  60. package/dist/esm/util/dev-env.mjs +10 -0
  61. package/dist/esm/util/manifest.d.ts +0 -4
  62. package/dist/esm/util/manifest.d.ts.map +1 -1
  63. package/dist/esm/util/manifest.mjs +0 -31
  64. package/dist/esm/util/s3/upload.d.ts +1 -1
  65. package/dist/esm/util/s3/upload.d.ts.map +1 -1
  66. package/dist/esm/util/s3/upload.mjs +2 -2
  67. package/dist/esm/util/tracker.d.ts.map +1 -1
  68. package/dist/esm/util/tracker.mjs +9 -1
  69. package/dist/esm/util/update-script.d.ts +2 -0
  70. package/dist/esm/util/update-script.d.ts.map +1 -0
  71. package/dist/esm/util/update-script.mjs +6 -0
  72. package/dist/index.js +36 -0
  73. package/dist/s3.d.ts +3 -0
  74. package/dist/s3.d.ts.map +1 -0
  75. package/dist/s3.js +10 -0
  76. package/dist/util/__tests__/dev-env.test.d.ts +2 -0
  77. package/dist/util/__tests__/dev-env.test.d.ts.map +1 -0
  78. package/dist/util/__tests__/tracker.test.d.ts +2 -0
  79. package/dist/util/__tests__/tracker.test.d.ts.map +1 -0
  80. package/dist/util/beta/__tests__/beta-client.test.d.ts +2 -0
  81. package/dist/util/beta/__tests__/beta-client.test.d.ts.map +1 -0
  82. package/dist/util/beta/__tests__/beta-store.test.d.ts +2 -0
  83. package/dist/util/beta/__tests__/beta-store.test.d.ts.map +1 -0
  84. package/dist/util/beta/__tests__/pin-host-mf-version.test.d.ts +2 -0
  85. package/dist/util/beta/__tests__/pin-host-mf-version.test.d.ts.map +1 -0
  86. package/dist/util/beta/beta-client.d.ts +13 -0
  87. package/dist/util/beta/beta-client.d.ts.map +1 -0
  88. package/dist/util/beta/beta-client.js +21 -0
  89. package/dist/util/beta/beta-store.d.ts +7 -0
  90. package/dist/util/beta/beta-store.d.ts.map +1 -0
  91. package/dist/util/beta/beta-store.js +45 -0
  92. package/dist/util/beta/pin-host-mf-version.d.ts +2 -0
  93. package/dist/util/beta/pin-host-mf-version.d.ts.map +1 -0
  94. package/dist/util/beta/pin-host-mf-version.js +13 -0
  95. package/dist/util/dev-env.d.ts +3 -0
  96. package/dist/util/dev-env.d.ts.map +1 -0
  97. package/dist/util/dev-env.js +18 -0
  98. package/dist/util/manifest.d.ts +0 -4
  99. package/dist/util/manifest.d.ts.map +1 -1
  100. package/dist/util/manifest.js +0 -36
  101. package/dist/util/s3/upload.d.ts +1 -1
  102. package/dist/util/s3/upload.d.ts.map +1 -1
  103. package/dist/util/s3/upload.js +2 -2
  104. package/dist/util/tracker.d.ts.map +1 -1
  105. package/dist/util/tracker.js +10 -1
  106. package/dist/util/update-script.d.ts +2 -0
  107. package/dist/util/update-script.d.ts.map +1 -0
  108. package/dist/util/update-script.js +13 -0
  109. package/handler-api/backend-runner/channels/snowflake-channel/run-query.ts +20 -8
  110. package/package.json +12 -1
  111. package/src/auth.ts +2 -0
  112. package/src/commands/__tests__/beta.test.ts +165 -0
  113. package/src/commands/__tests__/deploy.test.ts +18 -0
  114. package/src/commands/__tests__/doctor.test.ts +25 -0
  115. package/src/commands/__tests__/migrate.test.ts +34 -0
  116. package/src/commands/beta.ts +96 -0
  117. package/src/commands/deploy.ts +9 -2
  118. package/src/commands/doctor.ts +34 -7
  119. package/src/commands/migrate.ts +17 -6
  120. package/src/index.ts +38 -0
  121. package/src/s3.ts +2 -0
  122. package/src/templates/workspace/package.json.tmpl +1 -1
  123. package/src/util/__tests__/dev-env.test.ts +86 -0
  124. package/src/util/__tests__/tracker.test.ts +61 -0
  125. package/src/util/beta/__tests__/beta-client.test.ts +69 -0
  126. package/src/util/beta/__tests__/beta-store.test.ts +66 -0
  127. package/src/util/beta/__tests__/pin-host-mf-version.test.ts +23 -0
  128. package/src/util/beta/beta-client.ts +30 -0
  129. package/src/util/beta/beta-store.ts +39 -0
  130. package/src/util/beta/pin-host-mf-version.ts +10 -0
  131. package/src/util/dev-env.ts +9 -0
  132. package/src/util/manifest.ts +0 -37
  133. package/src/util/s3/upload.ts +6 -2
  134. package/src/util/tracker.ts +10 -1
  135. package/src/util/update-script.ts +4 -0
package/dist/auth.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { generateZ2HTokenCommand, type GenerateZ2HTokenOptions } from './commands/generate-z2h-token';
2
+ export { readZthAuth, Z2hAuthMissingError, Z2H_AUTH_FILE, type ZthAuth } from './util/auth/auth-store';
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,KAAK,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACtG,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/auth.js ADDED
@@ -0,0 +1,11 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const commands_generateZ2hToken = require('./commands/generate-z2h-token.js');
4
+ const util_auth_authStore = require('./util/auth/auth-store.js');
5
+
6
+
7
+
8
+ exports.generateZ2HTokenCommand = commands_generateZ2hToken.generateZ2HTokenCommand;
9
+ exports.Z2H_AUTH_FILE = util_auth_authStore.Z2H_AUTH_FILE;
10
+ exports.Z2hAuthMissingError = util_auth_authStore.Z2hAuthMissingError;
11
+ exports.readZthAuth = util_auth_authStore.readZthAuth;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=beta.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"beta.test.d.ts","sourceRoot":"","sources":["../../../src/commands/__tests__/beta.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=migrate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.test.d.ts","sourceRoot":"","sources":["../../../src/commands/__tests__/migrate.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ export declare function betaStatusCommand(): Promise<void>;
2
+ export declare function enterBetaCommand(): Promise<void>;
3
+ export declare function exitBetaCommand(): Promise<void>;
4
+ //# sourceMappingURL=beta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"beta.d.ts","sourceRoot":"","sources":["../../src/commands/beta.ts"],"names":[],"mappings":"AAuBA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0BvD;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0BtD;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBrD"}
@@ -0,0 +1,82 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const fs = require('fs-extra');
4
+ const execa = require('execa');
5
+ const util_logger = require('../util/logger.js');
6
+ const util_beta_betaClient = require('../util/beta/beta-client.js');
7
+ const util_beta_betaStore = require('../util/beta/beta-store.js');
8
+ const util_updateScript = require('../util/update-script.js');
9
+
10
+ async function converge() {
11
+ if (!(await fs.pathExists(util_updateScript.UPDATE_SCRIPT_PATH))) {
12
+ util_logger.warn(`update script not found at ${util_updateScript.UPDATE_SCRIPT_PATH} — skipping convergence`);
13
+ return;
14
+ }
15
+ try {
16
+ await execa.execa('bash', [util_updateScript.UPDATE_SCRIPT_PATH], { stdio: 'inherit' });
17
+ }
18
+ catch (err) {
19
+ util_logger.warn(`convergence failed: ${err.message}\nYour beta choice is saved — run 'bash ${util_updateScript.UPDATE_SCRIPT_PATH}' to retry.`);
20
+ }
21
+ }
22
+ async function betaStatusCommand() {
23
+ const active = await util_beta_betaStore.readBetaState();
24
+ if (!active) {
25
+ util_logger.output("[z2h-cli] you're not on a beta — run 'z2h-cli beta enter' to check for one and join", {
26
+ published: null,
27
+ active: null,
28
+ });
29
+ return;
30
+ }
31
+ const published = await util_beta_betaClient.fetchPublishedBeta();
32
+ if (!published) {
33
+ util_logger.output(`[z2h-cli] beta "${active.id}" is no longer published — converging back to stable in the background now`, {
34
+ published: null,
35
+ active: active.id,
36
+ });
37
+ return;
38
+ }
39
+ const inIt = active.id === published.id;
40
+ util_logger.output(`[z2h-cli] beta "${published.id}" — ${published.description} (${inIt ? "you're in it" : 'not in it'})`, {
41
+ published: published.id,
42
+ active: active.id,
43
+ });
44
+ }
45
+ async function enterBetaCommand() {
46
+ const active = await util_beta_betaStore.readBetaState();
47
+ if (active) {
48
+ throw new Error(`already on beta "${active.id}" — run 'z2h-cli beta exit' first`);
49
+ }
50
+ const beta = await util_beta_betaClient.fetchPublishedBeta();
51
+ if (!beta) {
52
+ throw new Error('no beta published right now');
53
+ }
54
+ await util_beta_betaStore.writeBetaState({
55
+ id: beta.id,
56
+ description: beta.description,
57
+ cliVersion: beta.cliVersion,
58
+ skillsBranch: beta.skillsBranch,
59
+ hostMfVersion: beta.hostMfVersion,
60
+ });
61
+ util_logger.info(`entering beta "${beta.id}" — ${beta.description}`);
62
+ await converge();
63
+ util_logger.output(`[z2h-cli] you're on beta "${beta.id}". Start a new Claude Code / Cursor session to pick up any skills change.`, { ok: true, beta: beta.id });
64
+ }
65
+ async function exitBetaCommand() {
66
+ const active = await util_beta_betaStore.readBetaState();
67
+ await util_beta_betaStore.clearBetaState();
68
+ if (!active) {
69
+ util_logger.output("[z2h-cli] no beta was active — you're already on stable", { ok: true, beta: null });
70
+ return;
71
+ }
72
+ util_logger.info(`leaving beta "${active.id}"`);
73
+ await converge();
74
+ util_logger.output("[z2h-cli] you're back on stable. Start a new Claude Code / Cursor session to pick up the change.", {
75
+ ok: true,
76
+ beta: null,
77
+ });
78
+ }
79
+
80
+ exports.betaStatusCommand = betaStatusCommand;
81
+ exports.enterBetaCommand = enterBetaCommand;
82
+ exports.exitBetaCommand = exitBetaCommand;
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,KAAK,UAAU,EAA2C,MAAM,4BAA4B,CAAC;AAiBtG,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAWD,wBAAsB,aAAa,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB3E"}
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,KAAK,UAAU,EAA2C,MAAM,4BAA4B,CAAC;AAiBtG,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAWD,wBAAsB,aAAa,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB3E"}
@@ -9,6 +9,8 @@ const util_s3_upload = require('../util/s3/upload.js');
9
9
  const constants = require('../constants.js');
10
10
  const util_auth_brokerCredentialProvider = require('../util/auth/broker-credential-provider.js');
11
11
  const util_auth_authStore = require('../util/auth/auth-store.js');
12
+ const util_beta_betaStore = require('../util/beta/beta-store.js');
13
+ const util_beta_pinHostMfVersion = require('../util/beta/pin-host-mf-version.js');
12
14
  const util_appName = require('../util/app-name.js');
13
15
  const util_git_repo = require('../util/git/repo.js');
14
16
  const util_git_gitEnv = require('../util/git/git-env.js');
@@ -90,6 +92,7 @@ async function uploadAndRegister(opts) {
90
92
  await util_broker_app.registerOrUpdateApp({ appName, token, nextVersion, entry, gitRemote, integrations, description });
91
93
  }
92
94
  async function deployPreview({ paths, consumerName, appName, token, opts }) {
95
+ const activeBeta = await util_beta_betaStore.readBetaState();
93
96
  await fs.ensureDir(paths.shadowDir);
94
97
  const { previewId } = await shadow_prepare.resolvePortAndMetadata(paths, util_appName.cleanAppName(consumerName));
95
98
  const previewSlug = util_appName.buildPreviewSlug(consumerName, previewId);
@@ -114,7 +117,7 @@ async function deployPreview({ paths, consumerName, appName, token, opts }) {
114
117
  gitRemote: '',
115
118
  isPreview: true,
116
119
  });
117
- const previewUrl = `https://bigbrain.me/bigbrain-vibe/${previewSlug}`;
120
+ const previewUrl = util_beta_pinHostMfVersion.pinHostMfVersion(`https://bigbrain.me/bigbrain-vibe/${previewSlug}`, activeBeta?.hostMfVersion);
118
121
  util_logger.output(`[z2h-cli] preview ready ✅\n app: ${appName}\n previewAppName: ${previewAppName}\n open: ${previewUrl}`, {
119
122
  ok: true,
120
123
  appName,
@@ -130,6 +133,7 @@ async function deployPreview({ paths, consumerName, appName, token, opts }) {
130
133
  }
131
134
  }
132
135
  async function deployLive({ paths, consumerName, appName, token, opts }) {
136
+ const activeBeta = await util_beta_betaStore.readBetaState();
133
137
  let gitRemote = await util_git_repo.getRemoteUrl(process.cwd());
134
138
  if (gitRemote) {
135
139
  if (opts.remote || opts.repoUrl) {
@@ -220,7 +224,7 @@ async function deployLive({ paths, consumerName, appName, token, opts }) {
220
224
  // The host MF parses the app name from the URL and prepends `mf-` itself
221
225
  // before looking it up in the manifest. So the user-facing URL must use
222
226
  // the consumer's de-scoped package name (no `mf-` prefix, no `@scope/`).
223
- const liveUrl = `https://bigbrain.me/bigbrain-vibe/${util_appName.cleanAppName(consumerName)}`;
227
+ const liveUrl = util_beta_pinHostMfVersion.pinHostMfVersion(`https://bigbrain.me/bigbrain-vibe/${util_appName.cleanAppName(consumerName)}`, activeBeta?.hostMfVersion);
224
228
  util_logger.output(`[z2h-cli] deployed ✅\n app: ${appName}\n version: ${nextVersion}\n open: ${liveUrl}`, {
225
229
  ok: true,
226
230
  appName,
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAwSA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAqEnD"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAmUA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAqEnD"}
@@ -11,6 +11,7 @@ const pc = require('picocolors');
11
11
  const util_logger = require('../util/logger.js');
12
12
  const util_workspace = require('../util/workspace.js');
13
13
  const util_auth_authStore = require('../util/auth/auth-store.js');
14
+ const util_beta_betaStore = require('../util/beta/beta-store.js');
14
15
  const constants = require('../constants.js');
15
16
 
16
17
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
@@ -102,7 +103,9 @@ function checkGitRemoteS3() {
102
103
  }
103
104
  async function checkZ2hCli() {
104
105
  const { version } = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('commands/doctor.js', document.baseURI).href)))('../../package.json');
105
- let latestVersion;
106
+ const activeBeta = await util_beta_betaStore.readBetaState();
107
+ const targetTag = activeBeta?.cliVersion ?? 'latest';
108
+ let targetVersion;
106
109
  try {
107
110
  const token = util_auth_authStore.tryReadAuthTokenSync();
108
111
  if (token) {
@@ -112,17 +115,40 @@ async function checkZ2hCli() {
112
115
  });
113
116
  if (res.ok) {
114
117
  const data = (await res.json());
115
- latestVersion = data['dist-tags']?.latest;
118
+ targetVersion = data['dist-tags']?.[targetTag];
116
119
  }
117
120
  }
118
121
  }
119
122
  catch {
120
123
  // version check is best-effort — no network / token not ready
121
124
  }
122
- if (latestVersion && latestVersion !== version) {
123
- return { label: 'z2h-cli', status: 'warn', detail: `${version} (latest: ${latestVersion})`, fix: UPDATE_CMD };
125
+ if (targetVersion && targetVersion !== version) {
126
+ return {
127
+ label: 'z2h-cli',
128
+ status: 'warn',
129
+ detail: `${version} (${targetTag}: ${targetVersion})`,
130
+ fix: UPDATE_CMD,
131
+ };
132
+ }
133
+ return {
134
+ label: 'z2h-cli',
135
+ status: 'ok',
136
+ detail: targetVersion ? `${version} (up to date on ${targetTag})` : version,
137
+ };
138
+ }
139
+ async function checkActiveBeta() {
140
+ const active = await util_beta_betaStore.readBetaState();
141
+ if (!active) {
142
+ return { label: 'beta', status: 'ok', detail: 'none — stable' };
124
143
  }
125
- return { label: 'z2h-cli', status: 'ok', detail: latestVersion ? `${version} (up to date)` : version };
144
+ const pins = [
145
+ active.cliVersion && `cli@${active.cliVersion}`,
146
+ active.skillsBranch && `skills@${active.skillsBranch}`,
147
+ active.hostMfVersion && `hostMf@${active.hostMfVersion}`,
148
+ ]
149
+ .filter(Boolean)
150
+ .join(', ');
151
+ return { label: 'beta', status: 'ok', detail: pins ? `${active.id} (${pins})` : active.id };
126
152
  }
127
153
  async function checkAuthToken() {
128
154
  try {
@@ -264,7 +290,7 @@ async function doctorCommand() {
264
290
  // treat as missing
265
291
  }
266
292
  const systemChecks = await Promise.all([checkNvm(), checkNode(), checkYarn(), checkAws(), checkGitRemoteS3()]);
267
- const cliChecks = await Promise.all([checkZ2hCli(), checkAuthToken(), checkNpmTokenInProfile()]);
293
+ const cliChecks = await Promise.all([checkZ2hCli(), checkAuthToken(), checkNpmTokenInProfile(), checkActiveBeta()]);
268
294
  const workspaceChecks = await Promise.all([checkWorkspace(), checkReactVersion()]);
269
295
  const pluginChecks = await Promise.all([
270
296
  checkPlugin('z2h@bigbrain-z2h', 'z2h plugin', true, pluginsJson),
@@ -1,3 +1,4 @@
1
+ export declare function baseVersion(version: string): string;
1
2
  export interface MigrateOptions {
2
3
  dryRun?: boolean;
3
4
  }
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AA6CA,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkGjG"}
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AA4BA,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMnD;AAqBD,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmGjG"}
@@ -16,6 +16,15 @@ const semver__default = /*#__PURE__*/_interopDefault(semver);
16
16
 
17
17
  const STATE_FILE = '.z2h-migrations-state.json';
18
18
  // ─── Helpers ───
19
+ // A prerelease sorts BELOW its own release under plain semver ordering, so
20
+ // comparing raw beta versions here would skip migrations the beta introduced.
21
+ function baseVersion(version) {
22
+ const parsed = semver__default.default.parse(version);
23
+ if (!parsed) {
24
+ throw new Error(`invalid semver version: ${version}`);
25
+ }
26
+ return `${parsed.major}.${parsed.minor}.${parsed.patch}`;
27
+ }
19
28
  async function readMigrationState(workspaceHome) {
20
29
  const statePath = path__default.default.join(workspaceHome, STATE_FILE);
21
30
  if (!(await fs.pathExists(statePath))) {
@@ -40,11 +49,12 @@ async function migrateCommand(cliVersion, opts = {}) {
40
49
  }
41
50
  const state = await readMigrationState(workspaceHome);
42
51
  const lastVersion = state?.lastMigratedVersion ?? '0.0.0';
43
- if (!semver__default.default.gt(cliVersion, lastVersion)) {
52
+ const targetVersion = baseVersion(cliVersion);
53
+ if (!semver__default.default.gt(targetVersion, lastVersion)) {
44
54
  util_logger.info('workspace is up to date — no migrations pending');
45
55
  return;
46
56
  }
47
- util_logger.info(`migrating workspace from v${lastVersion} → v${cliVersion}...`);
57
+ util_logger.info(`migrating workspace from v${lastVersion} → v${targetVersion}...`);
48
58
  // migrations.json is at the package root — two dirs up from dist/migrations/
49
59
  const thisDir = path__default.default.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('commands/migrate.js', document.baseURI).href))));
50
60
  const migrationsJsonPath = path__default.default.resolve(thisDir, '..', '..', 'migrations.json');
@@ -53,12 +63,12 @@ async function migrateCommand(cliVersion, opts = {}) {
53
63
  return;
54
64
  }
55
65
  const migrationsJson = (await fs.readJson(migrationsJsonPath));
56
- // Filter to pending migrations (version > lastVersion AND <= cliVersion).
66
+ // Filter to pending migrations (version > lastVersion AND <= targetVersion).
57
67
  // CONVENTION: a migration's `version` field must equal the CLI release it
58
68
  // ships with (not the feature branch version). This ensures the `gt` check
59
69
  // always catches a migration on the exact upgrade that introduces it.
60
70
  const pending = Object.entries(migrationsJson.migrations)
61
- .filter(([, entry]) => semver__default.default.gt(entry.version, lastVersion) && semver__default.default.lte(entry.version, cliVersion))
71
+ .filter(([, entry]) => semver__default.default.gt(entry.version, lastVersion) && semver__default.default.lte(entry.version, targetVersion))
62
72
  .sort(([, a], [, b]) => semver__default.default.compare(a.version, b.version));
63
73
  if (opts.dryRun) {
64
74
  util_logger.info(`${pending.length} pending migration(s) (dry-run — no changes will be applied):`);
@@ -68,7 +78,7 @@ async function migrateCommand(cliVersion, opts = {}) {
68
78
  return;
69
79
  }
70
80
  if (pending.length === 0) {
71
- await writeMigrationState(workspaceHome, { lastMigratedVersion: cliVersion });
81
+ await writeMigrationState(workspaceHome, { lastMigratedVersion: targetVersion });
72
82
  return;
73
83
  }
74
84
  const nxReady = await util_workspace.ensureWorkspaceNx(workspaceHome);
@@ -108,8 +118,9 @@ async function migrateCommand(cliVersion, opts = {}) {
108
118
  if (needsInstall) {
109
119
  await util_workspace.runYarnInstall(workspaceHome, 'package.json changed');
110
120
  }
111
- await writeMigrationState(workspaceHome, { lastMigratedVersion: cliVersion });
121
+ await writeMigrationState(workspaceHome, { lastMigratedVersion: targetVersion });
112
122
  util_logger.info('workspace migrations complete.');
113
123
  }
114
124
 
125
+ exports.baseVersion = baseVersion;
115
126
  exports.migrateCommand = migrateCommand;
@@ -0,0 +1,3 @@
1
+ export { generateZ2HTokenCommand, type GenerateZ2HTokenOptions } from './commands/generate-z2h-token';
2
+ export { readZthAuth, Z2hAuthMissingError, Z2H_AUTH_FILE, type ZthAuth } from './util/auth/auth-store';
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,KAAK,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACtG,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { generateZ2HTokenCommand } from './commands/generate-z2h-token.mjs';
2
+ export { Z2H_AUTH_FILE, Z2hAuthMissingError, readZthAuth } from './util/auth/auth-store.mjs';
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=beta.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"beta.test.d.ts","sourceRoot":"","sources":["../../../../src/commands/__tests__/beta.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=migrate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.test.d.ts","sourceRoot":"","sources":["../../../../src/commands/__tests__/migrate.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ export declare function betaStatusCommand(): Promise<void>;
2
+ export declare function enterBetaCommand(): Promise<void>;
3
+ export declare function exitBetaCommand(): Promise<void>;
4
+ //# sourceMappingURL=beta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"beta.d.ts","sourceRoot":"","sources":["../../../src/commands/beta.ts"],"names":[],"mappings":"AAuBA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0BvD;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0BtD;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBrD"}
@@ -0,0 +1,78 @@
1
+ import { pathExists } from 'fs-extra';
2
+ import { execa } from 'execa';
3
+ import { output, info, warn } from '../util/logger.mjs';
4
+ import { fetchPublishedBeta } from '../util/beta/beta-client.mjs';
5
+ import { readBetaState, writeBetaState, clearBetaState } from '../util/beta/beta-store.mjs';
6
+ import { UPDATE_SCRIPT_PATH } from '../util/update-script.mjs';
7
+
8
+ async function converge() {
9
+ if (!(await pathExists(UPDATE_SCRIPT_PATH))) {
10
+ warn(`update script not found at ${UPDATE_SCRIPT_PATH} — skipping convergence`);
11
+ return;
12
+ }
13
+ try {
14
+ await execa('bash', [UPDATE_SCRIPT_PATH], { stdio: 'inherit' });
15
+ }
16
+ catch (err) {
17
+ warn(`convergence failed: ${err.message}\nYour beta choice is saved — run 'bash ${UPDATE_SCRIPT_PATH}' to retry.`);
18
+ }
19
+ }
20
+ async function betaStatusCommand() {
21
+ const active = await readBetaState();
22
+ if (!active) {
23
+ output("[z2h-cli] you're not on a beta — run 'z2h-cli beta enter' to check for one and join", {
24
+ published: null,
25
+ active: null,
26
+ });
27
+ return;
28
+ }
29
+ const published = await fetchPublishedBeta();
30
+ if (!published) {
31
+ output(`[z2h-cli] beta "${active.id}" is no longer published — converging back to stable in the background now`, {
32
+ published: null,
33
+ active: active.id,
34
+ });
35
+ return;
36
+ }
37
+ const inIt = active.id === published.id;
38
+ output(`[z2h-cli] beta "${published.id}" — ${published.description} (${inIt ? "you're in it" : 'not in it'})`, {
39
+ published: published.id,
40
+ active: active.id,
41
+ });
42
+ }
43
+ async function enterBetaCommand() {
44
+ const active = await readBetaState();
45
+ if (active) {
46
+ throw new Error(`already on beta "${active.id}" — run 'z2h-cli beta exit' first`);
47
+ }
48
+ const beta = await fetchPublishedBeta();
49
+ if (!beta) {
50
+ throw new Error('no beta published right now');
51
+ }
52
+ await writeBetaState({
53
+ id: beta.id,
54
+ description: beta.description,
55
+ cliVersion: beta.cliVersion,
56
+ skillsBranch: beta.skillsBranch,
57
+ hostMfVersion: beta.hostMfVersion,
58
+ });
59
+ info(`entering beta "${beta.id}" — ${beta.description}`);
60
+ await converge();
61
+ output(`[z2h-cli] you're on beta "${beta.id}". Start a new Claude Code / Cursor session to pick up any skills change.`, { ok: true, beta: beta.id });
62
+ }
63
+ async function exitBetaCommand() {
64
+ const active = await readBetaState();
65
+ await clearBetaState();
66
+ if (!active) {
67
+ output("[z2h-cli] no beta was active — you're already on stable", { ok: true, beta: null });
68
+ return;
69
+ }
70
+ info(`leaving beta "${active.id}"`);
71
+ await converge();
72
+ output("[z2h-cli] you're back on stable. Start a new Claude Code / Cursor session to pick up the change.", {
73
+ ok: true,
74
+ beta: null,
75
+ });
76
+ }
77
+
78
+ export { betaStatusCommand, enterBetaCommand, exitBetaCommand };
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/commands/deploy.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,KAAK,UAAU,EAA2C,MAAM,4BAA4B,CAAC;AAiBtG,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAWD,wBAAsB,aAAa,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB3E"}
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/commands/deploy.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,KAAK,UAAU,EAA2C,MAAM,4BAA4B,CAAC;AAiBtG,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAWD,wBAAsB,aAAa,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB3E"}
@@ -7,6 +7,8 @@ import { uploadDir } from '../util/s3/upload.mjs';
7
7
  import { BUCKET_WRITE_NAME, brokerBaseUrl, routingHeaders, S3_PREVIEWS_FOLDER, BUCKET_READ_DNS_URL } from '../constants.mjs';
8
8
  import { fetchDeployVersion, brokerCredentialProvider } from '../util/auth/broker-credential-provider.mjs';
9
9
  import { readZthAuth } from '../util/auth/auth-store.mjs';
10
+ import { readBetaState } from '../util/beta/beta-store.mjs';
11
+ import { pinHostMfVersion } from '../util/beta/pin-host-mf-version.mjs';
10
12
  import { validateAppName, cleanAppName, mfAppName, buildPreviewSlug } from '../util/app-name.mjs';
11
13
  import { getRemoteUrl, initRepo, guardCleanTree, pullAndResolve, pushToRemote } from '../util/git/repo.mjs';
12
14
  import { resolveGitEnv } from '../util/git/git-env.mjs';
@@ -84,6 +86,7 @@ async function uploadAndRegister(opts) {
84
86
  await registerOrUpdateApp({ appName, token, nextVersion, entry, gitRemote, integrations, description });
85
87
  }
86
88
  async function deployPreview({ paths, consumerName, appName, token, opts }) {
89
+ const activeBeta = await readBetaState();
87
90
  await ensureDir(paths.shadowDir);
88
91
  const { previewId } = await resolvePortAndMetadata(paths, cleanAppName(consumerName));
89
92
  const previewSlug = buildPreviewSlug(consumerName, previewId);
@@ -108,7 +111,7 @@ async function deployPreview({ paths, consumerName, appName, token, opts }) {
108
111
  gitRemote: '',
109
112
  isPreview: true,
110
113
  });
111
- const previewUrl = `https://bigbrain.me/bigbrain-vibe/${previewSlug}`;
114
+ const previewUrl = pinHostMfVersion(`https://bigbrain.me/bigbrain-vibe/${previewSlug}`, activeBeta?.hostMfVersion);
112
115
  output(`[z2h-cli] preview ready ✅\n app: ${appName}\n previewAppName: ${previewAppName}\n open: ${previewUrl}`, {
113
116
  ok: true,
114
117
  appName,
@@ -124,6 +127,7 @@ async function deployPreview({ paths, consumerName, appName, token, opts }) {
124
127
  }
125
128
  }
126
129
  async function deployLive({ paths, consumerName, appName, token, opts }) {
130
+ const activeBeta = await readBetaState();
127
131
  let gitRemote = await getRemoteUrl(process.cwd());
128
132
  if (gitRemote) {
129
133
  if (opts.remote || opts.repoUrl) {
@@ -214,7 +218,7 @@ async function deployLive({ paths, consumerName, appName, token, opts }) {
214
218
  // The host MF parses the app name from the URL and prepends `mf-` itself
215
219
  // before looking it up in the manifest. So the user-facing URL must use
216
220
  // the consumer's de-scoped package name (no `mf-` prefix, no `@scope/`).
217
- const liveUrl = `https://bigbrain.me/bigbrain-vibe/${cleanAppName(consumerName)}`;
221
+ const liveUrl = pinHostMfVersion(`https://bigbrain.me/bigbrain-vibe/${cleanAppName(consumerName)}`, activeBeta?.hostMfVersion);
218
222
  output(`[z2h-cli] deployed ✅\n app: ${appName}\n version: ${nextVersion}\n open: ${liveUrl}`, {
219
223
  ok: true,
220
224
  appName,
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor.ts"],"names":[],"mappings":"AAwSA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAqEnD"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor.ts"],"names":[],"mappings":"AAmUA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAqEnD"}
@@ -9,6 +9,7 @@ import pc from 'picocolors';
9
9
  import { getOutputMode, output } from '../util/logger.mjs';
10
10
  import { getWorkspaceHome, isZ2hWorkspace } from '../util/workspace.mjs';
11
11
  import { tryReadAuthTokenSync, Z2H_AUTH_FILE } from '../util/auth/auth-store.mjs';
12
+ import { readBetaState } from '../util/beta/beta-store.mjs';
12
13
  import { brokerNpmRegistryUrl, routingHeaders } from '../constants.mjs';
13
14
 
14
15
  const HOME = os.homedir();
@@ -92,7 +93,9 @@ function checkGitRemoteS3() {
92
93
  }
93
94
  async function checkZ2hCli() {
94
95
  const { version } = createRequire(import.meta.url)('../../package.json');
95
- let latestVersion;
96
+ const activeBeta = await readBetaState();
97
+ const targetTag = activeBeta?.cliVersion ?? 'latest';
98
+ let targetVersion;
96
99
  try {
97
100
  const token = tryReadAuthTokenSync();
98
101
  if (token) {
@@ -102,17 +105,40 @@ async function checkZ2hCli() {
102
105
  });
103
106
  if (res.ok) {
104
107
  const data = (await res.json());
105
- latestVersion = data['dist-tags']?.latest;
108
+ targetVersion = data['dist-tags']?.[targetTag];
106
109
  }
107
110
  }
108
111
  }
109
112
  catch {
110
113
  // version check is best-effort — no network / token not ready
111
114
  }
112
- if (latestVersion && latestVersion !== version) {
113
- return { label: 'z2h-cli', status: 'warn', detail: `${version} (latest: ${latestVersion})`, fix: UPDATE_CMD };
115
+ if (targetVersion && targetVersion !== version) {
116
+ return {
117
+ label: 'z2h-cli',
118
+ status: 'warn',
119
+ detail: `${version} (${targetTag}: ${targetVersion})`,
120
+ fix: UPDATE_CMD,
121
+ };
122
+ }
123
+ return {
124
+ label: 'z2h-cli',
125
+ status: 'ok',
126
+ detail: targetVersion ? `${version} (up to date on ${targetTag})` : version,
127
+ };
128
+ }
129
+ async function checkActiveBeta() {
130
+ const active = await readBetaState();
131
+ if (!active) {
132
+ return { label: 'beta', status: 'ok', detail: 'none — stable' };
114
133
  }
115
- return { label: 'z2h-cli', status: 'ok', detail: latestVersion ? `${version} (up to date)` : version };
134
+ const pins = [
135
+ active.cliVersion && `cli@${active.cliVersion}`,
136
+ active.skillsBranch && `skills@${active.skillsBranch}`,
137
+ active.hostMfVersion && `hostMf@${active.hostMfVersion}`,
138
+ ]
139
+ .filter(Boolean)
140
+ .join(', ');
141
+ return { label: 'beta', status: 'ok', detail: pins ? `${active.id} (${pins})` : active.id };
116
142
  }
117
143
  async function checkAuthToken() {
118
144
  try {
@@ -254,7 +280,7 @@ async function doctorCommand() {
254
280
  // treat as missing
255
281
  }
256
282
  const systemChecks = await Promise.all([checkNvm(), checkNode(), checkYarn(), checkAws(), checkGitRemoteS3()]);
257
- const cliChecks = await Promise.all([checkZ2hCli(), checkAuthToken(), checkNpmTokenInProfile()]);
283
+ const cliChecks = await Promise.all([checkZ2hCli(), checkAuthToken(), checkNpmTokenInProfile(), checkActiveBeta()]);
258
284
  const workspaceChecks = await Promise.all([checkWorkspace(), checkReactVersion()]);
259
285
  const pluginChecks = await Promise.all([
260
286
  checkPlugin('z2h@bigbrain-z2h', 'z2h plugin', true, pluginsJson),
@@ -1,3 +1,4 @@
1
+ export declare function baseVersion(version: string): string;
1
2
  export interface MigrateOptions {
2
3
  dryRun?: boolean;
3
4
  }
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/commands/migrate.ts"],"names":[],"mappings":"AA6CA,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkGjG"}
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/commands/migrate.ts"],"names":[],"mappings":"AA4BA,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMnD;AAqBD,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmGjG"}