@workser/cli 0.6.8 → 0.6.9

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/index.js CHANGED
@@ -4636,6 +4636,47 @@ workser audio understand "transcribe this" --file ./voicemail.m4a -t transcribe
4636
4636
  - **This is billed to the project's organization**, same as image generation \u2014 it's
4637
4637
  a real provider call, not free introspection. Don't loop it over every file in a
4638
4638
  folder "just in case"; use it when you actually need to know what's in one.
4639
+ `
4640
+ },
4641
+ {
4642
+ topic: "key",
4643
+ title: "Managed keys \u2014 list and rotate this app's Workser-issued credentials",
4644
+ summary: "See this app's AI Gateway and auth keys (redacted), and rotate one without opening Orbit.",
4645
+ commands: ["key"],
4646
+ source: "skills/workser/reference/key.md",
4647
+ body: `# Managed keys \u2014 list and rotate this app's Workser-issued credentials
4648
+
4649
+ \`\`\`
4650
+ workser key list [--app <webAppId>]
4651
+ workser key rotate <key> [--app <webAppId>] [--env production|preview]
4652
+ \`\`\`
4653
+
4654
+ App-scoped, not project-scoped: run from the app's own folder and \`--app\` is
4655
+ picked up automatically; from anywhere else, pass \`--app <webAppId>\` \u2014 a
4656
+ mistake here is the wrong app's key, so there is no "primary app" default the
4657
+ way \`env\` has one.
4658
+
4659
+ ## What's rotatable
4660
+
4661
+ Only credentials with a real rotation handler:
4662
+
4663
+ - \`AI_GATEWAY_API_KEY\` \u2014 the deployed agent's key into the Workser AI
4664
+ Gateway. Split by environment (\`--env production\` or \`--env preview\`
4665
+ required), so rotating one never touches the other.
4666
+ - \`BETTER_AUTH_SECRET\` \u2014 a single value, no \`--env\` needed.
4667
+
4668
+ Every other Workser-managed value (\`DATABASE_URL\`, the internal service
4669
+ keys) has no rotation handler yet \u2014 each belongs to a different subsystem
4670
+ with its own cutover semantics, and \`key rotate\` refuses rather than fake
4671
+ one.
4672
+
4673
+ ## After rotating
4674
+
4675
+ The old value stops authorizing immediately, server-side. An already-running
4676
+ deployment keeps using whatever it was built with until it's redeployed \u2014
4677
+ run \`workser deploy\` (\`--prod\` for the production key) to pick up the new
4678
+ value. \`key rotate\` prints the new secret exactly once; it is never shown
4679
+ again or stored anywhere in the clear.
4639
4680
  `
4640
4681
  },
4641
4682
  {
@@ -4865,6 +4906,17 @@ workser doc create "Checkout \u2014 implementation plan" --markdown "$(cat plan.
4865
4906
  workser decision create "Carts live server-side" --context "\u2026" --decision "\u2026" --json
4866
4907
  \`\`\`
4867
4908
 
4909
+ **A wrong row is edited, not replaced.** If a subtask's title, teammate, note or
4910
+ scope is wrong after you created it, fix that same row:
4911
+
4912
+ \`\`\`bash
4913
+ workser task subtask update <id> --title "\u2026" --role api --note "\u2026" --scope "src/api"
4914
+ \`\`\`
4915
+
4916
+ Never tell the user a subtask is locked, and never file a second one alongside
4917
+ the wrong one \u2014 a plan with a duplicate phase in it is a plan nobody can read
4918
+ the progress of.
4919
+
4868
4920
  **Don't pass \`--work-item\` for a multi-phase plan.** A linked document renders on
4869
4921
  its card and is *hidden* from the Docs panel; a plan spanning three phases
4870
4922
  belongs to the project, not to phase 1.
@@ -5511,6 +5563,10 @@ function requireProject(ctx) {
5511
5563
  }
5512
5564
  return ctx.projectId;
5513
5565
  }
5566
+ function appTarget(ctx, explicit) {
5567
+ const said = typeof explicit === "string" ? explicit.trim() : "";
5568
+ return said || ctx.appId || void 0;
5569
+ }
5514
5570
 
5515
5571
  // src/run.ts
5516
5572
  function action(fn) {
@@ -6791,8 +6847,71 @@ function formatEnvValue(value) {
6791
6847
  return /[\s"'#]/.test(value) ? JSON.stringify(value) : value;
6792
6848
  }
6793
6849
 
6794
- // src/commands/deploy.ts
6850
+ // src/commands/key.ts
6795
6851
  var import_picocolors10 = __toESM(require_picocolors(), 1);
6852
+ function requireApp(ctx, explicit) {
6853
+ const appId = appTarget(ctx, explicit);
6854
+ if (!appId) {
6855
+ throw new WorkserError(
6856
+ "No app to target.\n\n \u2022 Run this from the app's own folder (its ID is picked up automatically), or\n \u2022 pass --app <webAppId> \u2014 `workser project show` lists an app's ID.",
6857
+ { code: "no_app" }
6858
+ );
6859
+ }
6860
+ return appId;
6861
+ }
6862
+ function registerKey(program3) {
6863
+ const key = program3.command("key").description("Manage this app's Workser-issued credentials (AI Gateway, auth secret)");
6864
+ key.command("list").description("List this app's managed keys (redacted \u2014 never the secret)").option("--app <webAppId>", "Which app (default: the one this folder is linked to)").action(
6865
+ action(async ({ ctx, opts }) => {
6866
+ const appId = requireApp(ctx, opts.app);
6867
+ const items = await api(ctx, `/v1/apps/${appId}/keys`);
6868
+ ok(items, () => {
6869
+ if (!items?.length) {
6870
+ return line(import_picocolors10.default.dim("No managed keys yet \u2014 they're created the first time this app deploys."));
6871
+ }
6872
+ for (const item of items) {
6873
+ const lastUsed = item.last_used_at ? `last used ${item.last_used_at}` : "never used yet";
6874
+ line(`${import_picocolors10.default.bold(item.environment)} ${item.prefix}\u2026 ${import_picocolors10.default.dim(`(${lastUsed})`)}`);
6875
+ }
6876
+ });
6877
+ })
6878
+ );
6879
+ key.command("rotate <key>").description("Rotate a managed key (AI_GATEWAY_API_KEY, BETTER_AUTH_SECRET)").option("--app <webAppId>", "Which app (default: the one this folder is linked to)").option("--env <environment>", "production or preview \u2014 required for AI_GATEWAY_API_KEY").action(
6880
+ action(async ({ ctx, args, opts }) => {
6881
+ const appId = requireApp(ctx, opts.app);
6882
+ const keyName = args[0];
6883
+ const environment = typeof opts.env === "string" ? opts.env : void 0;
6884
+ if (environment && environment !== "production" && environment !== "preview") {
6885
+ throw new WorkserError(
6886
+ `--env must be "production" or "preview", got "${environment}".`,
6887
+ { code: "bad_input" }
6888
+ );
6889
+ }
6890
+ const res = await api(
6891
+ ctx,
6892
+ `/v1/apps/${appId}/keys/${encodeURIComponent(keyName)}/rotate`,
6893
+ { body: { environment } }
6894
+ );
6895
+ ok(res, () => {
6896
+ success(`Rotated ${import_picocolors10.default.bold(keyName)}${res?.environment ? ` (${res.environment})` : ""}.`);
6897
+ if (res?.key) {
6898
+ line("");
6899
+ line(import_picocolors10.default.bold("New value \u2014 shown once, not stored anywhere in the clear:"));
6900
+ line(import_picocolors10.default.yellow(res.key));
6901
+ }
6902
+ line("");
6903
+ line(
6904
+ import_picocolors10.default.dim(
6905
+ "The old value stopped working immediately. If this app is already deployed, redeploy so it picks up the new one: workser deploy" + (res?.environment === "production" ? " --prod" : "")
6906
+ )
6907
+ );
6908
+ });
6909
+ })
6910
+ );
6911
+ }
6912
+
6913
+ // src/commands/deploy.ts
6914
+ var import_picocolors11 = __toESM(require_picocolors(), 1);
6796
6915
  var TERMINAL = /* @__PURE__ */ new Set(["ready", "live", "success", "error", "failed", "canceled"]);
6797
6916
  function registerDeploy(program3) {
6798
6917
  const deploy = program3.command("deploy").description("Deploy the current project to Workser (git \u2192 Vercel) and return a live URL").option("--prod", "deploy to production (same as --env production)", false).option(
@@ -6843,7 +6962,7 @@ async function watchDeploy(ctx, id) {
6843
6962
  for (; ; ) {
6844
6963
  const dep = await api(ctx, `/v1/deployments/${encodeURIComponent(id)}`);
6845
6964
  if (!isJson() && dep.status !== last) {
6846
- line(` ${colorStatus(dep.status)}${dep.url ? " " + import_picocolors10.default.cyan(dep.url) : ""}`);
6965
+ line(` ${colorStatus(dep.status)}${dep.url ? " " + import_picocolors11.default.cyan(dep.url) : ""}`);
6847
6966
  last = dep.status;
6848
6967
  }
6849
6968
  if (TERMINAL.has(String(dep.status).toLowerCase())) return dep;
@@ -6853,12 +6972,12 @@ async function watchDeploy(ctx, id) {
6853
6972
  function printDeploy(dep) {
6854
6973
  if (!dep) return;
6855
6974
  const ready = ["ready", "live", "success"].includes(String(dep.status).toLowerCase());
6856
- if (ready && dep.url) success(`Live at ${import_picocolors10.default.cyan(dep.url)}`);
6857
- else line(`deploy ${colorStatus(dep.status)} ${import_picocolors10.default.dim(`(${dep.id ?? "?"})`)}${dep.url ? " " + dep.url : ""}`);
6975
+ if (ready && dep.url) success(`Live at ${import_picocolors11.default.cyan(dep.url)}`);
6976
+ else line(`deploy ${colorStatus(dep.status)} ${import_picocolors11.default.dim(`(${dep.id ?? "?"})`)}${dep.url ? " " + dep.url : ""}`);
6858
6977
  }
6859
6978
 
6860
6979
  // src/commands/versions.ts
6861
- var import_picocolors11 = __toESM(require_picocolors(), 1);
6980
+ var import_picocolors12 = __toESM(require_picocolors(), 1);
6862
6981
  function registerVersions(program3) {
6863
6982
  program3.command("versions").description("List the Workser-managed versions of the project (deploy history)").option("--app <webAppId>", "which app (defaults to the primary app)").option(
6864
6983
  "--env <environment>",
@@ -6877,7 +6996,7 @@ function registerVersions(program3) {
6877
6996
  }
6878
6997
  });
6879
6998
  ok(items, () => {
6880
- if (!items?.length) return line(import_picocolors11.default.dim("No versions yet. `workser deploy` to create one."));
6999
+ if (!items?.length) return line(import_picocolors12.default.dim("No versions yet. `workser deploy` to create one."));
6881
7000
  for (const v of items) {
6882
7001
  line(formatVersion(v));
6883
7002
  }
@@ -6886,11 +7005,11 @@ function registerVersions(program3) {
6886
7005
  );
6887
7006
  }
6888
7007
  function formatVersion(v) {
6889
- const ref = import_picocolors11.default.yellow(shortRef(v.ref));
6890
- const when = import_picocolors11.default.dim(formatTime(v.createdAt));
6891
- const msg = (v.message ?? "").trim() || import_picocolors11.default.dim("(no message)");
6892
- const badge = v.deployed ? " " + import_picocolors11.default.green(v.deployedEnvironment ? `live in ${v.deployedEnvironment}` : "deployed") : "";
6893
- const url = v.url ? " " + import_picocolors11.default.cyan(v.url) : "";
7008
+ const ref = import_picocolors12.default.yellow(shortRef(v.ref));
7009
+ const when = import_picocolors12.default.dim(formatTime(v.createdAt));
7010
+ const msg = (v.message ?? "").trim() || import_picocolors12.default.dim("(no message)");
7011
+ const badge = v.deployed ? " " + import_picocolors12.default.green(v.deployedEnvironment ? `live in ${v.deployedEnvironment}` : "deployed") : "";
7012
+ const url = v.url ? " " + import_picocolors12.default.cyan(v.url) : "";
6894
7013
  return `${ref} ${when} ${msg}${badge}${url}`;
6895
7014
  }
6896
7015
  function shortRef(ref) {
@@ -6904,7 +7023,7 @@ function formatTime(t) {
6904
7023
  }
6905
7024
 
6906
7025
  // src/commands/logs.ts
6907
- var import_picocolors12 = __toESM(require_picocolors(), 1);
7026
+ var import_picocolors13 = __toESM(require_picocolors(), 1);
6908
7027
  function registerLogs(program3) {
6909
7028
  program3.command("logs").description("Show the build logs of the latest deployment").option("-n, --lines <n>", "number of lines", "100").option("-f, --follow", "keep streaming new logs", false).option("--app <webAppId>", "which app (defaults to the primary app)").option("--env <environment>", "preview or production (default: whichever deployed last)").action(
6910
7029
  action(async ({ ctx, opts }) => {
@@ -6938,10 +7057,10 @@ function registerLogs(program3) {
6938
7057
  function print(res) {
6939
7058
  const entries = res?.entries ?? [];
6940
7059
  for (const e of entries) line(formatLog(e));
6941
- if (!entries.length && res?.note) line(import_picocolors12.default.dim(res.note));
7060
+ if (!entries.length && res?.note) line(import_picocolors13.default.dim(res.note));
6942
7061
  if (entries.length && res?.deploymentId) {
6943
7062
  const where = res.environment ? ` (${res.environment})` : "";
6944
- line(import_picocolors12.default.dim(`\u2014 build ${res.deploymentId}${where}`));
7063
+ line(import_picocolors13.default.dim(`\u2014 build ${res.deploymentId}${where}`));
6945
7064
  }
6946
7065
  }
6947
7066
  function formatLog(e) {
@@ -6950,7 +7069,7 @@ function formatLog(e) {
6950
7069
  }
6951
7070
 
6952
7071
  // src/commands/domain.ts
6953
- var import_picocolors13 = __toESM(require_picocolors(), 1);
7072
+ var import_picocolors14 = __toESM(require_picocolors(), 1);
6954
7073
 
6955
7074
  // src/reserved-domains.ts
6956
7075
  var RESERVED_APEX = [
@@ -7013,9 +7132,9 @@ function registerDomain(program3) {
7013
7132
  { method: "POST", body: { domain: host } }
7014
7133
  );
7015
7134
  ok(result, () => {
7016
- line(`${import_picocolors13.default.green("Attached")} ${host}`);
7135
+ line(`${import_picocolors14.default.green("Attached")} ${host}`);
7017
7136
  line(
7018
- import_picocolors13.default.dim(
7137
+ import_picocolors14.default.dim(
7019
7138
  "It goes live once DNS points at us. Run `workser domain list` to see its status."
7020
7139
  )
7021
7140
  );
@@ -7031,7 +7150,7 @@ function registerDomain(program3) {
7031
7150
  opts.app ? `/v1/projects/${projectId}/web-apps/${opts.app}/domains/${encodeURIComponent(host)}` : `/v1/projects/${projectId}/domains/${encodeURIComponent(host)}`,
7032
7151
  { method: "DELETE" }
7033
7152
  );
7034
- ok(result, () => line(`${import_picocolors13.default.yellow("Detached")} ${host}`));
7153
+ ok(result, () => line(`${import_picocolors14.default.yellow("Detached")} ${host}`));
7035
7154
  })
7036
7155
  );
7037
7156
  domain.command("list").description("List domains attached to the project").action(
@@ -7039,8 +7158,8 @@ function registerDomain(program3) {
7039
7158
  const projectId = requireProject(ctx);
7040
7159
  const items = await api(ctx, `/v1/projects/${projectId}/domains`);
7041
7160
  ok(items, () => {
7042
- if (!items?.length) return line(import_picocolors13.default.dim("No custom domains."));
7043
- for (const d of items) line(`${d.domain}${import_picocolors13.default.dim(" " + (d.status ?? ""))}`);
7161
+ if (!items?.length) return line(import_picocolors14.default.dim("No custom domains."));
7162
+ for (const d of items) line(`${d.domain}${import_picocolors14.default.dim(" " + (d.status ?? ""))}`);
7044
7163
  });
7045
7164
  })
7046
7165
  );
@@ -7072,7 +7191,7 @@ function openUrl(url) {
7072
7191
  }
7073
7192
 
7074
7193
  // src/commands/doctor.ts
7075
- var import_picocolors14 = __toESM(require_picocolors(), 1);
7194
+ var import_picocolors15 = __toESM(require_picocolors(), 1);
7076
7195
  import { spawnSync } from "child_process";
7077
7196
  function registerDoctor(program3) {
7078
7197
  program3.command("doctor").description("Print the resolved endpoint, mode, token presence (masked), and current project").action(
@@ -7106,29 +7225,29 @@ function registerDoctor(program3) {
7106
7225
  workspace: session.workspaceName ?? null
7107
7226
  };
7108
7227
  ok(report, () => {
7109
- line(import_picocolors14.default.bold("workser doctor"));
7110
- line(` endpoint: ${ctx.endpoint} ${import_picocolors14.default.dim(`(${endpointSource})`)}`);
7228
+ line(import_picocolors15.default.bold("workser doctor"));
7229
+ line(` endpoint: ${ctx.endpoint} ${import_picocolors15.default.dim(`(${endpointSource})`)}`);
7111
7230
  line(
7112
- ` env: ${env === "prod" ? import_picocolors14.default.yellow(env) : env}` + import_picocolors14.default.dim(process.env.WORKSER_ENV ? " ($WORKSER_ENV)" : " (default)")
7231
+ ` env: ${env === "prod" ? import_picocolors15.default.yellow(env) : env}` + import_picocolors15.default.dim(process.env.WORKSER_ENV ? " ($WORKSER_ENV)" : " (default)")
7113
7232
  );
7114
7233
  line(` mode: ${ctx.mode}`);
7115
7234
  line(
7116
- ` token: ${ctx.token ? `${maskToken(ctx.token)} ${import_picocolors14.default.dim(`(${tokenSource})`)}` : import_picocolors14.default.yellow("none \u2014 run `workser login`")}`
7235
+ ` token: ${ctx.token ? `${maskToken(ctx.token)} ${import_picocolors15.default.dim(`(${tokenSource})`)}` : import_picocolors15.default.yellow("none \u2014 run `workser login`")}`
7117
7236
  );
7118
7237
  line(
7119
- ` project: ${ctx.projectId ?? import_picocolors14.default.dim("none")}` + (link?.name ? ` ${import_picocolors14.default.dim(`(${link.name})`)}` : "") + (projectSource ? import_picocolors14.default.dim(` [${projectSource}]`) : "")
7238
+ ` project: ${ctx.projectId ?? import_picocolors15.default.dim("none")}` + (link?.name ? ` ${import_picocolors15.default.dim(`(${link.name})`)}` : "") + (projectSource ? import_picocolors15.default.dim(` [${projectSource}]`) : "")
7120
7239
  );
7121
7240
  line(` cwd: ${ctx.cwd}`);
7122
- line(` git: ${git2 ?? import_picocolors14.default.dim("not on this shell's PATH")}`);
7241
+ line(` git: ${git2 ?? import_picocolors15.default.dim("not on this shell's PATH")}`);
7123
7242
  if (!git2) {
7124
7243
  line("");
7125
7244
  line(
7126
- import_picocolors14.default.dim(
7245
+ import_picocolors15.default.dim(
7127
7246
  " Workser brings its own git, so syncing and publishing still work."
7128
7247
  )
7129
7248
  );
7130
7249
  line(
7131
- import_picocolors14.default.dim(
7250
+ import_picocolors15.default.dim(
7132
7251
  ` Only needed if you want to run git yourself here. ${GIT_INSTALL_HINT}`
7133
7252
  )
7134
7253
  );
@@ -7136,16 +7255,16 @@ function registerDoctor(program3) {
7136
7255
  if (envIgnored) {
7137
7256
  line("");
7138
7257
  line(
7139
- import_picocolors14.default.yellow(
7258
+ import_picocolors15.default.yellow(
7140
7259
  ` WORKSER_ENV=${env} is not in effect \u2014 ${endpointSource} wins.`
7141
7260
  )
7142
7261
  );
7143
7262
  line(
7144
- import_picocolors14.default.dim(
7263
+ import_picocolors15.default.dim(
7145
7264
  ` Re-run \`workser login\` to switch (the saved token is tied to ${ctx.endpoint}),`
7146
7265
  )
