deepspace 0.28.1 → 0.29.0

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.
package/dist/cli.js CHANGED
@@ -1800,6 +1800,24 @@ function healBlocker(appDir, wranglerEnv) {
1800
1800
  }
1801
1801
  return null;
1802
1802
  }
1803
+ async function registerForLocalRun(appDir, token, wranglerEnv) {
1804
+ try {
1805
+ return (await ensureAppRegistered(appDir, token, wranglerEnv))?.appId ?? null;
1806
+ } catch (registrationError) {
1807
+ let hasUsableId = false;
1808
+ try {
1809
+ hasUsableId = readAppId(appDir, wranglerEnv) !== null;
1810
+ } catch {
1811
+ }
1812
+ if (!hasUsableId) throw registrationError;
1813
+ const firstLine = registrationError instanceof Error ? registrationError.message.split("\n")[0] : String(registrationError);
1814
+ process.stderr.write(
1815
+ `warning: could not register the app (${firstLine}) \u2014 continuing without app secrets.
1816
+ `
1817
+ );
1818
+ return null;
1819
+ }
1820
+ }
1803
1821
  function healRefusal(appDir, wranglerEnv) {
1804
1822
  const blocker = healBlocker(appDir, wranglerEnv);
1805
1823
  if (blocker === "placeholder_committed") {
@@ -2332,7 +2350,7 @@ function resolveWorkspaceWorktree(worktrees, workspaceId) {
2332
2350
  // src/cli/lib/source-api.ts
2333
2351
  function githubSourceRefusal(appId, repository) {
2334
2352
  return new Refusal(
2335
- `This app uses GitHub source (${repository}). Use normal Git/GitHub for source operations (clone, fetch, push); \`deepspace deploy\` ships the local working tree without changing Git.`,
2353
+ `This app uses GitHub source (${repository}). Use normal Git/GitHub for source operations. \`deepspace deploy\` ships the local working tree without changing Git.`,
2336
2354
  "source_managed_by_github",
2337
2355
  { extra: { appId, repository } }
2338
2356
  );
@@ -3776,7 +3794,11 @@ async function ensurePortFree(port, host, waitMs = 15e3) {
3776
3794
  `Port ${port} is already in use.
3777
3795
  Free it with \`${killArgv.join(" ")}\`, or use another port: \`--port <other>\`.`,
3778
3796
  "port_in_use",
3779
- { extra: { port } }
3797
+ // The machine action the contract documents for this refusal — the prose
3798
+ // named it while `--json` carried none (2026-08-28 coldstart AX). Not
3799
+ // actionRequired: freeing the port and choosing another port are both
3800
+ // legitimate, so the choice stays the caller's.
3801
+ { extra: { port }, action: { cwd: process.cwd(), argv: killArgv } }
3780
3802
  );
3781
3803
  }
3782
3804
  async function isHttpResponding(port, timeoutMs = 2e3) {
@@ -3918,6 +3940,7 @@ var dev_default = defineDeepspaceCommand({
3918
3940
  writeLaunchConfigIfMissing(appDir, detectAppName(appDir) ?? basename2(appDir), port, {
3919
3941
  updatePort: explicitPort
3920
3942
  });
3943
+ ensureInstallReady(appDir);
3921
3944
  let token;
3922
3945
  try {
3923
3946
  token = await ensureToken();
@@ -3940,21 +3963,12 @@ var dev_default = defineDeepspaceCommand({
3940
3963
  if (wranglerEnv) say(`Wrangler env: ${wranglerEnv}`);
3941
3964
  say(`Port: ${port}`);
3942
3965
  if (host !== DEFAULT_DEV_HOST) say(`Host: ${host}`);
3943
- ensureInstallReady(appDir);
3944
3966
  const lintFindings = await lintProjectSchemas(appDir);
3945
3967
  if (lintFindings && lintFindings.length > 0 && !args.json) {
3946
3968
  for (const line of formatSchemaLintFindings(lintFindings)) console.warn(line);
3947
3969
  }
3948
3970
  let generatedSecretsCache;
3949
- let appIdForSecrets = null;
3950
- try {
3951
- appIdForSecrets = (await ensureAppRegistered(appDir, token, wranglerEnv))?.appId ?? null;
3952
- } catch (registrationError) {
3953
- process.stderr.write(
3954
- `warning: could not register the app (${registrationError instanceof Error ? registrationError.message.split("\n")[0] : String(registrationError)}) \u2014 continuing without app secrets.
3955
- `
3956
- );
3957
- }
3971
+ const appIdForSecrets = await registerForLocalRun(appDir, token, wranglerEnv);
3958
3972
  if (appIdForSecrets) {
3959
3973
  try {
3960
3974
  const refreshed = await refreshSecretsCache(DEPLOY_URL2, token, appIdForSecrets, wranglerEnv);
@@ -4644,6 +4658,7 @@ var test_default = defineDeepspaceCommand({
4644
4658
  arg: args.port,
4645
4659
  worktree: () => resolveWorktreePort(appDir)
4646
4660
  });
4661
+ ensureInstallReady(appDir);
4647
4662
  if (suite !== "unit") await ensurePortFree(port, "0.0.0.0");
4648
4663
  let token;
4649
4664
  let ownerId;
@@ -4658,17 +4673,8 @@ var test_default = defineDeepspaceCommand({
4658
4673
  { action: cliAction("deepspace", "auth", "login") }
4659
4674
  );
4660
4675
  }
4661
- ensureInstallReady(appDir);
4662
4676
  let generatedSecretsCache;
4663
- let appIdForSecrets = null;
4664
- try {
4665
- appIdForSecrets = (await ensureAppRegistered(appDir, token, wranglerEnv))?.appId ?? null;
4666
- } catch (registrationError) {
4667
- process.stderr.write(
4668
- `warning: could not register the app (${registrationError instanceof Error ? registrationError.message.split("\n")[0] : String(registrationError)}) \u2014 continuing without app secrets.
4669
- `
4670
- );
4671
- }
4677
+ const appIdForSecrets = await registerForLocalRun(appDir, token, wranglerEnv);
4672
4678
  if (appIdForSecrets) {
4673
4679
  try {
4674
4680
  const refreshed = await refreshSecretsCache(DEPLOY_URL3, token, appIdForSecrets, wranglerEnv);
@@ -4928,7 +4934,8 @@ async function requireConsent(opts) {
4928
4934
 
4929
4935
  // src/cli/commands/test-accounts.ts
4930
4936
  function testAccountFailure(err, fallbackCode) {
4931
- const message = err instanceof Error ? err.message : String(err);
4937
+ const raw = err instanceof Error ? err.message : String(err);
4938
+ const message = raw.replace(/\.\s*$/, "");
4932
4939
  const code = err instanceof TestAccountServiceError ? err.code : void 0;
4933
4940
  if (code === "test_account_cap") {
4934
4941
  return new Refusal(
@@ -4948,7 +4955,7 @@ function testAccountFailure(err, fallbackCode) {
4948
4955
  "not_authenticated"
4949
4956
  );
4950
4957
  }
4951
- return new Refusal(`Failed: ${message}`, code ?? fallbackCode);
4958
+ return new Refusal(`Failed: ${raw}`, code ?? fallbackCode);
4952
4959
  }
4953
4960
  var create = defineDeepspaceCommand({
4954
4961
  meta: {
@@ -5291,7 +5298,7 @@ var recover = defineDeepspaceCommand({
5291
5298
  targets = remote.filter((account) => !known.has(account.id));
5292
5299
  if (targets.length === 0) {
5293
5300
  if (!args.json) console.log("Every pool account already has a local credential.");
5294
- return { data: { recovered: [], alreadyLocal: remote.length } };
5301
+ return { data: { recovered: [], alreadyLocal: remote.length, savedTo: TEST_ACCOUNTS_PATH } };
5295
5302
  }
5296
5303
  } else {
5297
5304
  const match = args.id ? remote.find((account) => account.id === args.id) : remote.find((account) => account.email === args.email);
@@ -5342,7 +5349,7 @@ Stored in ${TEST_ACCOUNTS_PATH}. ${rotatedCount} account(s) had no stored creden
5342
5349
  Stored in ${TEST_ACCOUNTS_PATH}. Passwords were retrieved, not reset \u2014 other machines' credentials still work.`
5343
5350
  );
5344
5351
  }
5345
- return { data: { recovered, requested: targets.length, failures: [] } };
5352
+ return { data: { recovered, requested: targets.length, failures: [], savedTo: TEST_ACCOUNTS_PATH } };
5346
5353
  }
5347
5354
  });
5348
5355
  var test_accounts_default = defineCommand2({
@@ -8055,6 +8062,9 @@ var whoami_default = defineDeepspaceCommand({
8055
8062
  console.log(`Email: ${payload.email ?? "(none)"}`);
8056
8063
  console.log(`Type: ${accountType}`);
8057
8064
  if (payload.iss) console.log(`Issuer: ${payload.iss}`);
8065
+ if (payload.exp) {
8066
+ console.log(`Expires: ${new Date(payload.exp * 1e3).toISOString()} (renews on use)`);
8067
+ }
8058
8068
  console.log(`Dashboard: ${DASHBOARD_URL}`);
8059
8069
  if (isTestAccount) {
8060
8070
  console.log("");
@@ -8140,6 +8150,19 @@ import { setTimeout as delay } from "timers/promises";
8140
8150
 
8141
8151
  // src/shared/log-events.ts
8142
8152
  var LOG_LEVELS = ["debug", "log", "info", "warn", "error"];
8153
+ function logEventText(e) {
8154
+ if (e.eventType === "exception" && e.exception) {
8155
+ const where = e.request ? ` \u2014 ${e.request.method} ${e.request.path}` : "";
8156
+ return `${e.exception.name}: ${e.exception.message}${where}`;
8157
+ }
8158
+ if (e.eventType === "request" && e.request) {
8159
+ const status3 = e.request.status !== void 0 ? ` ${e.request.status}` : "";
8160
+ const outcome = e.outcome && e.outcome !== "ok" ? ` (${e.outcome})` : "";
8161
+ return `${e.request.method} ${e.request.path}${status3}${outcome}`;
8162
+ }
8163
+ return e.message;
8164
+ }
8165
+ var MAX_LOG_TEXT_LENGTH = 8 * 1024;
8143
8166
 
8144
8167
  // src/cli/commands/logs.ts
8145
8168
  var DEPLOY_URL7 = process.env.DEEPSPACE_DEPLOY_URL ?? PLATFORM_URLS.deploy;
@@ -8151,6 +8174,9 @@ var LOG_RETENTION_DAYS = 7;
8151
8174
  function followInitialLimit(limit, maxLimit) {
8152
8175
  return limit ?? maxLimit;
8153
8176
  }
8177
+ function fatalFollowStatus(status3) {
8178
+ return [400, 401, 403, 404].includes(status3);
8179
+ }
8154
8180
  function nextPollSince(cursor, floor, lagMs = FOLLOW_LAG_MS) {
8155
8181
  return Math.max(cursor - lagMs, floor);
8156
8182
  }
@@ -8222,12 +8248,12 @@ function formatTime(ts, now) {
8222
8248
  }
8223
8249
  function formatEvent(e, color, now = Date.now()) {
8224
8250
  const time = paint("2", formatTime(e.timestamp, now), color);
8251
+ const text2 = displayLines(logEventText(e));
8225
8252
  let tag;
8226
8253
  let body;
8227
8254
  if (e.eventType === "exception" && e.exception) {
8228
8255
  tag = paint("31", "ERROR", color);
8229
- const where = e.request ? ` \u2014 ${e.request.method} ${e.request.path}` : "";
8230
- body = displayLines(`${e.exception.name}: ${e.exception.message}${where}`);
8256
+ body = text2;
8231
8257
  if (e.exception.stack) {
8232
8258
  const lines = e.exception.stack.split("\n");
8233
8259
  const firstIsHeader = lines.length > 0 && !/^\s*at\s/.test(lines[0]) && lines[0].includes(e.exception.message);
@@ -8236,17 +8262,14 @@ function formatEvent(e, color, now = Date.now()) {
8236
8262
  }
8237
8263
  } else if (e.eventType === "request" && e.request) {
8238
8264
  tag = paint("36", "REQ ", color);
8239
- const status3 = e.request.status !== void 0 ? ` ${e.request.status}` : "";
8240
- const outcome = e.outcome && e.outcome !== "ok" ? ` (${e.outcome})` : "";
8241
- body = displayLines(`${e.request.method} ${e.request.path}${status3}${outcome}`);
8265
+ body = text2;
8242
8266
  } else {
8243
8267
  const style = LEVEL_STYLE[e.level];
8244
8268
  tag = (e.level.toUpperCase() + " ").slice(0, 5);
8245
8269
  if (style) tag = paint(style, tag, color);
8246
- body = style ? paint(style, displayLines(e.message), color) : displayLines(e.message);
8270
+ body = style ? paint(style, text2, color) : text2;
8247
8271
  }
8248
- const client = e.source === "client" ? paint("35", "CLIENT", color) + " " : "";
8249
- return `${time} ${client}${tag} ${body}`;
8272
+ return `${time} ${tag} ${body}`;
8250
8273
  }
8251
8274
  var sleep3 = (ms, signal) => delay(ms, void 0, { signal });
8252
8275
  var logs_default = defineCommand4({
@@ -8285,7 +8308,7 @@ var logs_default = defineCommand4({
8285
8308
  },
8286
8309
  search: {
8287
8310
  type: "string",
8288
- description: "Only events whose message contains this text",
8311
+ description: "Only events whose rendered text contains this (case-insensitive)",
8289
8312
  required: false
8290
8313
  },
8291
8314
  limit: {
@@ -8353,6 +8376,13 @@ var logs_default = defineCommand4({
8353
8376
  );
8354
8377
  }
8355
8378
  };
8379
+ const noteTruncation = (humanMessage) => {
8380
+ if (args.json) {
8381
+ process.stdout.write(JSON.stringify({ type: "meta", truncated: true }) + "\n");
8382
+ } else {
8383
+ console.error(humanMessage);
8384
+ }
8385
+ };
8356
8386
  const first = await fetchPage(initialSince, args.follow ? followLimit : limit, token);
8357
8387
  if (args.follow && args.json) {
8358
8388
  process.stdout.write(
@@ -8384,16 +8414,9 @@ var logs_default = defineCommand4({
8384
8414
  );
8385
8415
  }
8386
8416
  } else if (first.truncated) {
8387
- if (args.json)
8388
- process.stdout.write(JSON.stringify({ type: "meta", truncated: true }) + "\n");
8389
- else if (args.search)
8390
- console.error(
8391
- `(showing the newest ${first.events.length} matches \u2014 search scans at most the newest 500 level-filtered events per fetch; narrow with --since/--level or raise --limit)`
8392
- );
8393
- else
8394
- console.error(
8395
- `(showing the newest ${first.events.length} events \u2014 narrow with --since/--level)`
8396
- );
8417
+ noteTruncation(
8418
+ args.search ? `(showing the newest ${first.events.length} matches \u2014 search scans at most the newest 500 level-filtered events per fetch; narrow with --since/--level or raise --limit)` : `(showing the newest ${first.events.length} events \u2014 narrow with --since/--level)`
8419
+ );
8397
8420
  }
8398
8421
  return;
8399
8422
  }
@@ -8410,17 +8433,13 @@ var logs_default = defineCommand4({
8410
8433
  let warnedTruncated = false;
8411
8434
  if (first.truncated) {
8412
8435
  warnedTruncated = true;
8413
- if (args.json) {
8414
- process.stdout.write(JSON.stringify({ type: "meta", truncated: true }) + "\n");
8415
- } else {
8416
- console.error(
8417
- paint(
8418
- "33",
8419
- args.search ? `(search scanned only the newest ${MAX_LIMIT} level-filtered events in the initial ${windowLabel} window \u2014 older matches may be omitted; narrow with --since/--level)` : `(more than ${followLimit} events in the initial ${windowLabel} window \u2014 some older events not shown; narrow with --since/--level)`,
8420
- stderrColor()
8421
- )
8422
- );
8423
- }
8436
+ noteTruncation(
8437
+ paint(
8438
+ "33",
8439
+ args.search ? `(search scanned only the newest ${MAX_LIMIT} level-filtered events in the initial ${windowLabel} window \u2014 older matches may be omitted; narrow with --since/--level)` : `(more than ${followLimit} events in the initial ${windowLabel} window \u2014 some older events not shown; narrow with --since/--level)`,
8440
+ stderrColor()
8441
+ )
8442
+ );
8424
8443
  }
8425
8444
  for (; ; ) {
8426
8445
  try {
@@ -8440,7 +8459,7 @@ var logs_default = defineCommand4({
8440
8459
  );
8441
8460
  } catch (err) {
8442
8461
  if (tail.signal.aborted) return;
8443
- if (err instanceof ApiError && [401, 403, 404].includes(err.status)) throw err;
8462
+ if (err instanceof ApiError && fatalFollowStatus(err.status)) throw err;
8444
8463
  backoff = Math.min(backoff ? backoff * 2 : MIN_POLL_MS, 3e4);
8445
8464
  const msg = err instanceof Error ? err.message : String(err);
8446
8465
  console.error(
@@ -8455,17 +8474,13 @@ var logs_default = defineCommand4({
8455
8474
  const realDrop = fresh.length >= followLimit || Boolean(args.search && page.truncated);
8456
8475
  if (realDrop && !warnedTruncated) {
8457
8476
  warnedTruncated = true;
8458
- if (args.json) {
8459
- process.stdout.write(JSON.stringify({ type: "meta", truncated: true }) + "\n");
8460
- } else {
8461
- console.error(
8462
- paint(
8463
- "33",
8464
- args.search ? `(search scanned only the newest ${MAX_LIMIT} level-filtered events this poll \u2014 older matches may be omitted; narrow with --level)` : `(burst exceeded ${followLimit} events/poll \u2014 some may be dropped; narrow with --level)`,
8465
- stderrColor()
8466
- )
8467
- );
8468
- }
8477
+ noteTruncation(
8478
+ paint(
8479
+ "33",
8480
+ args.search ? `(search scanned only the newest ${MAX_LIMIT} level-filtered events this poll \u2014 older matches may be omitted; narrow with --level)` : `(burst exceeded ${followLimit} events/poll \u2014 some may be dropped; narrow with --level)`,
8481
+ stderrColor()
8482
+ )
8483
+ );
8469
8484
  } else if (!realDrop) {
8470
8485
  warnedTruncated = false;
8471
8486
  }
@@ -8537,7 +8552,7 @@ function renderSummary(summary) {
8537
8552
  var usage_default = defineDeepspaceCommand({
8538
8553
  meta: {
8539
8554
  name: "usage",
8540
- description: "Show account-wide credits and integration spend (all apps)"
8555
+ description: "Show account-wide credits and integration spend (all apps). Storage is per app: `deepspace app files list`"
8541
8556
  },
8542
8557
  async run({ args }) {
8543
8558
  const token = await ensureToken();
@@ -11289,7 +11304,7 @@ function httpRefusal(response, tokens) {
11289
11304
  }
11290
11305
  if (response.status === 404 && !server) {
11291
11306
  return new Refusal(
11292
- "This app does not expose the requested agent endpoint.",
11307
+ "No agent endpoint answered for this app. Either the app name/id is wrong (`deepspace app list` shows yours), or the app does not register assistant tools \u2014 its worker needs `registerAgent(app, { tools, inApp: false })` deployed.",
11293
11308
  "agent_endpoint_not_found"
11294
11309
  );
11295
11310
  }
@@ -12252,6 +12267,9 @@ var init_default = defineDeepspaceCommand({
12252
12267
  console.log(
12253
12268
  `Registered on ${DEEPSPACE_ENV} as a NEW app under ${accountLabel(token)}; the original is untouched.`
12254
12269
  );
12270
+ console.log(
12271
+ "Note: the fork keeps the wrangler `name` \u2014 its first deploy targets the SAME subdomain as the original. For a separate URL, change `name` in wrangler.toml (and APP_NAME) before deploying."
12272
+ );
12255
12273
  } else {
12256
12274
  console.log(`Registered ${appId}${envSuffix} on ${DEEPSPACE_ENV} to ${accountLabel(token)}${commitNote}`);
12257
12275
  if (replacedMalformed !== null) {
@@ -12403,6 +12421,7 @@ var status_default = defineCommand12({
12403
12421
  json.sessionError = sessionError("Not logged in. Run `deepspace auth login` first.");
12404
12422
  } else {
12405
12423
  let who = null;
12424
+ let undecodableToken = false;
12406
12425
  try {
12407
12426
  const payload = decodeJwtPayload(
12408
12427
  readFileSync23(TOKEN_PATH, "utf-8").trim()
@@ -12410,13 +12429,39 @@ var status_default = defineCommand12({
12410
12429
  if (payload.email) who = payload.email;
12411
12430
  userId = payload.sub ?? null;
12412
12431
  } catch {
12432
+ undecodableToken = existsSync26(TOKEN_PATH);
12433
+ }
12434
+ let sessionLineEmitted = false;
12435
+ if (undecodableToken) {
12436
+ try {
12437
+ const healed = await ensureToken();
12438
+ const payload = decodeJwtPayload(healed);
12439
+ if (payload.email) who = payload.email;
12440
+ userId = payload.sub ?? null;
12441
+ } catch (err) {
12442
+ sessionLineEmitted = true;
12443
+ const offline = err instanceof TypeError || errorCode(err) === "network_error";
12444
+ if (offline) {
12445
+ lines.push(["Session", "logged in \xB7 stored token unreadable, could not verify offline"]);
12446
+ json.loggedIn = true;
12447
+ } else {
12448
+ lines.push(["Session", "stored credentials unusable \u2014 run `deepspace auth login`"]);
12449
+ facts.loggedIn = false;
12450
+ json.loggedIn = false;
12451
+ json.sessionError = sessionError(
12452
+ "Stored credentials are unusable. Run `deepspace auth login`."
12453
+ );
12454
+ }
12455
+ }
12456
+ }
12457
+ if (!sessionLineEmitted) {
12458
+ lines.push([
12459
+ "Session",
12460
+ `${who ?? "logged in"} \xB7 renews on use (re-login only after 30 idle days)`
12461
+ ]);
12462
+ json.loggedIn = true;
12463
+ if (who) json.user = who;
12413
12464
  }
12414
- lines.push([
12415
- "Session",
12416
- `${who ?? "logged in"} \xB7 renews on use (re-login only after 30 idle days)`
12417
- ]);
12418
- json.loggedIn = true;
12419
- if (who) json.user = who;
12420
12465
  }
12421
12466
  const appDir = findAppDir();
12422
12467
  if (!appDir) {
@@ -12551,9 +12596,10 @@ var status_default = defineCommand12({
12551
12596
  ]);
12552
12597
  json.source = { ...source, revision: sourceResult.value.revision };
12553
12598
  } else {
12599
+ const observed = inferredGithub ? observedGitHubRepository(appDir) : null;
12554
12600
  lines.push([
12555
12601
  "Source",
12556
- `unclaimed \xB7 ${inferredGithub ? "first release claims GitHub (from this checkout\u2019s remote), permanently" : "first deploy or push claims DeepSpace, permanently"}`
12602
+ `unclaimed \xB7 ${inferredGithub ? `first release claims GitHub${observed ? ` (${observed})` : ""} from this checkout\u2019s remote, permanently` : "first deploy or push claims DeepSpace, permanently"}`
12557
12603
  ]);
12558
12604
  json.source = null;
12559
12605
  json.sourceInference = inferredGithub ? "github" : "deepspace";
@@ -14175,9 +14221,9 @@ var newWorkspaceCommand = defineDeepspaceCommand({
14175
14221
  },
14176
14222
  async run({ args }) {
14177
14223
  const task = typeof args.task === "string" ? args.task.trim() : "";
14178
- if (!task) {
14224
+ if (!task || task.startsWith("-")) {
14179
14225
  throw new Refusal(
14180
- 'A workspace needs a task \u2014 pass -t "<what this workspace is for>" (it is shown to every collaborator and agent).',
14226
+ 'A workspace needs a task \u2014 pass -t "<what this workspace is for>" (quote it, and put flags like --json after it; it is shown to every collaborator and agent).',
14181
14227
  "invalid_task"
14182
14228
  );
14183
14229
  }
@@ -15528,7 +15574,7 @@ function formatEvent2(e, lands, actors) {
15528
15574
  detail = `"${String(s.task ?? "")}" from ${short(s.baseOid)}`;
15529
15575
  break;
15530
15576
  case "workspace.synced":
15531
- detail = `${e.subjectId ? `${e.subjectId} ` : ""}\u2192 ${short(s.headOid)}`;
15577
+ detail = `${e.subjectId ? `${e.subjectId} ` : ""}${typeof s.task === "string" && s.task ? `"${s.task}" ` : ""}\u2192 ${short(s.headOid)}`;
15532
15578
  break;
15533
15579
  case "workspace.landed":
15534
15580
  detail = `"${String(s.task ?? "")}" \u2192 ${short(s.landedOid)} on ${String(s.into ?? "trunk")}`;
@@ -15799,6 +15845,7 @@ function reportSource(appId, state, json) {
15799
15845
  );
15800
15846
  }
15801
15847
  console.log(`Revision: ${state.revision}`);
15848
+ console.log(`Registered: ${state.registered ? "yes" : "no"}`);
15802
15849
  }
15803
15850
 
15804
15851
  // src/cli/commands/update.ts
@@ -15809,7 +15856,7 @@ import { join as join28, resolve as resolve22 } from "path";
15809
15856
  // package.json
15810
15857
  var package_default = {
15811
15858
  name: "deepspace",
15812
- version: "0.28.1",
15859
+ version: "0.29.0",
15813
15860
  engines: {
15814
15861
  node: ">=22.15.0 <23 || >=24 <25 || >=26 <27"
15815
15862
  },