@isomorph.ai/cli 0.4.0-rc.2 → 0.4.1-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.
@@ -62,6 +62,12 @@ async function runDeploy(rootArg, client, output, tenantId, options = {}) {
62
62
  const profile = await readAppProfile(root);
63
63
  for (const line of describeProfile(profile))
64
64
  output(line);
65
+ // Refused here, in the first second: a deploy with no description used to run
66
+ // the whole gate and open an operation before `confirmProfile` refused it
67
+ // (live, 2026-09-16), and the operation it left behind then blocked the
68
+ // corrected tree as "changed before its upload finished".
69
+ if (!profile.name.trim() || !profile.description.trim())
70
+ throw new CliError("PROFILE_INCOMPLETE", "The app needs a name and a description in .isomorph/app.json before it can deploy.", undefined, "Edit `name` and `description` in .isomorph/app.json (show them to the person first), then run this again.");
65
71
  let pending = await readPending(root, tenantId, client.endpoint);
66
72
  let prior;
67
73
  if (pending) {
@@ -98,8 +104,16 @@ async function runDeploy(rootArg, client, output, tenantId, options = {}) {
98
104
  }
99
105
  if (pending && prior?.sourceSave)
100
106
  pending.uploaded = true;
107
+ // A record whose upload never finished pins nothing: nothing of the old tree
108
+ // reached Isomorph, so the changed tree is simply what this deploy carries.
109
+ // Only an upload already in progress (parts sent, completion pending) must
110
+ // see the bytes it started with.
101
111
  if (pending && !pending.uploaded && pending.sourceDigest !== (await sourceDigest(root)).digest) {
102
- throw new CliError("UPLOAD_SOURCE_CHANGED", "The app changed before its upload finished. Restore the submitted files before continuing this operation.", pending.operationRef);
112
+ if (pending.uploadCompletion)
113
+ throw new CliError("UPLOAD_SOURCE_CHANGED", "The app changed while its upload was in progress. Restore the submitted files to finish it, or wait for it to expire and deploy again.", pending.operationRef);
114
+ output("The app changed since the previous attempt started; deploying the current code on the same operation.");
115
+ pending = { ...pending, sourceDigest: (await sourceDigest(root)).digest, graph: await scanWorkspace(root, { sourceBoundary: "root" }) };
116
+ await writePending(root, pending);
103
117
  }
104
118
  // Link first: the app's identity lands in `.isomorph/kit.lock.json`, which is
105
119
  // one of the deployable files, so a report pinned after the link stays fresh
@@ -114,7 +114,10 @@ export function kitPaths(root) {
114
114
  return { kit, local, declaration: join(kit, "integrations.json"), app: join(kit, "app.json"), lock: join(kit, "kit.lock.json"), checks: join(kit, "checks"), devLock: join(local, "dev.lock"), state: join(local, "state"), report: join(local, "check-report.json") };
115
115
  }
116
116
  export function defaultAppProfile(root) {
117
- return { schema: "isomorph.app/1.0", name: basename(resolve(root)), description: "", audience: [] };
117
+ // A real description from the start: the person changes it, but a first
118
+ // deploy is never refused for a field they have not been shown yet.
119
+ const name = basename(resolve(root));
120
+ return { schema: "isomorph.app/1.0", name, description: `${name}: an app built on Isomorph.`, audience: [] };
118
121
  }
119
122
  /** `.isomorph/app.json` as `init` writes it. */
120
123
  export function renderAppProfile(profile) {
@@ -1 +1 @@
1
- export const CLI_VERSION = "0.4.0-rc.2";
1
+ export const CLI_VERSION = "0.4.1-rc.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@isomorph.ai/cli",
3
- "version": "0.4.0-rc.2",
3
+ "version": "0.4.1-rc.1",
4
4
  "description": "Isomorph development kit CLI",
5
5
  "type": "module",
6
6
  "bin": {