7147
7266
  );
7148
- line(import_picocolors14.default.dim(` or pass --endpoint ${ENV_BASE_URLS[env]}.`));
7267
+ line(import_picocolors15.default.dim(` or pass --endpoint ${ENV_BASE_URLS[env]}.`));
7149
7268
  }
7150
7269
  });
7151
7270
  })
@@ -7175,7 +7294,32 @@ function maskToken(token) {
7175
7294
  }
7176
7295
 
7177
7296
  // src/commands/agent.ts
7178
- var import_picocolors15 = __toESM(require_picocolors(), 1);
7297
+ var import_picocolors16 = __toESM(require_picocolors(), 1);
7298
+
7299
+ // src/model-policy.ts
7300
+ var DELEGATION_BLOCKED_MODELS = [
7301
+ {
7302
+ match: "fable",
7303
+ label: "Claude Fable 5",
7304
+ reason: "it is the most expensive model available and no delegated run is worth it \u2014 ask the owner if you think this one is"
7305
+ }
7306
+ ];
7307
+ function blockedDelegationModel(model) {
7308
+ const value = (model ?? "").trim().toLowerCase();
7309
+ if (!value) return null;
7310
+ return DELEGATION_BLOCKED_MODELS.find((entry) => value.includes(entry.match)) ?? null;
7311
+ }
7312
+ function assertDelegatableModel(flag, model) {
7313
+ const blocked = blockedDelegationModel(model);
7314
+ if (!blocked || !model) return;
7315
+ throw new WorkserError(
7316
+ `${flag} "${model}" can't be chosen for a delegated run: ${blocked.reason}.
7317
+ Pick another model, or leave ${flag} off to use the agent's own default.`,
7318
+ { code: "bad_request" }
7319
+ );
7320
+ }
7321
+
7322
+ // src/commands/agent.ts
7179
7323
  var SPAWNABLE_AGENTS = ["claude_code", "codex", "kimi", "opencode", "grok"];
7180
7324
  function registerAgent(program3) {
7181
7325
  const agent = program3.command("agent").description("Delegate focused subtasks to your configured agent roles (each runs isolated)");
@@ -7183,20 +7327,20 @@ function registerAgent(program3) {
7183
7327
  action(async ({ ctx }) => {
7184
7328
  const cfg = await api(ctx, "/v1/agents");
7185
7329
  ok(cfg, () => {
7186
- line(import_picocolors15.default.bold("main agent:") + " " + (cfg?.mainAgent ?? import_picocolors15.default.dim("none")));
7187
- line(import_picocolors15.default.bold("backup agent:") + " " + (cfg?.backupAgent ?? import_picocolors15.default.dim("none")));
7330
+ line(import_picocolors16.default.bold("main agent:") + " " + (cfg?.mainAgent ?? import_picocolors16.default.dim("none")));
7331
+ line(import_picocolors16.default.bold("backup agent:") + " " + (cfg?.backupAgent ?? import_picocolors16.default.dim("none")));
7188
7332
  if (cfg?.effectiveMainAgent && cfg.effectiveMainAgent !== cfg.mainAgent) {
7189
7333
  line(
7190
- import_picocolors15.default.yellow(
7334
+ import_picocolors16.default.yellow(
7191
7335
  ` \u2937 failover active: runs use ${cfg.effectiveMainAgent} (main not available)`
7192
7336
  )
7193
7337
  );
7194
7338
  }
7195
7339
  const roles = cfg?.roles ?? [];
7196
7340
  if (!roles.length) {
7197
- line(import_picocolors15.default.dim("No subagents configured. Add them in the Workser Orbit Agents screen."));
7341
+ line(import_picocolors16.default.dim("No subagents configured. Add them in the Workser Orbit Agents screen."));
7198
7342
  } else {
7199
- line(import_picocolors15.default.bold("subagents:"));
7343
+ line(import_picocolors16.default.bold("subagents:"));
7200
7344
  for (const r of roles) line(" " + formatRole(r));
7201
7345
  }
7202
7346
  const detected = cfg?.detected ?? [];
@@ -7204,7 +7348,7 @@ function registerAgent(program3) {
7204
7348
  (d) => d?.installed && d?.authed !== false
7205
7349
  );
7206
7350
  line(
7207
- import_picocolors15.default.bold("spawnable (workser agent spawn <agent>):") + " " + (spawnable.length ? spawnable.map((d) => toContractId(d.id)).join(", ") : import_picocolors15.default.dim("none connected"))
7351
+ import_picocolors16.default.bold("spawnable (workser agent spawn <agent>):") + " " + (spawnable.length ? spawnable.map((d) => toContractId(d.id)).join(", ") : import_picocolors16.default.dim("none connected"))
7208
7352
  );
7209
7353
  });
7210
7354
  })
@@ -7218,8 +7362,8 @@ function registerAgent(program3) {
7218
7362
  backupAgent: cfg?.backupAgent ?? null
7219
7363
  },
7220
7364
  () => {
7221
- line(import_picocolors15.default.bold("main agent:") + " " + (cfg?.mainAgent ?? import_picocolors15.default.dim("none")));
7222
- line(import_picocolors15.default.bold("backup agent:") + " " + (cfg?.backupAgent ?? import_picocolors15.default.dim("none")));
7365
+ line(import_picocolors16.default.bold("main agent:") + " " + (cfg?.mainAgent ?? import_picocolors16.default.dim("none")));
7366
+ line(import_picocolors16.default.bold("backup agent:") + " " + (cfg?.backupAgent ?? import_picocolors16.default.dim("none")));
7223
7367
  }
7224
7368
  );
7225
7369
  })
