@isomorph.ai/cli 0.3.2-rc.1 → 0.3.3-rc.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.
@@ -86,7 +86,8 @@ async function deploy(rootArg, client, output, tenantId, includePaths = [], opti
86
86
  if (pending && !pending.uploaded && pending.sourceDigest !== (await sourceDigest(root)).digest) {
87
87
  throw new CliError("UPLOAD_SOURCE_CHANGED", "The app changed before its upload finished. Restore the submitted files before continuing this operation.", pending.operationRef);
88
88
  }
89
- const graph = pending?.graph ?? await scanWorkspace(root, { sourceBoundary: "root", ...(includePaths.length ? { includePaths } : {}) });
89
+ const scan = () => scanWorkspace(root, { sourceBoundary: "root", ...(includePaths.length ? { includePaths } : {}) });
90
+ let graph = pending?.graph ?? await scan();
90
91
  if (!graph.deploymentScope.includedFiles.length)
91
92
  throw new CliError("PREFLIGHT_EMPTY", "The selected app boundary contains no eligible files.");
92
93
  if (graph.deploymentScope.includedFiles.some(isProhibitedSecretPath))
@@ -100,7 +101,8 @@ async function deploy(rootArg, client, output, tenantId, includePaths = [], opti
100
101
  // before any grant lookup, database replay, operation or upload.
101
102
  if (!pending?.uploaded)
102
103
  await assertChecksPassedForTree(root, output);
103
- const files = pending?.uploaded ? [] : await Promise.all(graph.deploymentScope.includedFiles.map(async (path) => ({ path, content: new Uint8Array(await readFile(resolve(root, path))) })));
104
+ const readTree = async () => pending?.uploaded ? [] : await Promise.all(graph.deploymentScope.includedFiles.map(async (path) => ({ path, content: new Uint8Array(await readFile(resolve(root, path))) })));
105
+ let files = await readTree();
104
106
  output(`Isomorph found ${graph.deploymentScope.includedFiles.length} app files.`);
105
107
  // A declared connection IT has not approved yet would only park the
106
108
  // deployment after the save; file the request and refuse here, before any operation exists.
@@ -113,8 +115,26 @@ async function deploy(rootArg, client, output, tenantId, includePaths = [], opti
113
115
  // operation no journey exercises, a cross-user leak) is refused here,
114
116
  // before the save, by the same gate with the same wording.
115
117
  const gate = options.kitGate === false ? undefined : options.kitGate ?? (options.integrations ? { bundle: options.integrations.bundle } : undefined);
116
- if (gate && !pending?.uploaded)
118
+ if (gate && !pending?.uploaded) {
117
119
  await preflightKitGate(root, gate.bundle, output, gate.run);
120
+ // The gate AUTHORS `.isomorph/checks/*.mjs` — the retained journeys the cloud replays. On an app
121
+ // that has never run `isomorph check` on its own they did not exist when the tree was scanned
122
+ // above, so the package shipped without them and the cloud gate, which has no journeys to run,
123
+ // refused every write the source performs as unexercised. Locally the same gate had just
124
+ // generated and passed them, so the app looked ready and the refusal named `src/App.tsx` rather
125
+ // than the missing files (2026-09-15). Re-read the tree the gate leaves behind.
126
+ if (!pending) {
127
+ graph = await scan();
128
+ files = await readTree();
129
+ }
130
+ }
131
+ // The journeys are the app's proof for the cloud gate; a package without the ones on disk is
132
+ // refused there, minutes later, in terms that point at the app instead of the package.
133
+ const packaged = new Set(graph.deploymentScope.includedFiles);
134
+ const unpackaged = (await retainedChecks(root)).filter(name => !packaged.has(`.isomorph/checks/${name}`));
135
+ if (!pending?.uploaded && unpackaged.length) {
136
+ throw new CliError("CHECKS_NOT_PACKAGED", `The app package does not carry its retained check${unpackaged.length === 1 ? "" : "s"} (${nameList(unpackaged)}), so the deployment would have nothing to replay.`, undefined, "Run `isomorph check --app-root .`, then run this again.");
137
+ }
118
138
  // A `CliError` is Isomorph's own answer (`AUTH_REQUIRED` after two 401s, a
119
139
  // JSON-RPC refusal) and reaches the builder as it is; only a plain Error from
120
140
  // the transport — Isomorph out of reach — is "not started". Reporting a
@@ -1 +1 @@
1
- export const CLI_VERSION = "0.3.2-rc.1";
1
+ export const CLI_VERSION = "0.3.3-rc.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@isomorph.ai/cli",
3
- "version": "0.3.2-rc.1",
3
+ "version": "0.3.3-rc.1",
4
4
  "description": "Isomorph development kit CLI",
5
5
  "type": "module",
6
6
  "bin": {