@@ -7251,6 +7395,7 @@ function registerAgent(program3) {
7251
7395
  action(async ({ ctx, args, opts }) => {
7252
7396
  const spawnAgent = args[0];
7253
7397
  const task = args[1].join(" ");
7398
+ assertDelegatableModel("--model", opts.model);
7254
7399
  const res = await api(ctx, "/v1/agents/run", {
7255
7400
  body: {
7256
7401
  agent: spawnAgent,
@@ -7279,21 +7424,21 @@ function toContractId(id) {
7279
7424
  return id === "claude" ? "claude_code" : id;
7280
7425
  }
7281
7426
  function formatRole(r) {
7282
- const label = import_picocolors15.default.yellow(r.role);
7283
- const agent = import_picocolors15.default.dim("\xB7 " + (r.agent ?? "?"));
7284
- const enabled = r.enabled === false ? import_picocolors15.default.red("disabled") : import_picocolors15.default.green("enabled");
7427
+ const label = import_picocolors16.default.yellow(r.role);
7428
+ const agent = import_picocolors16.default.dim("\xB7 " + (r.agent ?? "?"));
7429
+ const enabled = r.enabled === false ? import_picocolors16.default.red("disabled") : import_picocolors16.default.green("enabled");
7285
7430
  const runnable = r.installed && r.authed !== false;
7286
- const ready = runnable ? import_picocolors15.default.green("runnable") : import_picocolors15.default.dim("not runnable");
7431
+ const ready = runnable ? import_picocolors16.default.green("runnable") : import_picocolors16.default.dim("not runnable");
7287
7432
  const extras = [];
7288
7433
  if (r.model) extras.push(`model ${r.model}`);
7289
7434
  if (Array.isArray(r.apps) && r.apps.length) extras.push(`apps: ${r.apps.join(",")}`);
7290
7435
  if (Array.isArray(r.mcp) && r.mcp.length) extras.push(`mcp: ${r.mcp.length}`);
7291
- const tail = extras.length ? " " + import_picocolors15.default.dim(extras.join(" \xB7 ")) : "";
7436
+ const tail = extras.length ? " " + import_picocolors16.default.dim(extras.join(" \xB7 ")) : "";
7292
7437
  return `${label} ${agent} ${enabled} ${ready}${tail}`;
7293
7438
  }
7294
7439
 
7295
7440
  // src/commands/verify.ts
7296
- var import_picocolors16 = __toESM(require_picocolors(), 1);
7441
+ var import_picocolors17 = __toESM(require_picocolors(), 1);
7297
7442
  function registerVerify(program3) {
7298
7443
  program3.command("verify").description(
7299
7444
  "Run the project's checks (typecheck/lint/build) \u2014 use before declaring a task done"
@@ -7315,23 +7460,23 @@ function registerVerify(program3) {
7315
7460
  function printVerify(res) {
7316
7461
  if (!res) return;
7317
7462
  if (!res.checks?.length) {
7318
- line(import_picocolors16.default.dim(res.note ?? "No checks detected."));
7463
+ line(import_picocolors17.default.dim(res.note ?? "No checks detected."));
7319
7464
  return;
7320
7465
  }
7321
7466
  for (const c of res.checks) {
7322
7467
  line(
7323
- ` ${c.ok ? import_picocolors16.default.green("\u2713") : import_picocolors16.default.red("\u2717")} ${c.name}${c.ok ? "" : import_picocolors16.default.dim(` (exit ${c.exitCode})`)}`
7468
+ ` ${c.ok ? import_picocolors17.default.green("\u2713") : import_picocolors17.default.red("\u2717")} ${c.name}${c.ok ? "" : import_picocolors17.default.dim(` (exit ${c.exitCode})`)}`
7324
7469
  );
7325
7470
  }
7326
7471
  if (res.ok) success("All checks passed");
7327
7472
  else
7328
7473
  line(
7329
- import_picocolors16.default.red("Some checks failed \u2014 fix the errors above and re-run ") + import_picocolors16.default.bold("workser verify") + import_picocolors16.default.red(".")
7474
+ import_picocolors17.default.red("Some checks failed \u2014 fix the errors above and re-run ") + import_picocolors17.default.bold("workser verify") + import_picocolors17.default.red(".")
7330
7475
  );
7331
7476
  }
7332
7477
 
7333
7478
  // src/commands/checkpoint.ts
7334
- var import_picocolors17 = __toESM(require_picocolors(), 1);
7479
+ var import_picocolors18 = __toESM(require_picocolors(), 1);
7335
7480
  function registerCheckpoint(program3) {
7336
7481
  program3.command("checkpoint [label]").description(
7337
7482
  "Save the current state of this folder so you can come back to it"
@@ -7348,8 +7493,8 @@ function registerCheckpoint(program3) {
7348
7493
  ok(res, () => {
7349
7494
  const p = res?.point;
7350
7495
  success(`Saved a checkpoint${p?.label ? `: ${p.label}` : ""}`);
7351
- if (p?.ref) line(import_picocolors17.default.dim(` ${p.ref.slice(0, 7)}`));
7352
- line(import_picocolors17.default.dim(" Come back to it with `workser restore`."));
7496
+ if (p?.ref) line(import_picocolors18.default.dim(` ${p.ref.slice(0, 7)}`));
7497
+ line(import_picocolors18.default.dim(" Come back to it with `workser restore`."));
7353
7498
  });
7354
7499
  })
7355
7500
  );
@@ -7375,12 +7520,12 @@ function registerCheckpoint(program3) {
7375
7520
  );
7376
7521
  if (res?.filesChanged) {
7377
7522
  line(
7378
- import_picocolors17.default.dim(
7523
+ import_picocolors18.default.dim(
7379
7524
  ` ${res.filesChanged} file${res.filesChanged === 1 ? "" : "s"} changed`
7380
7525
  )
7381
7526
  );
7382
7527
  }
7383
- line(import_picocolors17.default.dim(" This is reversible: `workser restore` again."));
7528
+ line(import_picocolors18.default.dim(" This is reversible: `workser restore` again."));
7384
7529
  });
7385
7530
  })
7386
7531
  );
@@ -7397,25 +7542,25 @@ function registerCheckpoint(program3) {
7397
7542
  function printPoints(points) {
7398
7543
  if (!points.length) {
7399
7544
  info("No checkpoints yet for this folder.");
7400
- line(import_picocolors17.default.dim(" Take one with `workser checkpoint`."));
7545
+ line(import_picocolors18.default.dim(" Take one with `workser checkpoint`."));
7401
7546
  return;
7402
7547
  }
7403
- line(import_picocolors17.default.bold("Checkpoints"));
7548
+ line(import_picocolors18.default.bold("Checkpoints"));
7404
7549
  for (const p of points) {
7405
7550
  const when = p.at ? new Date(p.at).toLocaleString() : "";
7406
7551
  line(
7407
- ` ${import_picocolors17.default.dim(p.ref.slice(0, 7))} ${p.label}${when ? import_picocolors17.default.dim(` ${when}`) : ""}`
7552
+ ` ${import_picocolors18.default.dim(p.ref.slice(0, 7))} ${p.label}${when ? import_picocolors18.default.dim(` ${when}`) : ""}`
7408
7553
  );
7409
7554
  }
7410
7555
  line(
7411
- import_picocolors17.default.dim(
7556
+ import_picocolors18.default.dim(
7412
7557
  "\nGo back with `workser restore <ref>`, or just `workser restore` for the newest."
7413
7558
  )
7414
7559
  );
7415
7560
  }
7416
7561
 
7417
7562
  // src/commands/sync.ts
7418
- var import_picocolors18 = __toESM(require_picocolors(), 1);
7563
+ var import_picocolors19 = __toESM(require_picocolors(), 1);
7419
7564
  function registerSync(program3) {
7420
7565
  program3.command("sync").description(
7421
7566
  "Reconcile this folder with the copy Workser holds (pull, then push)"
@@ -7442,7 +7587,7 @@ function registerSync(program3) {
7442
7587
  warn(res?.message ?? "Couldn't sync this folder.");
7443
7588
  if (res?.state === "diverged") {
7444
7589
  line(
7445
- import_picocolors18.default.dim(
7590
+ import_picocolors19.default.dim(
7446
7591
  " This folder and Workser's copy have both changed. Open Workser to resolve it."
7447
7592
  )
7448
7593
  );
@@ -7454,7 +7599,7 @@ function registerSync(program3) {
7454
7599
  return;
7455
7600
  }
7456
7601
  success("Synced");
7457
- if (res?.ref) line(import_picocolors18.default.dim(` ${String(res.ref).slice(0, 7)}`));
7602
+ if (res?.ref) line(import_picocolors19.default.dim(` ${String(res.ref).slice(0, 7)}`));
7458
7603
  });
7459
7604
  if (refused) process.exitCode = 1;
7460
7605
  })
@@ -7462,7 +7607,7 @@ function registerSync(program3) {
7462
7607
  }
7463
7608
 
7464
7609
  // src/commands/workflow.ts
7465
- var import_picocolors19 = __toESM(require_picocolors(), 1);
7610
+ var import_picocolors20 = __toESM(require_picocolors(), 1);
7466
7611
  function registerWorkflow(program3) {
7467
7612
  const wf = program3.command("workflow").description("Create, run, and inspect workflow automations for the project");
7468
7613
  wf.command("list").description("List the project's workflows").action(
@@ -7470,10 +7615,10 @@ function registerWorkflow(program3) {
7470
7615
  const projectId = requireProject(ctx);
7471
7616
  const items = await api(ctx, `/v1/projects/${projectId}/workflows`);
7472
7617
  ok(items, () => {
7473
- if (!items?.length) return line(import_picocolors19.default.dim("No workflows yet. `workser workflow create`."));
7618
+ if (!items?.length) return line(import_picocolors20.default.dim("No workflows yet. `workser workflow create`."));
7474
7619
  for (const w of items) {
7475
- const status = w.is_active ? import_picocolors19.default.green("active") : import_picocolors19.default.dim("inactive");
7476
- line(`${w.id} ${import_picocolors19.default.bold(w.name ?? "Untitled")} ${status}`);
7620
+ const status = w.is_active ? import_picocolors20.default.green("active") : import_picocolors20.default.dim("inactive");
7621
+ line(`${w.id} ${import_picocolors20.default.bold(w.name ?? "Untitled")} ${status}`);
7477
7622
  }
7478
7623
  });
7479
7624
  })
@@ -7485,7 +7630,7 @@ function registerWorkflow(program3) {
7485
7630
  const res = await api(ctx, `/v1/projects/${projectId}/workflows`, {
7486
7631
  body: { name: args[0], ...extra }
7487
7632
  });
7488
- ok(res, () => line(`Created workflow ${import_picocolors19.default.bold(res.id)}.`));
7633
+ ok(res, () => line(`Created workflow ${import_picocolors20.default.bold(res.id)}.`));
7489
7634
  })
7490
7635
  );
7491
7636
  wf.command("get <id>").description("Show a workflow's full definition").action(
@@ -7520,8 +7665,8 @@ function registerWorkflow(program3) {
7520
7665
  action(async ({ ctx, args }) => {
7521
7666
  const items = await api(ctx, `/v1/workflows/${args[0]}/executions`);
7522
7667
  ok(items, () => {
7523
- if (!items?.length) return line(import_picocolors19.default.dim("No runs yet."));
7524
- for (const e of items) line(`${e.id} ${e.status ?? ""} ${import_picocolors19.default.dim(e.started_at ?? "")}`);
7668
+ if (!items?.length) return line(import_picocolors20.default.dim("No runs yet."));
7669
+ for (const e of items) line(`${e.id} ${e.status ?? ""} ${import_picocolors20.default.dim(e.started_at ?? "")}`);
7525
7670
  });
7526
7671
  })
7527
7672
  );
@@ -7529,15 +7674,15 @@ function registerWorkflow(program3) {
7529
7674
  action(async ({ ctx, args }) => {
7530
7675
  const items = await api(ctx, `/v1/node-types`, { query: { q: args[0] } });
7531
7676
  ok(items, () => {
7532
- if (!items?.length) return line(import_picocolors19.default.dim("No matching node types."));
7533
- for (const n of items) line(`${n.name ?? n.type} ${import_picocolors19.default.dim(n.category ?? "")}`);
7677
+ if (!items?.length) return line(import_picocolors20.default.dim("No matching node types."));
7678
+ for (const n of items) line(`${n.name ?? n.type} ${import_picocolors20.default.dim(n.category ?? "")}`);
7534
7679
  });
7535
7680
  })
7536
7681
  );
7537
7682
  }
7538
7683
 
7539
7684
  // src/commands/connection.ts
7540
- var import_picocolors20 = __toESM(require_picocolors(), 1);
7685
+ var import_picocolors21 = __toESM(require_picocolors(), 1);
7541
7686
  function registerConnection(program3) {
7542
7687
  const connection = program3.command("connection").description("Connect and use third-party app connections (Gmail, Slack, Stripe, ...)");
7543
7688
  connection.command("list").description("List connectable toolkits and this project's existing connections").option("--toolkit <slug>", "filter connections to one toolkit").action(
@@ -7550,8 +7695,8 @@ function registerConnection(program3) {
7550
7695
  ok({ catalog, connections }, () => {
7551
7696
  const connected = new Set((connections ?? []).map((c) => c.toolkit ?? c.composio_app));
7552
7697
  for (const t of catalog ?? []) {
7553
- const status = connected.has(t.slug) ? import_picocolors20.default.green("connected") : import_picocolors20.default.dim("not connected");
7554
- line(`${t.slug} ${import_picocolors20.default.bold(t.name ?? t.slug)} ${status}`);
7698
+ const status = connected.has(t.slug) ? import_picocolors21.default.green("connected") : import_picocolors21.default.dim("not connected");
7699
+ line(`${t.slug} ${import_picocolors21.default.bold(t.name ?? t.slug)} ${status}`);
7555
7700
  }
7556
7701
  });
7557
7702
  })
@@ -7563,9 +7708,9 @@ function registerConnection(program3) {
7563
7708
  query: { q: args[0], toolkit: opts.toolkit, limit: opts.limit }
7564
7709
  });
7565
7710
  ok(items, () => {
7566
- if (!items?.length) return line(import_picocolors20.default.dim("No matching actions."));
7711
+ if (!items?.length) return line(import_picocolors21.default.dim("No matching actions."));
7567
7712
  for (const t of items) {
7568
- line(`${t.slug} ${import_picocolors20.default.dim(`[${t.toolkit}]`)} ${t.description ?? ""}`);
7713
+ line(`${t.slug} ${import_picocolors21.default.dim(`[${t.toolkit}]`)} ${t.description ?? ""}`);
7569
7714
  }
7570
7715
  });
7571
7716
  })
@@ -7582,7 +7727,7 @@ function registerConnection(program3) {
7582
7727
  });
7583
7728
  ok(
7584
7729
  res,
7585
- () => res.oauth_url ? line(`Open this URL to finish connecting: ${import_picocolors20.default.underline(res.oauth_url)}`) : line(`Connection ${res.connection_id} is ${res.status}.`)
7730
+ () => res.oauth_url ? line(`Open this URL to finish connecting: ${import_picocolors21.default.underline(res.oauth_url)}`) : line(`Connection ${res.connection_id} is ${res.status}.`)
7586
7731
  );
7587
7732
  })
7588
7733
  );
@@ -7600,8 +7745,8 @@ function registerConnection(program3) {
7600
7745
  const projectId = requireProject(ctx);
7601
7746
  const items = await api(ctx, `/v1/projects/${projectId}/integrations/${args[0]}/tools`);
7602
7747
  ok(items, () => {
7603
- if (!items?.length) return line(import_picocolors20.default.dim("No tools found."));
7604
- for (const t of items) line(`${t.slug} ${import_picocolors20.default.dim(t.description ?? "")}`);
7748
+ if (!items?.length) return line(import_picocolors21.default.dim("No tools found."));
7749
+ for (const t of items) line(`${t.slug} ${import_picocolors21.default.dim(t.description ?? "")}`);
7605
7750
  });
7606
7751
  })
7607
7752
  );
@@ -7617,7 +7762,7 @@ function registerConnection(program3) {
7617
7762
  }
7618
7763
 
7619
7764
  // src/commands/tool.ts
7620
- var import_picocolors21 = __toESM(require_picocolors(), 1);
7765
+ var import_picocolors22 = __toESM(require_picocolors(), 1);
7621
7766
  function registerTool(program3) {
7622
7767
  const tool = program3.command("tool").description(
7623
7768
  "Computer-use tools: filesystem, shell, screenshot, input control, clipboard, notifications, basic browser"
@@ -7626,7 +7771,7 @@ function registerTool(program3) {
7626
7771
  action(async ({ ctx }) => {
7627
7772
  const tools = await api(ctx, "/v1/tool/list");
7628
7773
  ok(tools, () => {
7629
- if (!tools?.length) return line(import_picocolors21.default.dim("No tools available."));
7774
+ if (!tools?.length) return line(import_picocolors22.default.dim("No tools available."));
7630
7775
  const byCategory = /* @__PURE__ */ new Map();
7631
7776
  for (const t of tools) {
7632
7777
  const list = byCategory.get(t.category) ?? [];
@@ -7634,9 +7779,9 @@ function registerTool(program3) {
7634
7779
  byCategory.set(t.category, list);
7635
7780
  }
7636
7781
  for (const [category, items] of byCategory) {
7637
- line(import_picocolors21.default.bold(category) + ":");
7782
+ line(import_picocolors22.default.bold(category) + ":");
7638
7783
  for (const t of items) {
7639
- line(` ${t.name} ${import_picocolors21.default.dim(t.description ?? "")}`);
7784
+ line(` ${t.name} ${import_picocolors22.default.dim(t.description ?? "")}`);
7640
7785
  }
7641
7786
  }
7642
7787
  });
@@ -7654,7 +7799,7 @@ function registerTool(program3) {
7654
7799
  }
7655
7800
 
7656
7801
  // src/commands/memory.ts
7657
- var import_picocolors22 = __toESM(require_picocolors(), 1);
7802
+ var import_picocolors23 = __toESM(require_picocolors(), 1);
7658
7803
  function registerMemory(program3) {
7659
7804
  const memory = program3.command("memory").description("Durable, cross-conversation project memory (shared with cloud agents on the same project)");
7660
7805
  memory.command("add <content>").description("Store something worth remembering across future conversations").option("--metadata <json>", "extra metadata for filtering, as a JSON string").option("--id <customId>", "custom id for dedup/updates").action(
@@ -7678,9 +7823,9 @@ function registerMemory(program3) {
7678
7823
  });
7679
7824
  ok(res, () => {
7680
7825
  const results = res?.results ?? res ?? [];
7681
- if (!results?.length) return line(import_picocolors22.default.dim("No matching memories."));
7826
+ if (!results?.length) return line(import_picocolors23.default.dim("No matching memories."));
7682
7827
  for (const r of results) {
7683
- line(`${import_picocolors22.default.dim(r.id ?? "?")} ${r.memory ?? r.content ?? ""}`);
7828
+ line(`${import_picocolors23.default.dim(r.id ?? "?")} ${r.memory ?? r.content ?? ""}`);
7684
7829
  }
7685
7830
  });
7686
7831
  })
@@ -7697,7 +7842,7 @@ function registerMemory(program3) {
7697
7842
  }
7698
7843
 
7699
7844
  // src/commands/business.ts
7700
- var import_picocolors23 = __toESM(require_picocolors(), 1);
7845
+ var import_picocolors24 = __toESM(require_picocolors(), 1);
7701
7846
  var RESOURCE_PATHS = {
7702
7847
  "business-config": "business-config",
7703
7848
  "business-settings": "business-settings",
@@ -7757,7 +7902,7 @@ function registerBusiness(program3) {
7757
7902
  const projectId = requireProject(ctx);
7758
7903
  const [resource] = args;
7759
7904
  const res = await api(ctx, businessPath(projectId, resource), { body: JSON.parse(opts.body) });
7760
- ok(res, () => line(`Created ${resource} ${import_picocolors23.default.bold(res?.id ?? "")}.`));
7905
+ ok(res, () => line(`Created ${resource} ${import_picocolors24.default.bold(res?.id ?? "")}.`));
7761
7906
  })
7762
7907
  );
7763
7908
  biz.command("update <resource> <id>").description("Update a record by id (PATCH/PUT \u2014 matches the underlying route)").option("--body <json>", "changed fields as a JSON object string", "{}").action(
@@ -7799,7 +7944,7 @@ function businessPath(projectId, resource, subpath) {
7799
7944
  }
7800
7945
 
7801
7946
  // src/commands/artifact.ts
7802
- var import_picocolors24 = __toESM(require_picocolors(), 1);
7947
+ var import_picocolors25 = __toESM(require_picocolors(), 1);
7803
7948
  import { existsSync as existsSync2, statSync } from "fs";
7804
7949
  import { resolve as resolve3, basename as basename3 } from "path";
7805
7950
  var KINDS = [
@@ -7896,7 +8041,7 @@ function registerArtifact(program3) {
7896
8041
  ok(
7897
8042
  res,
7898
8043
  () => success(
7899
- `Recorded ${import_picocolors24.default.bold(res?.title ?? "artifact")}${res?.kind ? import_picocolors24.default.dim(` (${res.kind})`) : ""}`
8044
+ `Recorded ${import_picocolors25.default.bold(res?.title ?? "artifact")}${res?.kind ? import_picocolors25.default.dim(` (${res.kind})`) : ""}`
7900
8045
  )
7901
8046
  );
7902
8047
  })
@@ -7934,7 +8079,7 @@ function registerArtifact(program3) {
7934
8079
  }
7935
8080
  function printArtifacts(rows) {
7936
8081
  if (!rows.length) {
7937
- line(import_picocolors24.default.dim("Nothing produced yet."));
8082
+ line(import_picocolors25.default.dim("Nothing produced yet."));
7938
8083
  return;
7939
8084
  }
7940
8085
  const byStep = /* @__PURE__ */ new Map();
@@ -7944,26 +8089,26 @@ function printArtifacts(rows) {
7944
8089
  byStep.set(r.subtask_id, list);
7945
8090
  }
7946
8091
  for (const [stepId, items] of byStep) {
7947
- line(import_picocolors24.default.bold(`step ${stepId}`));
8092
+ line(import_picocolors25.default.bold(`step ${stepId}`));
7948
8093
  for (const a of items) {
7949
- const flag = a.promoted_at ? import_picocolors24.default.green(" *") : " ";
8094
+ const flag = a.promoted_at ? import_picocolors25.default.green(" *") : " ";
7950
8095
  const where = a.local_path || a.cloud_url || "";
7951
8096
  line(
7952
- `${flag} ${import_picocolors24.default.dim(`[${a.kind}]`)} ${a.title ?? "(untitled)"}` + (where ? import_picocolors24.default.dim(` ${where}`) : "")
8097
+ `${flag} ${import_picocolors25.default.dim(`[${a.kind}]`)} ${a.title ?? "(untitled)"}` + (where ? import_picocolors25.default.dim(` ${where}`) : "")
7953
8098
  );
7954
- if (a.description) line(import_picocolors24.default.dim(` ${a.description}`));
8099
+ if (a.description) line(import_picocolors25.default.dim(` ${a.description}`));
7955
8100
  }
7956
8101
  line("");
7957
8102
  }
7958
- line(import_picocolors24.default.dim("* = handed over as a deliverable; the rest is working material."));
8103
+ line(import_picocolors25.default.dim("* = handed over as a deliverable; the rest is working material."));
7959
8104
  }
7960
8105
  function printRun(run) {
7961
8106
  if (!run) return;
7962
- line(` run ${import_picocolors24.default.bold(run.runId)}`);
8107
+ line(` run ${import_picocolors25.default.bold(run.runId)}`);
7963
8108
  if (run.taskId) line(` task ${run.taskId}`);
7964
8109
  if (run.conversationId) line(` chat ${run.conversationId}`);
7965
8110
  if (run.projectId) line(` project ${run.projectId}`);
7966
- if (run.cwd) line(` folder ${import_picocolors24.default.dim(run.cwd)}`);
8111
+ if (run.cwd) line(` folder ${import_picocolors25.default.dim(run.cwd)}`);
7967
8112
  }
7968
8113
 
7969
8114
  // src/commands/image.ts
@@ -8144,7 +8289,7 @@ function registerAudio(program3) {
8144
8289
  }
8145
8290
 
8146
8291
  // src/commands/ask.ts
8147
- var import_picocolors25 = __toESM(require_picocolors(), 1);
8292
+ var import_picocolors26 = __toESM(require_picocolors(), 1);
8148
8293
  var TYPES = [
8149
8294
  "input",
8150
8295
  "choice",
@@ -8222,7 +8367,7 @@ function registerAsk(program3) {
8222
8367
  code: "bad_request"
8223
8368
  });
8224
8369
  }
8225
- info(import_picocolors25.default.dim("Waiting for the user to answer\u2026"));
8370
+ info(import_picocolors26.default.dim("Waiting for the user to answer\u2026"));
8226
8371
  const res = await api(ctx, `/v1/runs/${runTarget(ctx)}/ask`, {
8227
8372
  body: {
8228
8373
  type,
@@ -8250,12 +8395,12 @@ function deriveTitle(message) {
8250
8395
  function printAnswer(res) {
8251
8396
  if (!res) return;
8252
8397
  if (res.status === "answered") {
8253
- line(` ${import_picocolors25.default.green("answered")}`);
8398
+ line(` ${import_picocolors26.default.green("answered")}`);
8254
8399
  const value = extract(res.response);
8255
8400
  if (value) line(` ${value}`);
8256
8401
  return;
8257
8402
  }
8258
- line(` ${import_picocolors25.default.yellow(res.status)} ${import_picocolors25.default.dim(res.reason ?? "")}`);
8403
+ line(` ${import_picocolors26.default.yellow(res.status)} ${import_picocolors26.default.dim(res.reason ?? "")}`);
8259
8404
  }
8260
8405
  function extract(response) {
8261
8406
  if (response == null) return "";
@@ -8274,7 +8419,7 @@ function extract(response) {
8274
8419
  }
8275
8420
 
8276
8421
  // src/commands/search.ts
8277
- var import_picocolors26 = __toESM(require_picocolors(), 1);
8422
+ var import_picocolors27 = __toESM(require_picocolors(), 1);
8278
8423
  function registerSearch(program3) {
8279
8424
  program3.command("search <query>").description("Search the web (Google-grounded, server-side)").option("-n, --max-results <n>", "max results", "5").action(
8280
8425
  action(async ({ ctx, args, opts }) => {
@@ -8287,9 +8432,9 @@ function registerSearch(program3) {
8287
8432
  line("");
8288
8433
  }
8289
8434
  const results = res?.results ?? [];
8290
- if (!results.length) return line(import_picocolors26.default.dim("No results."));
8435
+ if (!results.length) return line(import_picocolors27.default.dim("No results."));
8291
8436
  for (const r of results) {
8292
- line(`${r.title || import_picocolors26.default.dim("(untitled)")} ${import_picocolors26.default.dim(r.url)}`);
8437
+ line(`${r.title || import_picocolors27.default.dim("(untitled)")} ${import_picocolors27.default.dim(r.url)}`);
8293
8438
  }
8294
8439
  });
8295
8440
  })
@@ -8297,7 +8442,7 @@ function registerSearch(program3) {
8297
8442
  }
8298
8443
 
8299
8444
  // src/commands/board.ts
8300
- var import_picocolors27 = __toESM(require_picocolors(), 1);
8445
+ var import_picocolors28 = __toESM(require_picocolors(), 1);
8301
8446
 
8302
8447
  // src/commands/record-step.ts
8303
8448
  async function recordEntityStep(ctx, opts) {
@@ -8336,7 +8481,7 @@ function registerBoard(program3) {
8336
8481
  }
8337
8482
  ok(rows, () => {
8338
8483
  if (!rows.length) {
8339
- line(import_picocolors27.default.dim("No cards on the Board yet."));
8484
+ line(import_picocolors28.default.dim("No cards on the Board yet."));
8340
8485
  return;
8341
8486
  }
8342
8487
  for (const r of rows) line(formatRow(r));
@@ -8351,7 +8496,7 @@ function registerBoard(program3) {
8351
8496
  `/v1/projects/${projectId}/work-items/${args[0]}`
8352
8497
  );
8353
8498
  ok(row, () => {
8354
- line(`${import_picocolors27.default.bold(row.title)} ${import_picocolors27.default.dim(row.id)}`);
8499
+ line(`${import_picocolors28.default.bold(row.title)} ${import_picocolors28.default.dim(row.id)}`);
8355
8500
  line(`${statusTag(row.status)} priority ${row.priority}`);
8356
8501
  if (row.ownerHuman) line(`owner: ${row.ownerHuman}`);
8357
8502
  if (row.labels?.length) line(`labels: ${row.labels.join(", ")}`);
@@ -8392,7 +8537,7 @@ ${row.description}`);
8392
8537
  refId: row?.id,
8393
8538
  output: { workItem: row }
8394
8539
  });
8395
- ok(row, () => line(`Created work item ${import_picocolors27.default.bold(row?.id ?? "")} \u2014 ${title}`));
8540
+ ok(row, () => line(`Created work item ${import_picocolors28.default.bold(row?.id ?? "")} \u2014 ${title}`));
8396
8541
  })
8397
8542
  );
8398
8543
  board.command("update <id>").description("Change fields on a card \u2014 pass only what changes").option("--title <text>", "new title").option("--description <text>", "new description").option("--status <value>", STATUSES.join(" | ")).option("--priority <value>", PRIORITIES.join(" | ")).option(
@@ -8426,7 +8571,7 @@ ${row.description}`);
8426
8571
  );
8427
8572
  }
8428
8573
  const row = await patchItem(ctx, projectId, String(args[0]), body);
8429
- ok(row, () => line(`Updated ${import_picocolors27.default.bold(row.id)} \u2014 ${row.title} ${statusTag(row.status)}`));
8574
+ ok(row, () => line(`Updated ${import_picocolors28.default.bold(row.id)} \u2014 ${row.title} ${statusTag(row.status)}`));
8430
8575
  })
8431
8576
  );
8432
8577
  board.command("move <id> <status>").description(
@@ -8437,14 +8582,14 @@ ${row.description}`);
8437
8582
  const status = String(args[1]);
8438
8583
  assertStatus(status);
8439
8584
  const row = await patchItem(ctx, projectId, String(args[0]), { status });
8440
- ok(row, () => line(`Moved ${import_picocolors27.default.bold(row.title)} \u2192 ${statusTag(row.status)}`));
8585
+ ok(row, () => line(`Moved ${import_picocolors28.default.bold(row.title)} \u2192 ${statusTag(row.status)}`));
8441
8586
  })
8442
8587
  );
8443
8588
  board.command("close <id>").description("Shorthand for `board move <id> done`").action(
8444
8589
  action(async ({ ctx, args }) => {
8445
8590
  const projectId = requireProject(ctx);
8446
8591
  const row = await patchItem(ctx, projectId, String(args[0]), { status: "done" });
8447
- ok(row, () => line(`Closed ${import_picocolors27.default.bold(row.title)} ${statusTag(row.status)}`));
8592
+ ok(row, () => line(`Closed ${import_picocolors28.default.bold(row.title)} ${statusTag(row.status)}`));
8448
8593
  })
8449
8594
  );
8450
8595
  }
@@ -8477,23 +8622,23 @@ function assertPriority(value) {
8477
8622
  }
8478
8623
  }
8479
8624
  function formatRow(r) {
8480
- const labels = r.labels?.length ? import_picocolors27.default.dim(` [${r.labels.join(", ")}]`) : "";
8481
- const owner = r.ownerHuman ? import_picocolors27.default.dim(` @${r.ownerHuman}`) : "";
8482
- return `${import_picocolors27.default.dim(r.id)} ${statusTag(r.status)} ${r.title}${labels}${owner}`;
8625
+ const labels = r.labels?.length ? import_picocolors28.default.dim(` [${r.labels.join(", ")}]`) : "";
8626
+ const owner = r.ownerHuman ? import_picocolors28.default.dim(` @${r.ownerHuman}`) : "";
8627
+ return `${import_picocolors28.default.dim(r.id)} ${statusTag(r.status)} ${r.title}${labels}${owner}`;
8483
8628
  }
8484
8629
  function statusTag(status) {
8485
8630
  const label = status.padEnd(11);
8486
- if (status === "done") return import_picocolors27.default.green(label);
8487
- if (status === "in-progress") return import_picocolors27.default.yellow(label);
8488
- if (status === "in-review") return import_picocolors27.default.cyan(label);
8489
- return import_picocolors27.default.dim(label);
8631
+ if (status === "done") return import_picocolors28.default.green(label);
8632
+ if (status === "in-progress") return import_picocolors28.default.yellow(label);
8633
+ if (status === "in-review") return import_picocolors28.default.cyan(label);
8634
+ return import_picocolors28.default.dim(label);
8490
8635
  }
8491
8636
  function collect2(value, previous) {
8492
8637
  return [...previous, value];
8493
8638
  }
8494
8639
 
8495
8640
  // src/commands/task.ts
8496
- var import_picocolors28 = __toESM(require_picocolors(), 1);
8641
+ var import_picocolors29 = __toESM(require_picocolors(), 1);
8497
8642
  var STATUSES2 = [
8498
8643
  "todo",
8499
8644
  "working",
@@ -8502,7 +8647,30 @@ var STATUSES2 = [
8502
8647
  "accepted",
8503
8648
  "archived"
8504
8649
  ];
8505
- var ROLES = ["pm", "architect", "web", "api", "automation", "qa"];
8650
+ var ROLES = [
8651
+ "pm",
8652
+ "architect",
8653
+ "designer",
8654
+ "web",
8655
+ "api",
8656
+ "mobile",
8657
+ "python",
8658
+ "automation",
8659
+ "qa",
8660
+ "devops",
8661
+ "sre",
8662
+ "security",
8663
+ "analyst"
8664
+ ];
8665
+ var AGENTS = [
8666
+ "claude_code",
8667
+ "codex",
8668
+ "workser_code",
8669
+ "opencode",
8670
+ "cursor",
8671
+ "gemini"
8672
+ ];
8673
+ var EFFORTS = ["low", "medium", "high", "xhigh", "max"];
8506
8674
  var KINDS2 = [
8507
8675
  "data_reports",
8508
8676
  "web",
@@ -8511,6 +8679,7 @@ var KINDS2 = [
8511
8679
  "automation",
8512
8680
  "docs"
8513
8681
  ];
8682
+ var KIND_HELP = "what it produces (web app \u2192 web \xB7 phone app \u2192 mobile \xB7 api or ai-agent \u2192 service \xB7 worker or scheduled job \u2192 automation \xB7 report or analysis \u2192 data_reports \xB7 written page \u2192 docs)";
8514
8683
  function registerTask(program3) {
8515
8684
  const task = program3.command("task").description("The project's tasks and their subtasks (AI Tech Team)");
8516
8685
  task.command("list").description("List the board's tasks \u2014 run this before starting anything").option(
@@ -8530,7 +8699,7 @@ function registerTask(program3) {
8530
8699
  }) ?? [];
8531
8700
  ok(rows, () => {
8532
8701
  if (!rows.length) {
8533
- line(import_picocolors28.default.dim("No tasks on the board yet."));
8702
+ line(import_picocolors29.default.dim("No tasks on the board yet."));
8534
8703
  return;
8535
8704
  }
8536
8705
  for (const r of rows) line(formatRow2(r));
@@ -8554,7 +8723,7 @@ function registerTask(program3) {
8554
8723
  ok({ ...row, goal }, () => printTask(row, goal));
8555
8724
  })
8556
8725
  );
8557
- task.command("create <title>").description("Open a new root task for the project team").option("--note <text>", "context, constraints and expected outcome").option("--kind <value>", `what it produces (${KINDS2.join(" | ")})`).option("--label <value...>", "labels to put on the task").option("--app <id...>", "apps the task touches").option("--infra <ref...>", "shared setup it touches").option("--goal <id>", "the business goal this delivers part of").option(
8726
+ task.command("create <title>").description("Open a new root task for the project team").option("--note <text>", "context, constraints and expected outcome").option("--kind <value>", KIND_HELP).option("--label <value...>", "labels to put on the task").option("--app <id...>", "apps the task touches").option("--infra <ref...>", "shared setup it touches").option("--goal <id>", "the business goal this delivers part of").option(
8558
8727
  "--phase <name>",
8559
8728
  "which slice of that goal \u2014 must match one of its phase names"
8560
8729
  ).action(
@@ -8623,10 +8792,10 @@ function registerTask(program3) {
8623
8792
  };
8624
8793
  ok(result, () => {
8625
8794
  line(
8626
- `${import_picocolors28.default.green("opened")} ${import_picocolors28.default.bold(row.title)} ${import_picocolors28.default.dim(row.key ?? row.id)}`
8795
+ `${import_picocolors29.default.green("opened")} ${import_picocolors29.default.bold(row.title)} ${import_picocolors29.default.dim(row.key ?? row.id)}`
8627
8796
  );
8628
8797
  if (channelMessage)
8629
- line(import_picocolors28.default.dim("posted to the channel as Project Manager"));
8798
+ line(import_picocolors29.default.dim("posted to the channel as Project Manager"));
8630
8799
  if (channelMessageError) {
8631
8800
  warn(
8632
8801
  `Task opened, but its Project Manager card could not be posted: ${channelMessageError.message}`
@@ -8641,7 +8810,7 @@ function registerTask(program3) {
8641
8810
  ).option(
8642
8811
  "--task <id>",
8643
8812
  "the parent task (defaults to the task this run is inside)"
8644
- ).option("--role <value>", `who does it (${ROLES.join(" | ")})`).option("--kind <value>", `what it produces (${KINDS2.join(" | ")})`).option("--note <text>", "one sentence on what this subtask does").option(
8813
+ ).option("--role <value>", `who does it (${ROLES.join(" | ")})`).option("--kind <value>", KIND_HELP).option("--note <text>", "one sentence on what this subtask does").option(
8645
8814
  "--app <id...>",
8646
8815
  "the app this subtask is for \u2014 one id runs it inside that app's folder; leave it off and it runs at the project, seeing every app"
8647
8816
  ).option(
@@ -8650,11 +8819,18 @@ function registerTask(program3) {
8650
8819
  ).option("--scope <path...>", "files or folders THIS subtask owns").option(
8651
8820
  "--depends-on <id...>",
8652
8821
  "subtasks that must finish first (key or id)"
8653
- ).action(
8822
+ ).option(
8823
+ "--agent <id>",
8824
+ `run this step on a specific CLI (${AGENTS.join(" | ")}) instead of the role's own`
8825
+ ).option("--model <id>", "the model that CLI should use for this step").option("--effort <level>", `how hard it thinks (${EFFORTS.join(" | ")})`).action(
8654
8826
  action(async ({ ctx, args, opts }) => {
8655
8827
  const parent = resolveTaskId(ctx, opts.task);
8656
8828
  if (opts.role !== void 0) assertOneOf("--role", opts.role, ROLES);
8657
8829
  if (opts.kind !== void 0) assertOneOf("--kind", opts.kind, KINDS2);
8830
+ if (opts.agent !== void 0) assertOneOf("--agent", opts.agent, AGENTS);
8831
+ if (opts.effort !== void 0)
8832
+ assertOneOf("--effort", opts.effort, EFFORTS);
8833
+ assertDelegatableModel("--model", opts.model);
8658
8834
  const dependsOn = await resolveDeps(ctx, parent, opts.dependsOn ?? []);
8659
8835
  const row = await api(ctx, "/v1/project-tasks", {
8660
8836
  body: {
@@ -8677,11 +8853,30 @@ function registerTask(program3) {
8677
8853
  ]
8678
8854
  }
8679
8855
  });
8680
- ok(row, () => {
8856
+ const runner = opts.agent !== void 0 || opts.model !== void 0 || opts.effort !== void 0 ? await api(
8857
+ ctx,
8858
+ `/v1/project-tasks/${encodeURIComponent(row.id)}`,
8859
+ {
8860
+ method: "PATCH",
8861
+ body: {
8862
+ agentOverride: opts.agent,
8863
+ agentModelOverride: opts.model,
8864
+ agentEffortOverride: opts.effort
8865
+ }
8866
+ }
8867
+ ) : null;
8868
+ ok(runner ?? row, () => {
8681
8869
  line(
8682
- `${import_picocolors28.default.green("added")} ${import_picocolors28.default.bold(row.title)} ${import_picocolors28.default.dim(row.key ?? row.id)}`
8870
+ `${import_picocolors29.default.green("added")} ${import_picocolors29.default.bold(row.title)} ${import_picocolors29.default.dim(row.key ?? row.id)}`
8683
8871
  );
8684
- if (row.role) line(import_picocolors28.default.dim(`role: ${row.role}`));
8872
+ if (row.role) line(import_picocolors29.default.dim(`role: ${row.role}`));
8873
+ if (runner) {
8874
+ line(
8875
+ import_picocolors29.default.dim(
8876
+ `runs on: ${[opts.agent, opts.model, opts.effort].filter(Boolean).join(" \xB7 ")}`
8877
+ )
8878
+ );
8879
+ }
8685
8880
  });
8686
8881
  })
8687
8882
  );
@@ -8695,17 +8890,30 @@ function registerTask(program3) {
8695
8890
  const rows = row.subtasks ?? [];
8696
8891
  ok(rows, () => {
8697
8892
  if (!rows.length) {
8698
- line(import_picocolors28.default.dim("No subtasks yet."));
8893
+ line(import_picocolors29.default.dim("No subtasks yet."));
8699
8894
  return;
8700
8895
  }
8701
8896
  rows.forEach((r, i) => line(formatSubtask(r, i + 1)));
8702
8897
  });
8703
8898
  })
8704
8899
  );
8705
- subtask.command("update <id>").description("Change a subtask \u2014 its title, its role, what it touches").option("--title <text>").option("--note <text>").option("--role <value>", ROLES.join(" | ")).option("--kind <value>", KINDS2.join(" | ")).option("--scope <path...>", "replaces the subtask's scope entirely").action(
8900
+ subtask.command("update <id>").description("Change a subtask \u2014 its title, its role, what it touches").option("--title <text>").option("--note <text>").option("--role <value>", ROLES.join(" | ")).option("--kind <value>", KINDS2.join(" | ")).option("--scope <path...>", "replaces the subtask's scope entirely").option(
8901
+ "--agent <id>",
8902
+ `run this step on a specific CLI (${AGENTS.join(" | ")}); "default" hands it back to the role's own`
8903
+ ).option("--model <id>", 'the model that CLI should use; "default" clears it').option(
8904
+ "--effort <level>",
8905
+ `how hard it thinks (${EFFORTS.join(" | ")}); "default" clears it`
8906
+ ).action(
8706
8907
  action(async ({ ctx, args, opts }) => {
8707
8908
  if (opts.role !== void 0) assertOneOf("--role", opts.role, ROLES);
8708
8909
  if (opts.kind !== void 0) assertOneOf("--kind", opts.kind, KINDS2);
8910
+ if (opts.agent !== void 0 && opts.agent !== "default")
8911
+ assertOneOf("--agent", opts.agent, AGENTS);
8912
+ if (opts.effort !== void 0 && opts.effort !== "default")
8913
+ assertOneOf("--effort", opts.effort, EFFORTS);
8914
+ if (opts.model !== "default")
8915
+ assertDelegatableModel("--model", opts.model);
8916
+ const clearable = (value) => value === void 0 ? void 0 : value === "default" ? null : value;
8709
8917
  const row = await api(
8710
8918
  ctx,
8711
8919
  `/v1/project-tasks/${encodeURIComponent(args[0])}`,
@@ -8716,11 +8924,14 @@ function registerTask(program3) {
8716
8924
  summary: opts.note,
8717
8925
  role: opts.role,
8718
8926
  category: opts.kind,
8719
- scopePaths: opts.scope
8927
+ scopePaths: opts.scope,
8928
+ agentOverride: clearable(opts.agent),
8929
+ agentModelOverride: clearable(opts.model),
8930
+ agentEffortOverride: clearable(opts.effort)
8720
8931
  }
8721
8932
  }
8722
8933
  );
8723
- ok(row, () => line(`${import_picocolors28.default.green("updated")} ${import_picocolors28.default.bold(row.title)}`));
8934
+ ok(row, () => line(`${import_picocolors29.default.green("updated")} ${import_picocolors29.default.bold(row.title)}`));
8724
8935
  })
8725
8936
  );
8726
8937
  subtask.command("remove <id>").description("Remove a subtask (only before the work starts)").action(
@@ -8728,7 +8939,7 @@ function registerTask(program3) {
8728
8939
  await api(ctx, `/v1/project-tasks/${encodeURIComponent(args[0])}`, {
8729
8940
  method: "DELETE"
8730
8941
  });
8731
- ok({ removed: args[0] }, () => line(import_picocolors28.default.green("removed")));
8942
+ ok({ removed: args[0] }, () => line(import_picocolors29.default.green("removed")));
8732
8943
  })
8733
8944
  );
8734
8945
  task.command("move <id> <status>").description(
@@ -8743,7 +8954,7 @@ function registerTask(program3) {
8743
8954
  );
8744
8955
  ok(
8745
8956
  row,
8746
- () => line(`${import_picocolors28.default.green("moved")} ${import_picocolors28.default.bold(row.title)} \u2192 ${args[1]}`)
8957
+ () => line(`${import_picocolors29.default.green("moved")} ${import_picocolors29.default.bold(row.title)} \u2192 ${args[1]}`)
8747
8958
  );
8748
8959
  })
8749
8960
  );
@@ -8759,18 +8970,18 @@ function registerTask(program3) {
8759
8970
  );
8760
8971
  ok(row, () => {
8761
8972
  if (!row?.queued) {
8762
- line(import_picocolors28.default.yellow("could not resume it \u2014 check the step id"));
8973
+ line(import_picocolors29.default.yellow("could not resume it \u2014 check the step id"));
8763
8974
  return;
8764
8975
  }
8765
8976
  const started = row.started ?? 0;
8766
8977
  if (started > 0) {
8767
8978
  line(
8768
- `${import_picocolors28.default.green("resumed")} \u2014 ${started} step${started === 1 ? "" : "s"} started`
8979
+ `${import_picocolors29.default.green("resumed")} \u2014 ${started} step${started === 1 ? "" : "s"} started`
8769
8980
  );
8770
8981
  return;
8771
8982
  }
8772
8983
  line(
8773
- `${import_picocolors28.default.green("resumed")} \u2014 it is queued, but nothing started yet. Check the plan is approved and that no step is blocking the rest.`
8984
+ `${import_picocolors29.default.green("resumed")} \u2014 it is queued, but nothing started yet. Check the plan is approved and that no step is blocking the rest.`
8774
8985
  );
8775
8986
  });
8776
8987
  })
@@ -8784,11 +8995,11 @@ function registerTask(program3) {
8784
8995
  );
8785
8996
  ok(row, () => {
8786
8997
  if (row?.reopened) {
8787
- line(`${import_picocolors28.default.green("sent back")} \u2014 it will be picked up again`);
8998
+ line(`${import_picocolors29.default.green("sent back")} \u2014 it will be picked up again`);
8788
8999
  return;
8789
9000
  }
8790
9001
  line(
8791
- import_picocolors28.default.yellow(
9002
+ import_picocolors29.default.yellow(
8792
9003
  row?.reason === "already_open" ? "already waiting to be picked up \u2014 nothing to send back" : row?.reason === "still_working" ? "still working \u2014 let it finish before sending it back" : "could not send that step back"
8793
9004
  )
8794
9005
  );
@@ -8805,7 +9016,7 @@ function registerTask(program3) {
8805
9016
  `/v1/project-tasks/${encodeURIComponent(id)}/dispatch-check`,
8806
9017
  { method: "POST" }
8807
9018
  );
8808
- ok(row, () => line(import_picocolors28.default.green("approved \u2014 you may start")));
9019
+ ok(row, () => line(import_picocolors29.default.green("approved \u2014 you may start")));
8809
9020
  })
8810
9021
  );
8811
9022
  task.command("start [id]").description(
@@ -8820,13 +9031,13 @@ function registerTask(program3) {
8820
9031
  const started = row?.started ?? null;
8821
9032
  if (started && started > 0) {
8822
9033
  line(
8823
- import_picocolors28.default.green(
9034
+ import_picocolors29.default.green(
8824
9035
  `started ${started} step${started === 1 ? "" : "s"} \u2014 they are running now`
8825
9036
  )
8826
9037
  );
8827
9038
  return;
8828
9039
  }
8829
- line(import_picocolors28.default.yellow(row?.note ?? "Nothing started."));
9040
+ line(import_picocolors29.default.yellow(row?.note ?? "Nothing started."));
8830
9041
  });
8831
9042
  })
8832
9043
  );
@@ -8841,7 +9052,7 @@ function registerTask(program3) {
8841
9052
  );
8842
9053
  ok({ awaiting: row2.approval_state === "awaiting", task: row2 }, () => {
8843
9054
  line(
8844
- row2.approval_state === "awaiting" ? import_picocolors28.default.yellow(
9055
+ row2.approval_state === "awaiting" ? import_picocolors29.default.yellow(
8845
9056
  "The plan is waiting on the owner. They see it in the task."
8846
9057
  ) : `Already ${row2.approval_state}.`
8847
9058
  );
@@ -8866,7 +9077,7 @@ function registerTask(program3) {
8866
9077
  );
8867
9078
  ok(
8868
9079
  row,
8869
- () => line(`${import_picocolors28.default.green(row.approval_state)} ${import_picocolors28.default.bold(row.title)}`)
9080
+ () => line(`${import_picocolors29.default.green(row.approval_state)} ${import_picocolors29.default.bold(row.title)}`)
8870
9081
  );
8871
9082
  })
8872
9083
  );
@@ -8882,7 +9093,7 @@ function registerTask(program3) {
8882
9093
  `/v1/project-tasks/${encodeURIComponent(id)}/move`,
8883
9094
  { body: { status: "ready" } }
8884
9095
  );
8885
- ok(row, () => line(`${import_picocolors28.default.green("ready")} ${import_picocolors28.default.bold(row.title)}`));
9096
+ ok(row, () => line(`${import_picocolors29.default.green("ready")} ${import_picocolors29.default.bold(row.title)}`));
8886
9097
  })
8887
9098
  );
8888
9099
  }
@@ -8927,24 +9138,24 @@ function assertOneOf(flag, value, allowed) {
8927
9138
  }
8928
9139
  }
8929
9140
  function formatRow2(r) {
8930
- const key = import_picocolors28.default.dim((r.key ?? r.id.slice(0, 8)).padEnd(10));
8931
- const steps = r.subtaskTotal ? import_picocolors28.default.dim(` ${r.subtaskDone}/${r.subtaskTotal}`) : "";
8932
- const gate = r.approval_state === "awaiting" ? import_picocolors28.default.yellow(" awaiting approval") : "";
9141
+ const key = import_picocolors29.default.dim((r.key ?? r.id.slice(0, 8)).padEnd(10));
9142
+ const steps = r.subtaskTotal ? import_picocolors29.default.dim(` ${r.subtaskDone}/${r.subtaskTotal}`) : "";
9143
+ const gate = r.approval_state === "awaiting" ? import_picocolors29.default.yellow(" awaiting approval") : "";
8933
9144
  return `${key} ${statusTag2(r.status)} ${r.title}${steps}${gate}`;
8934
9145
  }
8935
9146
  function formatSubtask(r, index) {
8936
- const n = import_picocolors28.default.dim(String(index).padStart(2, "0"));
8937
- const role = r.role ? import_picocolors28.default.dim(` [${r.role}]`) : "";
8938
- const scope = r.scope_paths?.length ? import_picocolors28.default.dim(` owns: ${r.scope_paths.join(", ")}`) : "";
9147
+ const n = import_picocolors29.default.dim(String(index).padStart(2, "0"));
9148
+ const role = r.role ? import_picocolors29.default.dim(` [${r.role}]`) : "";
9149
+ const scope = r.scope_paths?.length ? import_picocolors29.default.dim(` owns: ${r.scope_paths.join(", ")}`) : "";
8939
9150
  const head = `${n} ${statusTag2(r.status)} ${r.title}${role}${scope}`;
8940
9151
  const summary = (r.result_summary ?? "").trim();
8941
9152
  if (!summary) return head;
8942
9153
  const wrapped = summary.split("\n").map((l) => ` ${l}`).join("\n");
8943
9154
  return `${head}
8944
- ${import_picocolors28.default.dim(wrapped)}`;
9155
+ ${import_picocolors29.default.dim(wrapped)}`;
8945
9156
  }
8946
9157
  function printTask(row, goal) {
8947
- line(`${import_picocolors28.default.bold(row.title)} ${import_picocolors28.default.dim(row.key ?? row.id)}`);
9158
+ line(`${import_picocolors29.default.bold(row.title)} ${import_picocolors29.default.dim(row.key ?? row.id)}`);
8948
9159
  line(`${statusTag2(row.status)} approval: ${row.approval_state}`);
8949
9160
  if (row.summary) line(`
8950
9161
  ${row.summary}`);
@@ -8957,53 +9168,53 @@ touches: ${row.targets.map((t) => t.appName ?? t.ref ?? t.kind).join(", ")}`
8957
9168
  }
8958
9169
  if (row.subtasks?.length) {
8959
9170
  line(`
8960
- ${import_picocolors28.default.bold("subtasks")}`);
9171
+ ${import_picocolors29.default.bold("subtasks")}`);
8961
9172
  row.subtasks.forEach((s, i) => line(formatSubtask(s, i + 1)));
8962
9173
  line(
8963
- import_picocolors28.default.dim(
9174
+ import_picocolors29.default.dim(
8964
9175
  `
8965
9176
  Run \`workser artifact list\` to see what these subtasks produced,`
8966
9177
  )
8967
9178
  );
8968
9179
  line(
8969
- import_picocolors28.default.dim(
9180
+ import_picocolors29.default.dim(
8970
9181
  `or \`workser artifact list --step <id>\` for one subtask's output alone.`
8971
9182
  )
8972
9183
  );
8973
9184
  } else {
8974
- line(import_picocolors28.default.dim("\nNo subtasks yet."));
9185
+ line(import_picocolors29.default.dim("\nNo subtasks yet."));
8975
9186
  }
8976
9187
  }
8977
9188
  function printGoalContext(row, goal) {
8978
9189
  const mine = row.phase ?? null;
8979
9190
  line(`
8980
- ${import_picocolors28.default.bold("part of")}: ${goal.title}`);
8981
- if (goal.outcome) line(import_picocolors28.default.dim(`done means: ${goal.outcome}`));
9191
+ ${import_picocolors29.default.bold("part of")}: ${goal.title}`);
9192
+ if (goal.outcome) line(import_picocolors29.default.dim(`done means: ${goal.outcome}`));
8982
9193
  const progress = goal.progress ?? [];
8983
9194
  for (const p of progress) {
8984
9195
  const where = p.total === 0 ? "not started" : `${p.done} of ${p.total} done`;
8985
- const here = mine && p.name === mine ? import_picocolors28.default.cyan(" <- this task") : "";
8986
- const mark = p.state === "done" ? import_picocolors28.default.green("*") : import_picocolors28.default.dim("-");
9196
+ const here = mine && p.name === mine ? import_picocolors29.default.cyan(" <- this task") : "";
9197
+ const mark = p.state === "done" ? import_picocolors29.default.green("*") : import_picocolors29.default.dim("-");
8987
9198
  line(` ${mark} ${p.name} \u2014 ${where}${here}`);
8988
9199
  }
8989
9200
  const next = progress.find((p) => p.state !== "done");
8990
9201
  const running = progress.some((p) => p.state === "working");
8991
9202
  if (next && !running) {
8992
9203
  line(
8993
- import_picocolors28.default.dim(
9204
+ import_picocolors29.default.dim(
8994
9205
  `
8995
9206
  Nothing is running. The next part waiting is "${next.name}" \u2014 offer it to them in a sentence rather than starting it unasked.`
8996
9207
  )
8997
9208
  );
8998
9209
  } else if (!next) {
8999
9210
  line(
9000
- import_picocolors28.default.dim(
9211
+ import_picocolors29.default.dim(
9001
9212
  "\nEvery part of this plan is done. Say so, and offer to wrap it up."
9002
9213
  )
9003
9214
  );
9004
9215
  }
9005
9216
  line(
9006
- import_picocolors28.default.dim(
9217
+ import_picocolors29.default.dim(
9007
9218
  "The plan is a reference for what was agreed, not a rule about what may run. Work can start on any part at any time if they ask for it."
9008
9219
  )
9009
9220
  );
@@ -9011,22 +9222,22 @@ Nothing is running. The next part waiting is "${next.name}" \u2014 offer it to t
9011
9222
  function statusTag2(status) {
9012
9223
  switch (status) {
9013
9224
  case "ready":
9014
- return import_picocolors28.default.green("[ready]");
9225
+ return import_picocolors29.default.green("[ready]");
9015
9226
  case "working":
9016
- return import_picocolors28.default.blue("[working]");
9227
+ return import_picocolors29.default.blue("[working]");
9017
9228
  case "checking":
9018
- return import_picocolors28.default.cyan("[checking]");
9229
+ return import_picocolors29.default.cyan("[checking]");
9019
9230
  case "accepted":
9020
- return import_picocolors28.default.green("[accepted]");
9231
+ return import_picocolors29.default.green("[accepted]");
9021
9232
  case "archived":
9022
- return import_picocolors28.default.dim("[archived]");
9233
+ return import_picocolors29.default.dim("[archived]");
9023
9234
  default:
9024
- return import_picocolors28.default.dim("[todo]");
9235
+ return import_picocolors29.default.dim("[todo]");
9025
9236
  }
9026
9237
  }
9027
9238
 
9028
9239
  // src/commands/goal.ts
9029
- var import_picocolors29 = __toESM(require_picocolors(), 1);
9240
+ var import_picocolors30 = __toESM(require_picocolors(), 1);
9030
9241
  var STATUSES3 = ["proposed", "agreed", "working", "delivered", "abandoned"];
9031
9242
  function registerGoal(program3) {
9032
9243
  const goal = program3.command("goal").description("Business goals and the phases that deliver them");
@@ -9038,7 +9249,7 @@ function registerGoal(program3) {
9038
9249
  }) ?? [];
9039
9250
  ok(rows, () => {
9040
9251
  if (!rows.length) {
9041
- line(import_picocolors29.default.dim("No goals yet \u2014 every task here stands on its own."));
9252
+ line(import_picocolors30.default.dim("No goals yet \u2014 every task here stands on its own."));
9042
9253
  return;
9043
9254
  }
9044
9255
  for (const g of rows) line(formatGoal(g));
@@ -9115,10 +9326,10 @@ function registerGoal(program3) {
9115
9326
  }
9116
9327
  });
9117
9328
  ok(row, () => {
9118
- success(`Proposed ${import_picocolors29.default.bold(row?.title ?? "goal")}`);
9329
+ success(`Proposed ${import_picocolors30.default.bold(row?.title ?? "goal")}`);
9119
9330
  printGoal(row);
9120
9331
  line(
9121
- import_picocolors29.default.dim(
9332
+ import_picocolors30.default.dim(
9122
9333
  "\nNothing has been created yet. The owner agrees the shape first."
9123
9334
  )
9124
9335
  );
@@ -9147,7 +9358,7 @@ function registerGoal(program3) {
9147
9358
  ok(
9148
9359
  row,
9149
9360
  () => line(
9150
- row?.recorded ? met === true ? import_picocolors29.default.green("recorded \u2014 met") : met === false ? import_picocolors29.default.yellow("recorded \u2014 not met") : import_picocolors29.default.dim("recorded \u2014 back to unchecked") : import_picocolors29.default.yellow(
9361
+ row?.recorded ? met === true ? import_picocolors30.default.green("recorded \u2014 met") : met === false ? import_picocolors30.default.yellow("recorded \u2014 not met") : import_picocolors30.default.dim("recorded \u2014 back to unchecked") : import_picocolors30.default.yellow(
9151
9362
  "couldn't record it \u2014 check the goal id, the phase name and the criterion id"
9152
9363
  )
9153
9364
  )
@@ -9181,42 +9392,42 @@ function registerGoal(program3) {
9181
9392
  function appScope(g) {
9182
9393
  const n = g.appIds?.length ?? 0;
9183
9394
  if (!n) return "";
9184
- return import_picocolors29.default.dim(` ${n} part${n === 1 ? "" : "s"} of the system`);
9395
+ return import_picocolors30.default.dim(` ${n} part${n === 1 ? "" : "s"} of the system`);
9185
9396
  }
9186
9397
  function formatGoal(g) {
9187
- const where = g.currentPhase && g.status !== "delivered" ? import_picocolors29.default.dim(` now: ${g.currentPhase}`) : "";
9188
- const count = g.taskTotal != null ? import_picocolors29.default.dim(` ${g.taskDone}/${g.taskTotal} done`) : "";
9189
- return `${statusTag3(g.status)} ${g.title}${appScope(g)}${where}${count} ${import_picocolors29.default.dim(g.id)}`;
9398
+ const where = g.currentPhase && g.status !== "delivered" ? import_picocolors30.default.dim(` now: ${g.currentPhase}`) : "";
9399
+ const count = g.taskTotal != null ? import_picocolors30.default.dim(` ${g.taskDone}/${g.taskTotal} done`) : "";
9400
+ return `${statusTag3(g.status)} ${g.title}${appScope(g)}${where}${count} ${import_picocolors30.default.dim(g.id)}`;
9190
9401
  }
9191
9402
  function printGoal(g) {
9192
9403
  if (!g) return;
9193
- line(`${import_picocolors29.default.bold(g.title)} ${import_picocolors29.default.dim(g.id)}`);
9404
+ line(`${import_picocolors30.default.bold(g.title)} ${import_picocolors30.default.dim(g.id)}`);
9194
9405
  line(statusTag3(g.status));
9195
9406
  if (g.outcome) line(`
9196
9407
  done means: ${g.outcome}`);
9197
9408
  const progress = g.progress ?? [];
9198
9409
  if (!progress.length) {
9199
- line(import_picocolors29.default.dim("\nNo phases agreed yet."));
9410
+ line(import_picocolors30.default.dim("\nNo phases agreed yet."));
9200
9411
  return;
9201
9412
  }
9202
9413
  line(`
9203
- ${import_picocolors29.default.bold("phases")}`);
9414
+ ${import_picocolors30.default.bold("phases")}`);
9204
9415
  for (const p of progress) {
9205
- const bar2 = p.total > 0 ? `${p.done}/${p.total} done` : import_picocolors29.default.dim("nothing filed yet");
9206
- const mark = p.state === "done" ? import_picocolors29.default.green("done") : p.state === "working" ? import_picocolors29.default.blue("working") : import_picocolors29.default.dim("waiting");
9416
+ const bar2 = p.total > 0 ? `${p.done}/${p.total} done` : import_picocolors30.default.dim("nothing filed yet");
9417
+ const mark = p.state === "done" ? import_picocolors30.default.green("done") : p.state === "working" ? import_picocolors30.default.blue("working") : import_picocolors30.default.dim("waiting");
9207
9418
  line(
9208
- ` ${import_picocolors29.default.dim(String(p.index).padStart(2, "0"))} ${p.name} ${mark} ${import_picocolors29.default.dim(bar2)}`
9419
+ ` ${import_picocolors30.default.dim(String(p.index).padStart(2, "0"))} ${p.name} ${mark} ${import_picocolors30.default.dim(bar2)}`
9209
9420
  );
9210
9421
  for (const c of p.criteria ?? []) {
9211
- const tick = c.met === true ? import_picocolors29.default.green("\u2713") : c.met === false ? import_picocolors29.default.red("\u2717") : import_picocolors29.default.dim("\xB7");
9212
- line(` ${tick} ${c.text} ${import_picocolors29.default.dim(c.id)}`);
9213
- if (c.note) line(import_picocolors29.default.dim(` ${c.note}`));
9422
+ const tick = c.met === true ? import_picocolors30.default.green("\u2713") : c.met === false ? import_picocolors30.default.red("\u2717") : import_picocolors30.default.dim("\xB7");
9423
+ line(` ${tick} ${c.text} ${import_picocolors30.default.dim(c.id)}`);
9424
+ if (c.note) line(import_picocolors30.default.dim(` ${c.note}`));
9214
9425
  }
9215
9426
  }
9216
9427
  const current = progress.find((p) => p.name === g.currentPhase);
9217
9428
  if (current) {
9218
9429
  line(
9219
- import_picocolors29.default.dim(
9430
+ import_picocolors30.default.dim(
9220
9431
  `
9221
9432
  ${current.name} \u2014 ${current.done} of ${current.total} done (phase ${current.index} of ${progress.length}).`
9222
9433
  )
@@ -9226,15 +9437,15 @@ ${current.name} \u2014 ${current.done} of ${current.total} done (phase ${current
9226
9437
  function statusTag3(status) {
9227
9438
  switch (status) {
9228
9439
  case "agreed":
9229
- return import_picocolors29.default.cyan("[agreed]");
9440
+ return import_picocolors30.default.cyan("[agreed]");
9230
9441
  case "working":
9231
- return import_picocolors29.default.blue("[working]");
9442
+ return import_picocolors30.default.blue("[working]");
9232
9443
  case "delivered":
9233
- return import_picocolors29.default.green("[delivered]");
9444
+ return import_picocolors30.default.green("[delivered]");
9234
9445
  case "abandoned":
9235
- return import_picocolors29.default.dim("[abandoned]");
9446
+ return import_picocolors30.default.dim("[abandoned]");
9236
9447
  default:
9237
- return import_picocolors29.default.yellow("[proposed]");
9448
+ return import_picocolors30.default.yellow("[proposed]");
9238
9449
  }
9239
9450
  }
9240
9451
 
@@ -9409,7 +9620,7 @@ function stripLeadingGlobalOptions(argv) {
9409
9620
  }
9410
9621
 
9411
9622
  // src/commands/decision.ts
9412
- var import_picocolors30 = __toESM(require_picocolors(), 1);
9623
+ var import_picocolors31 = __toESM(require_picocolors(), 1);
9413
9624
  function registerDecision(program3) {
9414
9625
  const decision = program3.command("decision").description("Read and record the project's architecture decisions");
9415
9626
  decision.command("list").description("Every decision on record \u2014 read this before changing how something works").option("--limit <n>", "cap the number returned (newest first)").action(
@@ -9422,11 +9633,11 @@ function registerDecision(program3) {
9422
9633
  rows = applyLimit(rows, opts.limit);
9423
9634
  ok(rows, () => {
9424
9635
  if (!rows.length) {
9425
- line(import_picocolors30.default.dim("No decisions recorded yet."));
9636
+ line(import_picocolors31.default.dim("No decisions recorded yet."));
9426
9637
  return;
9427
9638
  }
9428
9639
  for (const r of rows) {
9429
- line(`${import_picocolors30.default.dim(r.id)} ${import_picocolors30.default.dim(shortDate(r.createdAt))} ${r.title}`);
9640
+ line(`${import_picocolors31.default.dim(r.id)} ${import_picocolors31.default.dim(shortDate(r.createdAt))} ${r.title}`);
9430
9641
  line(` ${truncate(r.decision, 100)}`);
9431
9642
  }
9432
9643
  });
@@ -9440,16 +9651,16 @@ function registerDecision(program3) {
9440
9651
  `/v1/projects/${projectId}/architecture-decisions/${args[0]}`
9441
9652
  );
9442
9653
  ok(row, () => {
9443
- line(`${import_picocolors30.default.bold(row.title)} ${import_picocolors30.default.dim(row.id)}`);
9444
- line(import_picocolors30.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
9654
+ line(`${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.id)}`);
9655
+ line(import_picocolors31.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
9445
9656
  line(`
9446
- ${import_picocolors30.default.bold("Context")}
9657
+ ${import_picocolors31.default.bold("Context")}
9447
9658
  ${row.context}`);
9448
9659
  line(`
9449
- ${import_picocolors30.default.bold("Decision")}
9660
+ ${import_picocolors31.default.bold("Decision")}
9450
9661
  ${row.decision}`);
9451
9662
  if (row.consequences) line(`
9452
- ${import_picocolors30.default.bold("Consequences")}
9663
+ ${import_picocolors31.default.bold("Consequences")}
9453
9664
  ${row.consequences}`);
9454
9665
  });
9455
9666
  })
@@ -9478,7 +9689,7 @@ ${row.consequences}`);
9478
9689
  refId: row?.id,
9479
9690
  output: { decision: row }
9480
9691
  });
9481
- ok(row, () => line(`Recorded decision ${import_picocolors30.default.bold(row?.id ?? "")} \u2014 ${title}`));
9692
+ ok(row, () => line(`Recorded decision ${import_picocolors31.default.bold(row?.id ?? "")} \u2014 ${title}`));
9482
9693
  })
9483
9694
  );
9484
9695
  const requirement = program3.command("requirement").description("Read and record the project's requirements");
@@ -9490,11 +9701,11 @@ ${row.consequences}`);
9490
9701
  rows = applyLimit(rows, opts.limit);
9491
9702
  ok(rows, () => {
9492
9703
  if (!rows.length) {
9493
- line(import_picocolors30.default.dim("No requirements recorded yet."));
9704
+ line(import_picocolors31.default.dim("No requirements recorded yet."));
9494
9705
  return;
9495
9706
  }
9496
9707
  for (const r of rows) {
9497
- line(`${import_picocolors30.default.dim(r.id)} ${r.status.padEnd(9)} ${r.title}`);
9708
+ line(`${import_picocolors31.default.dim(r.id)} ${r.status.padEnd(9)} ${r.title}`);
9498
9709
  }
9499
9710
  });
9500
9711
  })
@@ -9507,8 +9718,8 @@ ${row.consequences}`);
9507
9718
  `/v1/projects/${projectId}/requirements/${args[0]}`
9508
9719
  );
9509
9720
  ok(row, () => {
9510
- line(`${import_picocolors30.default.bold(row.title)} ${import_picocolors30.default.dim(row.id)}`);
9511
- line(import_picocolors30.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
9721
+ line(`${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.id)}`);
9722
+ line(import_picocolors31.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
9512
9723
  line(`
9513
9724
  ${row.body}`);
9514
9725
  });
@@ -9534,7 +9745,7 @@ ${row.body}`);
9534
9745
  refId: row?.id,
9535
9746
  output: { requirement: row }
9536
9747
  });
9537
- ok(row, () => line(`Recorded requirement ${import_picocolors30.default.bold(row?.id ?? "")} \u2014 ${title}`));
9748
+ ok(row, () => line(`Recorded requirement ${import_picocolors31.default.bold(row?.id ?? "")} \u2014 ${title}`));
9538
9749
  })
9539
9750
  );
9540
9751
  requirement.command("update <id>").description(
@@ -9563,7 +9774,7 @@ ${row.body}`);
9563
9774
  code: "bad_request"
9564
9775
  });
9565
9776
  }
9566
- ok(row, () => line(`Updated requirement ${import_picocolors30.default.bold(row.id)} \u2014 ${row.title} (${row.status})`));
9777
+ ok(row, () => line(`Updated requirement ${import_picocolors31.default.bold(row.id)} \u2014 ${row.title} (${row.status})`));
9567
9778
  })
9568
9779
  );
9569
9780
  }
@@ -9586,7 +9797,7 @@ function shortDate(iso) {
9586
9797
  }
9587
9798
 
9588
9799
  // src/commands/doc.ts
9589
- var import_picocolors31 = __toESM(require_picocolors(), 1);
9800
+ var import_picocolors32 = __toESM(require_picocolors(), 1);
9590
9801
 
9591
9802
  // src/mermaid-fences.ts
9592
9803
  function hasDiagram(code) {
@@ -9631,13 +9842,13 @@ function registerDoc(program3) {
9631
9842
  }) ?? [];
9632
9843
  ok(rows, () => {
9633
9844
  if (!rows.length) {
9634
- line(import_picocolors31.default.dim("No documents yet."));
9845
+ line(import_picocolors32.default.dim("No documents yet."));
9635
9846
  return;
9636
9847
  }
9637
9848
  for (const r of rows) {
9638
- const link = r.workItemId ? import_picocolors31.default.dim(` \u21B3 ${r.workItemId}`) : "";
9639
- const file = r.filePath ? import_picocolors31.default.dim(` ${r.filePath}`) : "";
9640
- line(`${import_picocolors31.default.dim(r.id)} ${r.title}${link}${file}`);
9849
+ const link = r.workItemId ? import_picocolors32.default.dim(` \u21B3 ${r.workItemId}`) : "";
9850
+ const file = r.filePath ? import_picocolors32.default.dim(` ${r.filePath}`) : "";
9851
+ line(`${import_picocolors32.default.dim(r.id)} ${r.title}${link}${file}`);
9641
9852
  }
9642
9853
  });
9643
9854
  })
@@ -9651,17 +9862,17 @@ function registerDoc(program3) {
9651
9862
  );
9652
9863
  if (opts.markdown) {
9653
9864
  ok({ id: row.id, title: row.title, filePath: row.filePath }, () => {
9654
- line(`${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.id)}`);
9865
+ line(`${import_picocolors32.default.bold(row.title)} ${import_picocolors32.default.dim(row.id)}`);
9655
9866
  line(
9656
- row.filePath ? `Read it at ${import_picocolors31.default.bold(row.filePath)} (relative to the project folder).` : import_picocolors31.default.dim("This document has no markdown mirror on disk yet.")
9867
+ row.filePath ? `Read it at ${import_picocolors32.default.bold(row.filePath)} (relative to the project folder).` : import_picocolors32.default.dim("This document has no markdown mirror on disk yet.")
9657
9868
  );
9658
9869
  });
9659
9870
  return;
9660
9871
  }
9661
9872
  ok(row, () => {
9662
- line(`${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.id)}`);
9663
- if (row.workItemId) line(import_picocolors31.default.dim(`linked to work item ${row.workItemId}`));
9664
- if (row.filePath) line(import_picocolors31.default.dim(`markdown mirror: ${row.filePath}`));
9873
+ line(`${import_picocolors32.default.bold(row.title)} ${import_picocolors32.default.dim(row.id)}`);
9874
+ if (row.workItemId) line(import_picocolors32.default.dim(`linked to work item ${row.workItemId}`));
9875
+ if (row.filePath) line(import_picocolors32.default.dim(`markdown mirror: ${row.filePath}`));
9665
9876
  line("");
9666
9877
  line(row.contentJson);
9667
9878
  });
@@ -9690,7 +9901,7 @@ function registerDoc(program3) {
9690
9901
  refId: row?.id,
9691
9902
  output: { document: row }
9692
9903
  });
9693
- ok(row, () => line(`Created document ${import_picocolors31.default.bold(row?.id ?? "")} \u2014 ${title}`));
9904
+ ok(row, () => line(`Created document ${import_picocolors32.default.bold(row?.id ?? "")} \u2014 ${title}`));
9694
9905
  })
9695
9906
  );
9696
9907
  doc.command("diagram <id>").description(
@@ -9716,19 +9927,19 @@ function registerDoc(program3) {
9716
9927
  diagrams: diagrams.map((code) => ({ kind: diagramKind(code), code }))
9717
9928
  };
9718
9929
  ok(payload, () => {
9719
- line(`${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.id)}`);
9930
+ line(`${import_picocolors32.default.bold(row.title)} ${import_picocolors32.default.dim(row.id)}`);
9720
9931
  if (markdown === null) {
9721
9932
  line(
9722
- import_picocolors31.default.dim(
9933
+ import_picocolors32.default.dim(
9723
9934
  row.filePath ? `Could not read ${row.filePath} from this folder.` : "This document has no markdown mirror on disk yet."
9724
9935
  )
9725
9936
  );
9726
9937
  } else if (!diagrams.length) {
9727
- line(import_picocolors31.default.dim("No diagrams in this document."));
9938
+ line(import_picocolors32.default.dim("No diagrams in this document."));
9728
9939
  } else {
9729
9940
  for (const [i, code] of diagrams.entries()) {
9730
9941
  const kind = diagramKind(code) ?? "diagram";
9731
- line(`${import_picocolors31.default.dim(String(i + 1))} ${kind} ${import_picocolors31.default.dim(`${code.split("\n").length} lines`)}`);
9942
+ line(`${import_picocolors32.default.dim(String(i + 1))} ${kind} ${import_picocolors32.default.dim(`${code.split("\n").length} lines`)}`);
9732
9943
  }
9733
9944
  }
9734
9945
  });
@@ -9764,7 +9975,7 @@ function registerDoc(program3) {
9764
9975
  code: "bad_request"
9765
9976
  });
9766
9977
  }
9767
- ok(row, () => line(`Updated document ${import_picocolors31.default.bold(row.id)} \u2014 ${row.title}`));
9978
+ ok(row, () => line(`Updated document ${import_picocolors32.default.bold(row.id)} \u2014 ${row.title}`));
9768
9979
  })
9769
9980
  );
9770
9981
  }
@@ -9778,7 +9989,7 @@ function readMirror(cwd, filePath) {
9778
9989
  }
9779
9990
 
9780
9991
  // src/commands/design.ts
9781
- var import_picocolors32 = __toESM(require_picocolors(), 1);
9992
+ var import_picocolors33 = __toESM(require_picocolors(), 1);
9782
9993
  function registerDesign(program3) {
9783
9994
  const design = program3.command("design").description("Read the project's brand (colours, fonts, logo)");
9784
9995
  design.command("show").description("Show this project's brand \u2014 read it before writing any UI").option("--raw", "print the generated token files verbatim instead of a summary").action(
@@ -9792,11 +10003,11 @@ function registerDesign(program3) {
9792
10003
  if (opts.raw) {
9793
10004
  ok(files, () => {
9794
10005
  if (!files.length) {
9795
- line(import_picocolors32.default.dim("No brand set for this project."));
10006
+ line(import_picocolors33.default.dim("No brand set for this project."));
9796
10007
  return;
9797
10008
  }
9798
10009
  for (const f of files) {
9799
- line(import_picocolors32.default.bold(f.path));
10010
+ line(import_picocolors33.default.bold(f.path));
9800
10011
  line(f.contents);
9801
10012
  line("");
9802
10013
  }
@@ -9813,21 +10024,21 @@ function registerDesign(program3) {
9813
10024
  } : { hasBrand: false, colors: {}, fonts: {}, brand: {}, files: [] };
9814
10025
  ok(summary, () => {
9815
10026
  if (!tokens) {
9816
- line(import_picocolors32.default.dim("No brand set for this project \u2014 choose sensible styling yourself."));
10027
+ line(import_picocolors33.default.dim("No brand set for this project \u2014 choose sensible styling yourself."));
9817
10028
  return;
9818
10029
  }
9819
10030
  for (const [name, value] of Object.entries(tokens.brand)) {
9820
- line(`${import_picocolors32.default.dim(name.padEnd(12))} ${value}`);
10031
+ line(`${import_picocolors33.default.dim(name.padEnd(12))} ${value}`);
9821
10032
  }
9822
10033
  for (const [name, value] of Object.entries(tokens.color)) {
9823
- line(`${import_picocolors32.default.dim(`color.${name}`.padEnd(12))} ${value}`);
10034
+ line(`${import_picocolors33.default.dim(`color.${name}`.padEnd(12))} ${value}`);
9824
10035
  }
9825
10036
  for (const [name, value] of Object.entries(tokens.font)) {
9826
- line(`${import_picocolors32.default.dim(`font.${name}`.padEnd(12))} ${value}`);
10037
+ line(`${import_picocolors33.default.dim(`font.${name}`.padEnd(12))} ${value}`);
9827
10038
  }
9828
10039
  line("");
9829
10040
  line(
9830
- import_picocolors32.default.dim(
10041
+ import_picocolors33.default.dim(
9831
10042
  `Generated into the working tree as ${files.map((f) => f.path).join(", ")} \u2014 wire those in, never edit them.`
9832
10043
  )
9833
10044
  );
@@ -9858,7 +10069,7 @@ function unwrap(group) {
9858
10069
  }
9859
10070
 
9860
10071
  // src/commands/api.ts
9861
- var import_picocolors33 = __toESM(require_picocolors(), 1);
10072
+ var import_picocolors34 = __toESM(require_picocolors(), 1);
9862
10073
  import { readdirSync, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
9863
10074
  import { join as join3, relative, sep } from "path";
9864
10075
 
@@ -9969,13 +10180,13 @@ function registerApi(program3) {
9969
10180
  const cmd = program3.command("api").description("Call this service and check it describes its own routes");
9970
10181
  cmd.command("list").description("The requests saved with this service, in api/requests.json").option("--app <webAppId>", "the service, when this folder holds more than one").action(
9971
10182
  action(async ({ ctx, opts }) => {
9972
- const appId = requireApp(opts.app);
10183
+ const appId = requireApp2(opts.app);
9973
10184
  const res = await api(ctx, `/v1/apps/${encodeURIComponent(appId)}/api/requests`);
9974
10185
  ok(res, () => {
9975
- for (const note of res?.notes ?? []) line(import_picocolors33.default.dim(note));
10186
+ for (const note of res?.notes ?? []) line(import_picocolors34.default.dim(note));
9976
10187
  for (const r of res?.requests ?? []) {
9977
10188
  line(
9978
- `${import_picocolors33.default.dim(r.method.padEnd(6))}${r.path}${r.note ? import_picocolors33.default.dim(` ${r.note}`) : ""}`
10189
+ `${import_picocolors34.default.dim(r.method.padEnd(6))}${r.path}${r.note ? import_picocolors34.default.dim(` ${r.note}`) : ""}`
9979
10190
  );
9980
10191
  }
9981
10192
  });
@@ -9993,7 +10204,7 @@ function registerApi(program3) {
9993
10204
  "local (default), preview or production \u2014 the host comes from here, never from the path"
9994
10205
  ).action(
9995
10206
  action(async ({ ctx, args, opts }) => {
9996
- const appId = requireApp(opts.app);
10207
+ const appId = requireApp2(opts.app);
9997
10208
  const res = await api(
9998
10209
  ctx,
9999
10210
  `/v1/apps/${encodeURIComponent(appId)}/api/call`,
@@ -10009,14 +10220,14 @@ function registerApi(program3) {
10009
10220
  );
10010
10221
  ok(res, () => {
10011
10222
  if (!res?.ok) {
10012
- line(import_picocolors33.default.red(res?.error ?? "The service did not answer."));
10223
+ line(import_picocolors34.default.red(res?.error ?? "The service did not answer."));
10013
10224
  return;
10014
10225
  }
10015
10226
  const code = `${res.status}${res.statusText ? ` ${res.statusText}` : ""}`;
10016
- const colour2 = res.status && res.status < 300 ? import_picocolors33.default.green : res.status && res.status < 500 ? import_picocolors33.default.yellow : import_picocolors33.default.red;
10017
- line(`${colour2(code)} ${import_picocolors33.default.dim(`${res.durationMs}ms ${res.url}`)}`);
10227
+ const colour2 = res.status && res.status < 300 ? import_picocolors34.default.green : res.status && res.status < 500 ? import_picocolors34.default.yellow : import_picocolors34.default.red;
10228
+ line(`${colour2(code)} ${import_picocolors34.default.dim(`${res.durationMs}ms ${res.url}`)}`);
10018
10229
  if (res.body) line(res.body);
10019
- if (res.truncated) line(import_picocolors33.default.dim("(answer truncated)"));
10230
+ if (res.truncated) line(import_picocolors34.default.dim("(answer truncated)"));
10020
10231
  });
10021
10232
  if (!res?.ok) process.exitCode = 1;
10022
10233
  })
@@ -10036,15 +10247,15 @@ function registerApi(program3) {
10036
10247
  for (const r of report.routes) {
10037
10248
  const known = report.missing.some((m) => m.path === r.path);
10038
10249
  line(
10039
- `${known ? import_picocolors33.default.yellow("undocumented") : import_picocolors33.default.green("documented ")} ${r.path}${import_picocolors33.default.dim(` ${r.file}`)}`
10250
+ `${known ? import_picocolors34.default.yellow("undocumented") : import_picocolors34.default.green("documented ")} ${r.path}${import_picocolors34.default.dim(` ${r.file}`)}`
10040
10251
  );
10041
10252
  }
10042
10253
  for (const p of report.stale) {
10043
- line(`${import_picocolors33.default.dim("in spec only ")} ${p}`);
10254
+ line(`${import_picocolors34.default.dim("in spec only ")} ${p}`);
10044
10255
  }
10045
10256
  line("");
10046
10257
  if (report.ok && specFile) success(summary);
10047
- else line(import_picocolors33.default.yellow(summary));
10258
+ else line(import_picocolors34.default.yellow(summary));
10048
10259
  });
10049
10260
  if (opts.check && !report.ok) {
10050
10261
  throw new WorkserError(summary, { code: "bad_request" });
@@ -10060,7 +10271,7 @@ function collectHeader(raw, previous) {
10060
10271
  if (at <= 0) return previous;
10061
10272
  return { ...previous, [raw.slice(0, at).trim()]: raw.slice(at + 1).trim() };
10062
10273
  }
10063
- function requireApp(app) {
10274
+ function requireApp2(app) {
10064
10275
  const value = typeof app === "string" ? app.trim() : "";
10065
10276
  if (value) return value;
10066
10277
  throw new WorkserError(
@@ -10115,7 +10326,7 @@ function listRepoFiles(root, maxDepth = 8) {
10115
10326
  }
10116
10327
 
10117
10328
  // src/commands/analysis.ts
10118
- var import_picocolors34 = __toESM(require_picocolors(), 1);
10329
+ var import_picocolors35 = __toESM(require_picocolors(), 1);
10119
10330
  import { readFileSync as readFileSync4 } from "fs";
10120
10331
  function registerAnalysis(program3) {
10121
10332
  const cmd = program3.command("analysis").description("Run Python analysis locally, recorded in the task");
@@ -10125,14 +10336,14 @@ function registerAnalysis(program3) {
10125
10336
  const res = await api(ctx, path);
10126
10337
  ok(res, () => {
10127
10338
  line(
10128
- `${res?.available ? import_picocolors34.default.green("python") : import_picocolors34.default.red("python")} ${res?.version ?? "not found"} ${import_picocolors34.default.dim(res?.python ?? "")}`
10339
+ `${res?.available ? import_picocolors35.default.green("python") : import_picocolors35.default.red("python")} ${res?.version ?? "not found"} ${import_picocolors35.default.dim(res?.python ?? "")}`
10129
10340
  );
10130
10341
  for (const lib of res?.libraries ?? []) {
10131
10342
  line(
10132
- `${lib.present ? import_picocolors34.default.green(lib.name) : import_picocolors34.default.yellow(lib.name)}${import_picocolors34.default.dim(lib.present ? "" : " missing")}`
10343
+ `${lib.present ? import_picocolors35.default.green(lib.name) : import_picocolors35.default.yellow(lib.name)}${import_picocolors35.default.dim(lib.present ? "" : " missing")}`
10133
10344
  );
10134
10345
  }
10135
- for (const note of res?.notes ?? []) line(import_picocolors34.default.dim(note));
10346
+ for (const note of res?.notes ?? []) line(import_picocolors35.default.dim(note));
10136
10347
  });
10137
10348
  if (!res?.available) process.exitCode = 1;
10138
10349
  })
@@ -10154,15 +10365,15 @@ function registerAnalysis(program3) {
10154
10365
  );
10155
10366
  ok(res, () => {
10156
10367
  if (res?.stdout) line(res.stdout.replace(/\n$/, ""));
10157
- if (res?.stderr) line(import_picocolors34.default.dim(res.stderr.replace(/\n$/, "")));
10158
- if (res?.truncated) line(import_picocolors34.default.dim("(output truncated)"));
10368
+ if (res?.stderr) line(import_picocolors35.default.dim(res.stderr.replace(/\n$/, "")));
10369
+ if (res?.truncated) line(import_picocolors35.default.dim("(output truncated)"));
10159
10370
  const took = `${Math.round((res?.durationMs ?? 0) / 100) / 10}s`;
10160
10371
  line(
10161
- res?.ok ? import_picocolors34.default.green(`\u2713 ${res.summary ?? "It finished."}`) + import_picocolors34.default.dim(` ${took}`) : import_picocolors34.default.yellow(res?.summary ?? "It did not finish.") + import_picocolors34.default.dim(` ${took}`)
10372
+ res?.ok ? import_picocolors35.default.green(`\u2713 ${res.summary ?? "It finished."}`) + import_picocolors35.default.dim(` ${took}`) : import_picocolors35.default.yellow(res?.summary ?? "It did not finish.") + import_picocolors35.default.dim(` ${took}`)
10162
10373
  );
10163
10374
  if (res && !res.sandboxed) {
10164
10375
  line(
10165
- import_picocolors34.default.dim(
10376
+ import_picocolors35.default.dim(
10166
10377
  "This platform has no OS sandbox, so the script ran with your own file access."
10167
10378
  )
10168
10379
  );
@@ -10190,7 +10401,7 @@ function readCode(file, inline) {
10190
10401
  }
10191
10402
 
10192
10403
  // src/commands/scan.ts
10193
- var import_picocolors35 = __toESM(require_picocolors(), 1);
10404
+ var import_picocolors36 = __toESM(require_picocolors(), 1);
10194
10405
  import { spawnSync as spawnSync2 } from "child_process";
10195
10406
  import { existsSync as existsSync3, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
10196
10407
  import { join as join4, relative as relative2, sep as sep2 } from "path";
@@ -10474,22 +10685,22 @@ function runPermissions(cwd, findings, checked, skipped) {
10474
10685
  }
10475
10686
  function print2(report, summary) {
10476
10687
  for (const s of report.skipped) {
10477
- line(`${import_picocolors35.default.yellow("not checked")} ${s.check}${import_picocolors35.default.dim(` \u2014 ${s.reason}`)}`);
10688
+ line(`${import_picocolors36.default.yellow("not checked")} ${s.check}${import_picocolors36.default.dim(` \u2014 ${s.reason}`)}`);
10478
10689
  }
10479
10690
  for (const f of report.findings) {
10480
- const where = f.file ? import_picocolors35.default.dim(` ${f.file}${f.line ? `:${f.line}` : ""}`) : "";
10691
+ const where = f.file ? import_picocolors36.default.dim(` ${f.file}${f.line ? `:${f.line}` : ""}`) : "";
10481
10692
  line(`${severityTag(f.severity)} ${f.title}${where}`);
10482
- line(` ${import_picocolors35.default.dim(f.fix)}`);
10693
+ line(` ${import_picocolors36.default.dim(f.fix)}`);
10483
10694
  }
10484
10695
  if (report.findings.length || report.skipped.length) line("");
10485
10696
  if (report.ok && !report.skipped.length) success(summary);
10486
- else if (report.ok) line(import_picocolors35.default.yellow(summary));
10487
- else line(import_picocolors35.default.red(summary));
10697
+ else if (report.ok) line(import_picocolors36.default.yellow(summary));
10698
+ else line(import_picocolors36.default.red(summary));
10488
10699
  }
10489
10700
  function severityTag(severity) {
10490
- if (severity === "high") return import_picocolors35.default.red("serious ");
10491
- if (severity === "medium") return import_picocolors35.default.yellow("worth fixing");
10492
- return import_picocolors35.default.dim("minor ");
10701
+ if (severity === "high") return import_picocolors36.default.red("serious ");
10702
+ if (severity === "medium") return import_picocolors36.default.yellow("worth fixing");
10703
+ return import_picocolors36.default.dim("minor ");
10493
10704
  }
10494
10705
  function git(cwd, args) {
10495
10706
  try {
@@ -10550,7 +10761,7 @@ function listRepoFiles2(root, maxDepth = 8) {
10550
10761
  }
10551
10762
 
10552
10763
  // src/commands/health.ts
10553
- var import_picocolors36 = __toESM(require_picocolors(), 1);
10764
+ var import_picocolors37 = __toESM(require_picocolors(), 1);
10554
10765
  function registerHealth(program3) {
10555
10766
  program3.command("health").description("Check that the published apps in this project are still answering").option("--app <webAppId>", "check one app rather than all of them").action(
10556
10767
  action(async ({ ctx, opts }) => {
@@ -10564,16 +10775,16 @@ function registerHealth(program3) {
10564
10775
  }
10565
10776
  function print3(res) {
10566
10777
  if (!res?.checks?.length) {
10567
- line(import_picocolors36.default.dim(res?.note ?? "Nothing to check."));
10778
+ line(import_picocolors37.default.dim(res?.note ?? "Nothing to check."));
10568
10779
  return;
10569
10780
  }
10570
10781
  for (const c of res.checks) {
10571
- const mark = c.ok ? import_picocolors36.default.green("up ") : import_picocolors36.default.red("down");
10572
- const timing = import_picocolors36.default.dim(`${c.ms}ms`);
10573
- const detail = c.ok ? timing : import_picocolors36.default.dim(`${c.error ?? "no answer"}${c.failures > 1 ? ` \xB7 ${c.failures} in a row` : ""}`);
10574
- line(` ${mark} ${c.appName} ${import_picocolors36.default.dim(`(${c.environment})`)} ${c.url} ${detail}`);
10782
+ const mark = c.ok ? import_picocolors37.default.green("up ") : import_picocolors37.default.red("down");
10783
+ const timing = import_picocolors37.default.dim(`${c.ms}ms`);
10784
+ const detail = c.ok ? timing : import_picocolors37.default.dim(`${c.error ?? "no answer"}${c.failures > 1 ? ` \xB7 ${c.failures} in a row` : ""}`);
10785
+ line(` ${mark} ${c.appName} ${import_picocolors37.default.dim(`(${c.environment})`)} ${c.url} ${detail}`);
10575
10786
  if (c.incidentOpened) {
10576
- line(import_picocolors36.default.yellow(` An incident has been opened on the board for this.`));
10787
+ line(import_picocolors37.default.yellow(` An incident has been opened on the board for this.`));
10577
10788
  }
10578
10789
  }
10579
10790
  const down = res.checks.filter((c) => !c.ok);
@@ -10586,14 +10797,14 @@ function print3(res) {
10586
10797
  }
10587
10798
  const production = down.filter((c) => c.environment === "production").length;
10588
10799
  line(
10589
- import_picocolors36.default.red(
10800
+ import_picocolors37.default.red(
10590
10801
  `${down.length} of ${res.checks.length} not answering` + (production ? ` \u2014 ${production} customer-facing.` : " (preview only).")
10591
10802
  )
10592
10803
  );
10593
10804
  }
10594
10805
 
10595
10806
  // src/commands/urls.ts
10596
- var import_picocolors37 = __toESM(require_picocolors(), 1);
10807
+ var import_picocolors38 = __toESM(require_picocolors(), 1);
10597
10808
  function registerUrls(program3) {
10598
10809
  program3.command("urls").description("The stable preview and production addresses of every app in this project").option("--app <webAppId>", "just one app").action(
10599
10810
  action(async ({ ctx, opts }) => {
@@ -10607,20 +10818,20 @@ function registerUrls(program3) {
10607
10818
  const summary = urlsSummary(rows);
10608
10819
  ok({ rows, summary }, () => {
10609
10820
  for (const row of rows) {
10610
- const label = import_picocolors37.default.dim(row.environment.padEnd(10));
10611
- const value = row.url ? import_picocolors37.default.cyan(row.url) : import_picocolors37.default.dim(row.note ?? "not published");
10821
+ const label = import_picocolors38.default.dim(row.environment.padEnd(10));
10822
+ const value = row.url ? import_picocolors38.default.cyan(row.url) : import_picocolors38.default.dim(row.note ?? "not published");
10612
10823
  line(` ${row.appName.padEnd(22)} ${label} ${value}`);
10613
10824
  }
10614
10825
  line("");
10615
10826
  if (rows.some((r) => r.url)) success(summary);
10616
- else line(import_picocolors37.default.yellow(summary));
10827
+ else line(import_picocolors38.default.yellow(summary));
10617
10828
  });
10618
10829
  })
10619
10830
  );
10620
10831
  }
10621
10832
 
10622
10833
  // src/commands/deployments.ts
10623
- var import_picocolors38 = __toESM(require_picocolors(), 1);
10834
+ var import_picocolors39 = __toESM(require_picocolors(), 1);
10624
10835
  function registerDeployments(program3) {
10625
10836
  const cmd = program3.command("deployments").description("Deployment history, and putting a build in front of customers");
10626
10837
  cmd.command("list").description("What has been built, newest first").option("--app <webAppId>", "just one app (default: every app in the project)").option("--env <environment>", "preview or production").option("--limit <n>", "how many to show", "20").action(
@@ -10638,7 +10849,7 @@ function registerDeployments(program3) {
10638
10849
  ok(res, () => {
10639
10850
  if (!items.length) {
10640
10851
  return line(
10641
- import_picocolors38.default.dim(
10852
+ import_picocolors39.default.dim(
10642
10853
  environment ? `Nothing has been deployed to ${environment} yet.` : "Nothing has been deployed yet. `workser deploy` builds the first one."
10643
10854
  )
10644
10855
  );
@@ -10658,13 +10869,13 @@ function registerDeployments(program3) {
10658
10869
  ).catch(() => null) : null;
10659
10870
  ok({ ...dep, logs }, () => {
10660
10871
  line(formatDeployment(dep));
10661
- if (dep?.error_message) line(import_picocolors38.default.red(` ${dep.error_message}`));
10872
+ if (dep?.error_message) line(import_picocolors39.default.red(` ${dep.error_message}`));
10662
10873
  const events = logs?.events ?? [];
10663
10874
  for (const e of events) {
10664
- line(` ${import_picocolors38.default.dim(String(e.type ?? "log"))} ${e.text ?? ""}`);
10875
+ line(` ${import_picocolors39.default.dim(String(e.type ?? "log"))} ${e.text ?? ""}`);
10665
10876
  }
10666
10877
  if (opts.logs && !events.length) {
10667
- line(import_picocolors38.default.dim(" That build produced no output."));
10878
+ line(import_picocolors39.default.dim(" That build produced no output."));
10668
10879
  }
10669
10880
  });
10670
10881
  })
@@ -10708,16 +10919,16 @@ function printPromoted(res, version) {
10708
10919
  const what = version === null ? "the latest build" : `version ${version}`;
10709
10920
  const url = res.url ?? res.vercel_url;
10710
10921
  success(`Production is being rebuilt from ${what}.`);
10711
- if (url) line(import_picocolors38.default.dim(`It will be at ${url}`));
10712
- line(import_picocolors38.default.dim("`workser deploy status` follows it."));
10922
+ if (url) line(import_picocolors39.default.dim(`It will be at ${url}`));
10923
+ line(import_picocolors39.default.dim("`workser deploy status` follows it."));
10713
10924
  }
10714
10925
  function formatDeployment(d) {
10715
10926
  if (!d) return "";
10716
- const version = d.version !== void 0 ? import_picocolors38.default.yellow(`v${d.version}`) : import_picocolors38.default.dim("v?");
10717
- const env = import_picocolors38.default.dim((d.environment ?? "?").padEnd(10));
10927
+ const version = d.version !== void 0 ? import_picocolors39.default.yellow(`v${d.version}`) : import_picocolors39.default.dim("v?");
10928
+ const env = import_picocolors39.default.dim((d.environment ?? "?").padEnd(10));
10718
10929
  const app = d.webAppName ? `${d.webAppName} ` : "";
10719
- const when = import_picocolors38.default.dim(formatTime2(d.created_at));
10720
- const url = d.url ? " " + import_picocolors38.default.cyan(d.url) : "";
10930
+ const when = import_picocolors39.default.dim(formatTime2(d.created_at));
10931
+ const url = d.url ? " " + import_picocolors39.default.cyan(d.url) : "";
10721
10932
  return `${version} ${env} ${colorStatus(d.status ?? "")} ${app}${when}${url}`;
10722
10933
  }
10723
10934
  function formatTime2(t) {
@@ -10727,7 +10938,7 @@ function formatTime2(t) {
10727
10938
  }
10728
10939
 
10729
10940
  // src/commands/usage.ts
10730
- var import_picocolors39 = __toESM(require_picocolors(), 1);
10941
+ var import_picocolors40 = __toESM(require_picocolors(), 1);
10731
10942
 
10732
10943
  // src/usage.ts
10733
10944
  var NEAR_LIMIT_FRACTION = 0.8;
@@ -10822,7 +11033,7 @@ function registerUsage(program3) {
10822
11033
  function print4(report) {
10823
11034
  const dims = report.dimensions ?? [];
10824
11035
  if (!dims.length) {
10825
- return line(import_picocolors39.default.dim("Nothing to measure for this project yet."));
11036
+ return line(import_picocolors40.default.dim("Nothing to measure for this project yet."));
10826
11037
  }
10827
11038
  const width = Math.max(...dims.map((d) => d.label.length));
10828
11039
  for (const d of dims) {
@@ -10831,23 +11042,23 @@ function print4(report) {
10831
11042
  line("");
10832
11043
  const summary = usageSummary(report);
10833
11044
  const worst = dims.map(usageState);
10834
- if (worst.includes("over")) line(import_picocolors39.default.red(summary));
11045
+ if (worst.includes("over")) line(import_picocolors40.default.red(summary));
10835
11046
  else if (worst.includes("near") || worst.includes("unknown"))
10836
- line(import_picocolors39.default.yellow(summary));
11047
+ line(import_picocolors40.default.yellow(summary));
10837
11048
  else success(summary);
10838
11049
  }
10839
11050
  function gauge(d, _labelWidth) {
10840
11051
  const drawn = bar(d);
10841
- return drawn ? ` ${import_picocolors39.default.dim(drawn)}` : "";
11052
+ return drawn ? ` ${import_picocolors40.default.dim(drawn)}` : "";
10842
11053
  }
10843
11054
  function colour(d) {
10844
11055
  switch (usageState(d)) {
10845
11056
  case "over":
10846
- return d.kind === "hard" ? import_picocolors39.default.red : import_picocolors39.default.yellow;
11057
+ return d.kind === "hard" ? import_picocolors40.default.red : import_picocolors40.default.yellow;
10847
11058
  case "near":
10848
- return import_picocolors39.default.yellow;
11059
+ return import_picocolors40.default.yellow;
10849
11060
  case "unknown":
10850
- return import_picocolors39.default.dim;
11061
+ return import_picocolors40.default.dim;
10851
11062
  default:
10852
11063
  return (s) => s;
10853
11064
  }
@@ -10855,7 +11066,7 @@ function colour(d) {
10855
11066
 
10856
11067
  // src/index.ts
10857
11068
  var pkg = {
10858
- version: true ? "0.6.8" : "0.0.0-dev"
11069
+ version: true ? "0.6.9" : "0.0.0-dev"
10859
11070
  };
10860
11071
  var program2 = new Command();
10861
11072
  program2.name("workser").description(
@@ -10880,6 +11091,7 @@ registerAuth(program2);
10880
11091
  registerStorage(program2);
10881
11092
  registerNeon(program2);
10882
11093
  registerEnv(program2);
11094
+ registerKey(program2);
10883
11095
  registerDeploy(program2);
10884
11096
  registerVersions(program2);
10885
11097
  registerLogs(program2);