@workser/cli 0.6.12 → 0.6.13

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
@@ -3583,6 +3583,7 @@ function ownerOnly(opts) {
3583
3583
  }
3584
3584
 
3585
3585
  // src/output.ts
3586
+ var OUT_OF_SCOPE_EXIT = 7;
3586
3587
  var mode = "text";
3587
3588
  var quiet = false;
3588
3589
  function configureOutput(opts) {
@@ -3633,7 +3634,13 @@ function fail(err) {
3633
3634
  } else if (e.status === 401 || e.code === "unauthorized") {
3634
3635
  process.stderr.write(import_picocolors.default.dim(" Run `workser login` to authenticate.\n"));
3635
3636
  } else if (e.code === "no_project") {
3636
- process.stderr.write(import_picocolors.default.dim(" Run `workser project use <id>` or pass --project <id>.\n"));
3637
+ process.stderr.write(import_picocolors.default.dim(" cd into the project's folder, or open it in Workser.\n"));
3638
+ } else if (e.code === "out_of_scope") {
3639
+ process.stderr.write(
3640
+ import_picocolors.default.dim(
3641
+ " You can move between your organization's projects; another organization's are not reachable.\n"
3642
+ )
3643
+ );
3637
3644
  } else if (e.code === "awaiting_approval") {
3638
3645
  process.stderr.write(import_picocolors.default.dim(" Approve the action in Workser Orbit, then retry.\n"));
3639
3646
  } else if (e.code === "owner_only") {
@@ -3647,6 +3654,7 @@ function exitCodeFor(e) {
3647
3654
  if (e.status === 401 || e.code === "unauthorized") return 3;
3648
3655
  if (e.code === "awaiting_approval") return 5;
3649
3656
  if (e.code === "owner_only") return OWNER_ONLY_EXIT;
3657
+ if (e.code === "out_of_scope") return OUT_OF_SCOPE_EXIT;
3650
3658
  return 1;
3651
3659
  }
3652
3660
 
@@ -5624,6 +5632,9 @@ async function api(ctx, path, opts = {}) {
5624
5632
  if (ctx.mode === "daemon" && ctx.runId) {
5625
5633
  headers["x-workser-run-id"] = ctx.runId;
5626
5634
  }
5635
+ if (ctx.mode === "daemon" && ctx.cwd) {
5636
+ headers["x-workser-cwd"] = encodeURIComponent(ctx.cwd);
5637
+ }
5627
5638
  if (opts.body !== void 0) headers["content-type"] = "application/json";
5628
5639
  const method = opts.method ?? (opts.body !== void 0 ? "POST" : "GET");
5629
5640
  const bodyText = opts.body !== void 0 ? JSON.stringify(opts.body) : void 0;
@@ -5709,6 +5720,12 @@ function registerStatus(program3) {
5709
5720
  ` project: ${data.project?.name ?? "\u2014"}` + (data.project?.id ? import_picocolors3.default.dim(` (${data.project.id})`) : "")
5710
5721
  );
5711
5722
  if (ctx.projectRoot) line(` folder: ${import_picocolors3.default.dim(ctx.projectRoot)}`);
5723
+ if (data.scope) {
5724
+ const why = data.scope.source === "folder" ? "this folder" : data.scope.source === "active" ? "the project open in Workser" : null;
5725
+ line(
5726
+ data.scope.orgId ? ` org: ${data.scope.orgId}` + (why ? import_picocolors3.default.dim(` (from ${why})`) : "") : ` org: ${import_picocolors3.default.yellow("unscoped \u2014 every project is reachable")}`
5727
+ );
5728
+ }
5712
5729
  if (ctx.appId) {
5713
5730
  line(
5714
5731
  ` app: ${ctx.appName ?? "\u2014"}` + import_picocolors3.default.dim(` (${ctx.appId})`)
@@ -5921,7 +5938,7 @@ function registerProject(program3) {
5921
5938
  });
5922
5939
  })
5923
5940
  );
5924
- project.command("list").description("List the workspace's projects").action(
5941
+ project.command("list").description("List the projects in your organization").action(
5925
5942
  action(async ({ ctx }) => {
5926
5943
  const items = await api(ctx, `/v1/projects`);
5927
5944
  ok(items, () => {
@@ -5930,6 +5947,11 @@ function registerProject(program3) {
5930
5947
  const pinned = ctx.projectId && p.id === ctx.projectId ? import_picocolors4.default.green("\u25CF ") : " ";
5931
5948
  line(`${pinned}${p.name ?? "\u2014"}${p.id ? import_picocolors4.default.dim(` (${p.id})`) : ""}`);
5932
5949
  }
5950
+ line(
5951
+ import_picocolors4.default.dim(
5952
+ "\nYour organization's projects. Other organizations are not reachable from here."
5953
+ )
5954
+ );
5933
5955
  });
5934
5956
  })
5935
5957
  );
@@ -7841,8 +7863,52 @@ function registerMemory(program3) {
7841
7863
  );
7842
7864
  }
7843
7865
 
7844
- // src/commands/business.ts
7866
+ // src/commands/note.ts
7845
7867
  var import_picocolors24 = __toESM(require_picocolors(), 1);
7868
+ function registerNote(program3) {
7869
+ program3.command("note <text>").description("Leave a fact the rest of the team will need").addHelpText(
7870
+ "after",
7871
+ '\nFor things that are true about the WORK, not about your step:\n workser note "the API base path is /api/v2, not /api"\n workser note "added STRIPE_KEY to local, preview and production"\n\nWhat your own step did goes in `workser task done --summary` instead.\n'
7872
+ ).option(
7873
+ "--task <id>",
7874
+ "the plan to leave it on (default: the plan this step belongs to)"
7875
+ ).action(
7876
+ action(async ({ ctx, args, opts }) => {
7877
+ const text = typeof args[0] === "string" ? args[0].trim() : "";
7878
+ if (!text) {
7879
+ info("Nothing to note \u2014 give it a sentence.");
7880
+ return;
7881
+ }
7882
+ const taskId = opts.task || ctx.parentTaskId || ctx.projectTaskId;
7883
+ if (!taskId) {
7884
+ info(
7885
+ "No plan to leave this on. Run it from inside a step, or pass --task <id>."
7886
+ );
7887
+ return;
7888
+ }
7889
+ const res = await api(ctx, "/v1/team-notes", {
7890
+ body: {
7891
+ cwd: ctx.cwd,
7892
+ taskId,
7893
+ text,
7894
+ role: ctx.agentRole,
7895
+ agent: ctx.agentType
7896
+ }
7897
+ }).catch(() => null);
7898
+ if (!res) {
7899
+ info("Couldn't save that note \u2014 carrying on.");
7900
+ return;
7901
+ }
7902
+ ok(res, () => {
7903
+ success("Noted for the team.");
7904
+ line(import_picocolors24.default.dim(` ${text}`));
7905
+ });
7906
+ })
7907
+ );
7908
+ }
7909
+
7910
+ // src/commands/business.ts
7911
+ var import_picocolors25 = __toESM(require_picocolors(), 1);
7846
7912
  var RESOURCE_PATHS = {
7847
7913
  "business-config": "business-config",
7848
7914
  "business-settings": "business-settings",
@@ -7902,7 +7968,7 @@ function registerBusiness(program3) {
7902
7968
  const projectId = requireProject(ctx);
7903
7969
  const [resource] = args;
7904
7970
  const res = await api(ctx, businessPath(projectId, resource), { body: JSON.parse(opts.body) });
7905
- ok(res, () => line(`Created ${resource} ${import_picocolors24.default.bold(res?.id ?? "")}.`));
7971
+ ok(res, () => line(`Created ${resource} ${import_picocolors25.default.bold(res?.id ?? "")}.`));
7906
7972
  })
7907
7973
  );
7908
7974
  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(
@@ -7944,7 +8010,7 @@ function businessPath(projectId, resource, subpath) {
7944
8010
  }
7945
8011
 
7946
8012
  // src/commands/artifact.ts
7947
- var import_picocolors25 = __toESM(require_picocolors(), 1);
8013
+ var import_picocolors26 = __toESM(require_picocolors(), 1);
7948
8014
  import { existsSync as existsSync2, statSync } from "fs";
7949
8015
  import { resolve as resolve3, basename as basename3 } from "path";
7950
8016
  var KINDS = [
@@ -8041,7 +8107,7 @@ function registerArtifact(program3) {
8041
8107
  ok(
8042
8108
  res,
8043
8109
  () => success(
8044
- `Recorded ${import_picocolors25.default.bold(res?.title ?? "artifact")}${res?.kind ? import_picocolors25.default.dim(` (${res.kind})`) : ""}`
8110
+ `Recorded ${import_picocolors26.default.bold(res?.title ?? "artifact")}${res?.kind ? import_picocolors26.default.dim(` (${res.kind})`) : ""}`
8045
8111
  )
8046
8112
  );
8047
8113
  })
@@ -8079,7 +8145,7 @@ function registerArtifact(program3) {
8079
8145
  }
8080
8146
  function printArtifacts(rows) {
8081
8147
  if (!rows.length) {
8082
- line(import_picocolors25.default.dim("Nothing produced yet."));
8148
+ line(import_picocolors26.default.dim("Nothing produced yet."));
8083
8149
  return;
8084
8150
  }
8085
8151
  const byStep = /* @__PURE__ */ new Map();
@@ -8089,26 +8155,26 @@ function printArtifacts(rows) {
8089
8155
  byStep.set(r.subtask_id, list);
8090
8156
  }
8091
8157
  for (const [stepId, items] of byStep) {
8092
- line(import_picocolors25.default.bold(`step ${stepId}`));
8158
+ line(import_picocolors26.default.bold(`step ${stepId}`));
8093
8159
  for (const a of items) {
8094
- const flag = a.promoted_at ? import_picocolors25.default.green(" *") : " ";
8160
+ const flag = a.promoted_at ? import_picocolors26.default.green(" *") : " ";
8095
8161
  const where = a.local_path || a.cloud_url || "";
8096
8162
  line(
8097
- `${flag} ${import_picocolors25.default.dim(`[${a.kind}]`)} ${a.title ?? "(untitled)"}` + (where ? import_picocolors25.default.dim(` ${where}`) : "")
8163
+ `${flag} ${import_picocolors26.default.dim(`[${a.kind}]`)} ${a.title ?? "(untitled)"}` + (where ? import_picocolors26.default.dim(` ${where}`) : "")
8098
8164
  );
8099
- if (a.description) line(import_picocolors25.default.dim(` ${a.description}`));
8165
+ if (a.description) line(import_picocolors26.default.dim(` ${a.description}`));
8100
8166
  }
8101
8167
  line("");
8102
8168
  }
8103
- line(import_picocolors25.default.dim("* = handed over as a deliverable; the rest is working material."));
8169
+ line(import_picocolors26.default.dim("* = handed over as a deliverable; the rest is working material."));
8104
8170
  }
8105
8171
  function printRun(run) {
8106
8172
  if (!run) return;
8107
- line(` run ${import_picocolors25.default.bold(run.runId)}`);
8173
+ line(` run ${import_picocolors26.default.bold(run.runId)}`);
8108
8174
  if (run.taskId) line(` task ${run.taskId}`);
8109
8175
  if (run.conversationId) line(` chat ${run.conversationId}`);
8110
8176
  if (run.projectId) line(` project ${run.projectId}`);
8111
- if (run.cwd) line(` folder ${import_picocolors25.default.dim(run.cwd)}`);
8177
+ if (run.cwd) line(` folder ${import_picocolors26.default.dim(run.cwd)}`);
8112
8178
  }
8113
8179
 
8114
8180
  // src/commands/image.ts
@@ -8289,7 +8355,7 @@ function registerAudio(program3) {
8289
8355
  }
8290
8356
 
8291
8357
  // src/commands/ask.ts
8292
- var import_picocolors26 = __toESM(require_picocolors(), 1);
8358
+ var import_picocolors27 = __toESM(require_picocolors(), 1);
8293
8359
  var TYPES = [
8294
8360
  "input",
8295
8361
  "choice",
@@ -8367,7 +8433,7 @@ function registerAsk(program3) {
8367
8433
  code: "bad_request"
8368
8434
  });
8369
8435
  }
8370
- info(import_picocolors26.default.dim("Waiting for the user to answer\u2026"));
8436
+ info(import_picocolors27.default.dim("Waiting for the user to answer\u2026"));
8371
8437
  const res = await api(ctx, `/v1/runs/${runTarget(ctx)}/ask`, {
8372
8438
  body: {
8373
8439
  type,
@@ -8395,12 +8461,12 @@ function deriveTitle(message) {
8395
8461
  function printAnswer(res) {
8396
8462
  if (!res) return;
8397
8463
  if (res.status === "answered") {
8398
- line(` ${import_picocolors26.default.green("answered")}`);
8464
+ line(` ${import_picocolors27.default.green("answered")}`);
8399
8465
  const value = extract(res.response);
8400
8466
  if (value) line(` ${value}`);
8401
8467
  return;
8402
8468
  }
8403
- line(` ${import_picocolors26.default.yellow(res.status)} ${import_picocolors26.default.dim(res.reason ?? "")}`);
8469
+ line(` ${import_picocolors27.default.yellow(res.status)} ${import_picocolors27.default.dim(res.reason ?? "")}`);
8404
8470
  }
8405
8471
  function extract(response) {
8406
8472
  if (response == null) return "";
@@ -8419,7 +8485,7 @@ function extract(response) {
8419
8485
  }
8420
8486
 
8421
8487
  // src/commands/search.ts
8422
- var import_picocolors27 = __toESM(require_picocolors(), 1);
8488
+ var import_picocolors28 = __toESM(require_picocolors(), 1);
8423
8489
  function registerSearch(program3) {
8424
8490
  program3.command("search <query>").description("Search the web (Google-grounded, server-side)").option("-n, --max-results <n>", "max results", "5").action(
8425
8491
  action(async ({ ctx, args, opts }) => {
@@ -8432,9 +8498,9 @@ function registerSearch(program3) {
8432
8498
  line("");
8433
8499
  }
8434
8500
  const results = res?.results ?? [];
8435
- if (!results.length) return line(import_picocolors27.default.dim("No results."));
8501
+ if (!results.length) return line(import_picocolors28.default.dim("No results."));
8436
8502
  for (const r of results) {
8437
- line(`${r.title || import_picocolors27.default.dim("(untitled)")} ${import_picocolors27.default.dim(r.url)}`);
8503
+ line(`${r.title || import_picocolors28.default.dim("(untitled)")} ${import_picocolors28.default.dim(r.url)}`);
8438
8504
  }
8439
8505
  });
8440
8506
  })
@@ -8442,7 +8508,7 @@ function registerSearch(program3) {
8442
8508
  }
8443
8509
 
8444
8510
  // src/commands/board.ts
8445
- var import_picocolors28 = __toESM(require_picocolors(), 1);
8511
+ var import_picocolors29 = __toESM(require_picocolors(), 1);
8446
8512
 
8447
8513
  // src/commands/record-step.ts
8448
8514
  async function recordEntityStep(ctx, opts) {
@@ -8481,7 +8547,7 @@ function registerBoard(program3) {
8481
8547
  }
8482
8548
  ok(rows, () => {
8483
8549
  if (!rows.length) {
8484
- line(import_picocolors28.default.dim("No cards on the Board yet."));
8550
+ line(import_picocolors29.default.dim("No cards on the Board yet."));
8485
8551
  return;
8486
8552
  }
8487
8553
  for (const r of rows) line(formatRow(r));
@@ -8496,7 +8562,7 @@ function registerBoard(program3) {
8496
8562
  `/v1/projects/${projectId}/work-items/${args[0]}`
8497
8563
  );
8498
8564
  ok(row, () => {
8499
- line(`${import_picocolors28.default.bold(row.title)} ${import_picocolors28.default.dim(row.id)}`);
8565
+ line(`${import_picocolors29.default.bold(row.title)} ${import_picocolors29.default.dim(row.id)}`);
8500
8566
  line(`${statusTag(row.status)} priority ${row.priority}`);
8501
8567
  if (row.ownerHuman) line(`owner: ${row.ownerHuman}`);
8502
8568
  if (row.labels?.length) line(`labels: ${row.labels.join(", ")}`);
@@ -8537,7 +8603,7 @@ ${row.description}`);
8537
8603
  refId: row?.id,
8538
8604
  output: { workItem: row }
8539
8605
  });
8540
- ok(row, () => line(`Created work item ${import_picocolors28.default.bold(row?.id ?? "")} \u2014 ${title}`));
8606
+ ok(row, () => line(`Created work item ${import_picocolors29.default.bold(row?.id ?? "")} \u2014 ${title}`));
8541
8607
  })
8542
8608
  );
8543
8609
  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(
@@ -8571,7 +8637,7 @@ ${row.description}`);
8571
8637
  );
8572
8638
  }
8573
8639
  const row = await patchItem(ctx, projectId, String(args[0]), body);
8574
- ok(row, () => line(`Updated ${import_picocolors28.default.bold(row.id)} \u2014 ${row.title} ${statusTag(row.status)}`));
8640
+ ok(row, () => line(`Updated ${import_picocolors29.default.bold(row.id)} \u2014 ${row.title} ${statusTag(row.status)}`));
8575
8641
  })
8576
8642
  );
8577
8643
  board.command("move <id> <status>").description(
@@ -8582,14 +8648,14 @@ ${row.description}`);
8582
8648
  const status = String(args[1]);
8583
8649
  assertStatus(status);
8584
8650
  const row = await patchItem(ctx, projectId, String(args[0]), { status });
8585
- ok(row, () => line(`Moved ${import_picocolors28.default.bold(row.title)} \u2192 ${statusTag(row.status)}`));
8651
+ ok(row, () => line(`Moved ${import_picocolors29.default.bold(row.title)} \u2192 ${statusTag(row.status)}`));
8586
8652
  })
8587
8653
  );
8588
8654
  board.command("close <id>").description("Shorthand for `board move <id> done`").action(
8589
8655
  action(async ({ ctx, args }) => {
8590
8656
  const projectId = requireProject(ctx);
8591
8657
  const row = await patchItem(ctx, projectId, String(args[0]), { status: "done" });
8592
- ok(row, () => line(`Closed ${import_picocolors28.default.bold(row.title)} ${statusTag(row.status)}`));
8658
+ ok(row, () => line(`Closed ${import_picocolors29.default.bold(row.title)} ${statusTag(row.status)}`));
8593
8659
  })
8594
8660
  );
8595
8661
  }
@@ -8622,23 +8688,23 @@ function assertPriority(value) {
8622
8688
  }
8623
8689
  }
8624
8690
  function formatRow(r) {
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}`;
8691
+ const labels = r.labels?.length ? import_picocolors29.default.dim(` [${r.labels.join(", ")}]`) : "";
8692
+ const owner = r.ownerHuman ? import_picocolors29.default.dim(` @${r.ownerHuman}`) : "";
8693
+ return `${import_picocolors29.default.dim(r.id)} ${statusTag(r.status)} ${r.title}${labels}${owner}`;
8628
8694
  }
8629
8695
  function statusTag(status) {
8630
8696
  const label = status.padEnd(11);
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);
8697
+ if (status === "done") return import_picocolors29.default.green(label);
8698
+ if (status === "in-progress") return import_picocolors29.default.yellow(label);
8699
+ if (status === "in-review") return import_picocolors29.default.cyan(label);
8700
+ return import_picocolors29.default.dim(label);
8635
8701
  }
8636
8702
  function collect2(value, previous) {
8637
8703
  return [...previous, value];
8638
8704
  }
8639
8705
 
8640
8706
  // src/commands/task.ts
8641
- var import_picocolors29 = __toESM(require_picocolors(), 1);
8707
+ var import_picocolors30 = __toESM(require_picocolors(), 1);
8642
8708
 
8643
8709
  // src/subtask-attachments.ts
8644
8710
  var MAX_REF_NOTE = 500;
@@ -8752,7 +8818,7 @@ function registerTask(program3) {
8752
8818
  }) ?? [];
8753
8819
  ok(rows, () => {
8754
8820
  if (!rows.length) {
8755
- line(import_picocolors29.default.dim("No tasks on the board yet."));
8821
+ line(import_picocolors30.default.dim("No tasks on the board yet."));
8756
8822
  return;
8757
8823
  }
8758
8824
  for (const r of rows) line(formatRow2(r));
@@ -8861,10 +8927,10 @@ function registerTask(program3) {
8861
8927
  };
8862
8928
  ok(result, () => {
8863
8929
  line(
8864
- `${import_picocolors29.default.green("opened")} ${import_picocolors29.default.bold(row.title)} ${import_picocolors29.default.dim(row.key ?? row.id)}`
8930
+ `${import_picocolors30.default.green("opened")} ${import_picocolors30.default.bold(row.title)} ${import_picocolors30.default.dim(row.key ?? row.id)}`
8865
8931
  );
8866
8932
  if (channelMessage)
8867
- line(import_picocolors29.default.dim("posted to the channel as Project Manager"));
8933
+ line(import_picocolors30.default.dim("posted to the channel as Project Manager"));
8868
8934
  if (channelMessageError) {
8869
8935
  warn(
8870
8936
  `Task opened, but its Project Manager card could not be posted: ${channelMessageError.message}`
@@ -8943,12 +9009,12 @@ function registerTask(program3) {
8943
9009
  ) : null;
8944
9010
  ok(runner ?? row, () => {
8945
9011
  line(
8946
- `${import_picocolors29.default.green("added")} ${import_picocolors29.default.bold(row.title)} ${import_picocolors29.default.dim(row.key ?? row.id)}`
9012
+ `${import_picocolors30.default.green("added")} ${import_picocolors30.default.bold(row.title)} ${import_picocolors30.default.dim(row.key ?? row.id)}`
8947
9013
  );
8948
- if (row.role) line(import_picocolors29.default.dim(`role: ${row.role}`));
9014
+ if (row.role) line(import_picocolors30.default.dim(`role: ${row.role}`));
8949
9015
  if (runner) {
8950
9016
  line(
8951
- import_picocolors29.default.dim(
9017
+ import_picocolors30.default.dim(
8952
9018
  `runs on: ${[opts.agent, opts.model, opts.effort].filter(Boolean).join(" \xB7 ")}`
8953
9019
  )
8954
9020
  );
@@ -8966,7 +9032,7 @@ function registerTask(program3) {
8966
9032
  const rows = row.subtasks ?? [];
8967
9033
  ok(rows, () => {
8968
9034
  if (!rows.length) {
8969
- line(import_picocolors29.default.dim("No subtasks yet."));
9035
+ line(import_picocolors30.default.dim("No subtasks yet."));
8970
9036
  return;
8971
9037
  }
8972
9038
  rows.forEach((r, i) => line(formatSubtask(r, i + 1)));
@@ -9014,7 +9080,7 @@ function registerTask(program3) {
9014
9080
  }
9015
9081
  }
9016
9082
  );
9017
- ok(row, () => line(`${import_picocolors29.default.green("updated")} ${import_picocolors29.default.bold(row.title)}`));
9083
+ ok(row, () => line(`${import_picocolors30.default.green("updated")} ${import_picocolors30.default.bold(row.title)}`));
9018
9084
  })
9019
9085
  );
9020
9086
  subtask.command("remove <id>").description("Remove a subtask (only before the work starts)").action(
@@ -9022,7 +9088,7 @@ function registerTask(program3) {
9022
9088
  await api(ctx, `/v1/project-tasks/${encodeURIComponent(args[0])}`, {
9023
9089
  method: "DELETE"
9024
9090
  });
9025
- ok({ removed: args[0] }, () => line(import_picocolors29.default.green("removed")));
9091
+ ok({ removed: args[0] }, () => line(import_picocolors30.default.green("removed")));
9026
9092
  })
9027
9093
  );
9028
9094
  task.command("move <id> <status>").description(
@@ -9037,7 +9103,7 @@ function registerTask(program3) {
9037
9103
  );
9038
9104
  ok(
9039
9105
  row,
9040
- () => line(`${import_picocolors29.default.green("moved")} ${import_picocolors29.default.bold(row.title)} \u2192 ${args[1]}`)
9106
+ () => line(`${import_picocolors30.default.green("moved")} ${import_picocolors30.default.bold(row.title)} \u2192 ${args[1]}`)
9041
9107
  );
9042
9108
  })
9043
9109
  );
@@ -9053,18 +9119,18 @@ function registerTask(program3) {
9053
9119
  );
9054
9120
  ok(row, () => {
9055
9121
  if (!row?.queued) {
9056
- line(import_picocolors29.default.yellow("could not resume it \u2014 check the step id"));
9122
+ line(import_picocolors30.default.yellow("could not resume it \u2014 check the step id"));
9057
9123
  return;
9058
9124
  }
9059
9125
  const started = row.started ?? 0;
9060
9126
  if (started > 0) {
9061
9127
  line(
9062
- `${import_picocolors29.default.green("resumed")} \u2014 ${started} step${started === 1 ? "" : "s"} started`
9128
+ `${import_picocolors30.default.green("resumed")} \u2014 ${started} step${started === 1 ? "" : "s"} started`
9063
9129
  );
9064
9130
  return;
9065
9131
  }
9066
9132
  line(
9067
- `${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.`
9133
+ `${import_picocolors30.default.green("resumed")} \u2014 it is queued, but nothing started yet. Check the plan is approved and that no step is blocking the rest.`
9068
9134
  );
9069
9135
  });
9070
9136
  })
@@ -9078,11 +9144,11 @@ function registerTask(program3) {
9078
9144
  );
9079
9145
  ok(row, () => {
9080
9146
  if (row?.reopened) {
9081
- line(`${import_picocolors29.default.green("sent back")} \u2014 it will be picked up again`);
9147
+ line(`${import_picocolors30.default.green("sent back")} \u2014 it will be picked up again`);
9082
9148
  return;
9083
9149
  }
9084
9150
  line(
9085
- import_picocolors29.default.yellow(
9151
+ import_picocolors30.default.yellow(
9086
9152
  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"
9087
9153
  )
9088
9154
  );
@@ -9099,7 +9165,7 @@ function registerTask(program3) {
9099
9165
  `/v1/project-tasks/${encodeURIComponent(id)}/dispatch-check`,
9100
9166
  { method: "POST" }
9101
9167
  );
9102
- ok(row, () => line(import_picocolors29.default.green("approved \u2014 you may start")));
9168
+ ok(row, () => line(import_picocolors30.default.green("approved \u2014 you may start")));
9103
9169
  })
9104
9170
  );
9105
9171
  task.command("start [id]").description(
@@ -9114,13 +9180,13 @@ function registerTask(program3) {
9114
9180
  const started = row?.started ?? null;
9115
9181
  if (started && started > 0) {
9116
9182
  line(
9117
- import_picocolors29.default.green(
9183
+ import_picocolors30.default.green(
9118
9184
  `started ${started} step${started === 1 ? "" : "s"} \u2014 they are running now`
9119
9185
  )
9120
9186
  );
9121
9187
  return;
9122
9188
  }
9123
- line(import_picocolors29.default.yellow(row?.note ?? "Nothing started."));
9189
+ line(import_picocolors30.default.yellow(row?.note ?? "Nothing started."));
9124
9190
  });
9125
9191
  })
9126
9192
  );
@@ -9135,7 +9201,7 @@ function registerTask(program3) {
9135
9201
  );
9136
9202
  ok({ awaiting: row2.approval_state === "awaiting", task: row2 }, () => {
9137
9203
  line(
9138
- row2.approval_state === "awaiting" ? import_picocolors29.default.yellow(
9204
+ row2.approval_state === "awaiting" ? import_picocolors30.default.yellow(
9139
9205
  "The plan is waiting on the owner. They see it in the task."
9140
9206
  ) : `Already ${row2.approval_state}.`
9141
9207
  );
@@ -9160,7 +9226,7 @@ function registerTask(program3) {
9160
9226
  );
9161
9227
  ok(
9162
9228
  row,
9163
- () => line(`${import_picocolors29.default.green(row.approval_state)} ${import_picocolors29.default.bold(row.title)}`)
9229
+ () => line(`${import_picocolors30.default.green(row.approval_state)} ${import_picocolors30.default.bold(row.title)}`)
9164
9230
  );
9165
9231
  })
9166
9232
  );
@@ -9176,7 +9242,7 @@ function registerTask(program3) {
9176
9242
  `/v1/project-tasks/${encodeURIComponent(id)}/move`,
9177
9243
  { body: { status: "ready" } }
9178
9244
  );
9179
- ok(row, () => line(`${import_picocolors29.default.green("ready")} ${import_picocolors29.default.bold(row.title)}`));
9245
+ ok(row, () => line(`${import_picocolors30.default.green("ready")} ${import_picocolors30.default.bold(row.title)}`));
9180
9246
  })
9181
9247
  );
9182
9248
  }
@@ -9221,24 +9287,24 @@ function assertOneOf(flag, value, allowed) {
9221
9287
  }
9222
9288
  }
9223
9289
  function formatRow2(r) {
9224
- const key = import_picocolors29.default.dim((r.key ?? r.id.slice(0, 8)).padEnd(10));
9225
- const steps = r.subtaskTotal ? import_picocolors29.default.dim(` ${r.subtaskDone}/${r.subtaskTotal}`) : "";
9226
- const gate = r.approval_state === "awaiting" ? import_picocolors29.default.yellow(" awaiting approval") : "";
9290
+ const key = import_picocolors30.default.dim((r.key ?? r.id.slice(0, 8)).padEnd(10));
9291
+ const steps = r.subtaskTotal ? import_picocolors30.default.dim(` ${r.subtaskDone}/${r.subtaskTotal}`) : "";
9292
+ const gate = r.approval_state === "awaiting" ? import_picocolors30.default.yellow(" awaiting approval") : "";
9227
9293
  return `${key} ${statusTag2(r.status)} ${r.title}${steps}${gate}`;
9228
9294
  }
9229
9295
  function formatSubtask(r, index) {
9230
- const n = import_picocolors29.default.dim(String(index).padStart(2, "0"));
9231
- const role = r.role ? import_picocolors29.default.dim(` [${r.role}]`) : "";
9232
- const scope = r.scope_paths?.length ? import_picocolors29.default.dim(` owns: ${r.scope_paths.join(", ")}`) : "";
9296
+ const n = import_picocolors30.default.dim(String(index).padStart(2, "0"));
9297
+ const role = r.role ? import_picocolors30.default.dim(` [${r.role}]`) : "";
9298
+ const scope = r.scope_paths?.length ? import_picocolors30.default.dim(` owns: ${r.scope_paths.join(", ")}`) : "";
9233
9299
  const head = `${n} ${statusTag2(r.status)} ${r.title}${role}${scope}`;
9234
9300
  const summary = (r.result_summary ?? "").trim();
9235
9301
  if (!summary) return head;
9236
9302
  const wrapped = summary.split("\n").map((l) => ` ${l}`).join("\n");
9237
9303
  return `${head}
9238
- ${import_picocolors29.default.dim(wrapped)}`;
9304
+ ${import_picocolors30.default.dim(wrapped)}`;
9239
9305
  }
9240
9306
  function printTask(row, goal) {
9241
- line(`${import_picocolors29.default.bold(row.title)} ${import_picocolors29.default.dim(row.key ?? row.id)}`);
9307
+ line(`${import_picocolors30.default.bold(row.title)} ${import_picocolors30.default.dim(row.key ?? row.id)}`);
9242
9308
  line(`${statusTag2(row.status)} approval: ${row.approval_state}`);
9243
9309
  if (row.summary) line(`
9244
9310
  ${row.summary}`);
@@ -9251,53 +9317,53 @@ touches: ${row.targets.map((t) => t.appName ?? t.ref ?? t.kind).join(", ")}`
9251
9317
  }
9252
9318
  if (row.subtasks?.length) {
9253
9319
  line(`
9254
- ${import_picocolors29.default.bold("subtasks")}`);
9320
+ ${import_picocolors30.default.bold("subtasks")}`);
9255
9321
  row.subtasks.forEach((s, i) => line(formatSubtask(s, i + 1)));
9256
9322
  line(
9257
- import_picocolors29.default.dim(
9323
+ import_picocolors30.default.dim(
9258
9324
  `
9259
9325
  Run \`workser artifact list\` to see what these subtasks produced,`
9260
9326
  )
9261
9327
  );
9262
9328
  line(
9263
- import_picocolors29.default.dim(
9329
+ import_picocolors30.default.dim(
9264
9330
  `or \`workser artifact list --step <id>\` for one subtask's output alone.`
9265
9331
  )
9266
9332
  );
9267
9333
  } else {
9268
- line(import_picocolors29.default.dim("\nNo subtasks yet."));
9334
+ line(import_picocolors30.default.dim("\nNo subtasks yet."));
9269
9335
  }
9270
9336
  }
9271
9337
  function printGoalContext(row, goal) {
9272
9338
  const mine = row.phase ?? null;
9273
9339
  line(`
9274
- ${import_picocolors29.default.bold("part of")}: ${goal.title}`);
9275
- if (goal.outcome) line(import_picocolors29.default.dim(`done means: ${goal.outcome}`));
9340
+ ${import_picocolors30.default.bold("part of")}: ${goal.title}`);
9341
+ if (goal.outcome) line(import_picocolors30.default.dim(`done means: ${goal.outcome}`));
9276
9342
  const progress = goal.progress ?? [];
9277
9343
  for (const p of progress) {
9278
9344
  const where = p.total === 0 ? "not started" : `${p.done} of ${p.total} done`;
9279
- const here = mine && p.name === mine ? import_picocolors29.default.cyan(" <- this task") : "";
9280
- const mark = p.state === "done" ? import_picocolors29.default.green("*") : import_picocolors29.default.dim("-");
9345
+ const here = mine && p.name === mine ? import_picocolors30.default.cyan(" <- this task") : "";
9346
+ const mark = p.state === "done" ? import_picocolors30.default.green("*") : import_picocolors30.default.dim("-");
9281
9347
  line(` ${mark} ${p.name} \u2014 ${where}${here}`);
9282
9348
  }
9283
9349
  const next = progress.find((p) => p.state !== "done");
9284
9350
  const running = progress.some((p) => p.state === "working");
9285
9351
  if (next && !running) {
9286
9352
  line(
9287
- import_picocolors29.default.dim(
9353
+ import_picocolors30.default.dim(
9288
9354
  `
9289
9355
  Nothing is running. The next part waiting is "${next.name}" \u2014 offer it to them in a sentence rather than starting it unasked.`
9290
9356
  )
9291
9357
  );
9292
9358
  } else if (!next) {
9293
9359
  line(
9294
- import_picocolors29.default.dim(
9360
+ import_picocolors30.default.dim(
9295
9361
  "\nEvery part of this plan is done. Say so, and offer to wrap it up."
9296
9362
  )
9297
9363
  );
9298
9364
  }
9299
9365
  line(
9300
- import_picocolors29.default.dim(
9366
+ import_picocolors30.default.dim(
9301
9367
  "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."
9302
9368
  )
9303
9369
  );
@@ -9305,22 +9371,22 @@ Nothing is running. The next part waiting is "${next.name}" \u2014 offer it to t
9305
9371
  function statusTag2(status) {
9306
9372
  switch (status) {
9307
9373
  case "ready":
9308
- return import_picocolors29.default.green("[ready]");
9374
+ return import_picocolors30.default.green("[ready]");
9309
9375
  case "working":
9310
- return import_picocolors29.default.blue("[working]");
9376
+ return import_picocolors30.default.blue("[working]");
9311
9377
  case "checking":
9312
- return import_picocolors29.default.cyan("[checking]");
9378
+ return import_picocolors30.default.cyan("[checking]");
9313
9379
  case "accepted":
9314
- return import_picocolors29.default.green("[accepted]");
9380
+ return import_picocolors30.default.green("[accepted]");
9315
9381
  case "archived":
9316
- return import_picocolors29.default.dim("[archived]");
9382
+ return import_picocolors30.default.dim("[archived]");
9317
9383
  default:
9318
- return import_picocolors29.default.dim("[todo]");
9384
+ return import_picocolors30.default.dim("[todo]");
9319
9385
  }
9320
9386
  }
9321
9387
 
9322
9388
  // src/commands/goal.ts
9323
- var import_picocolors30 = __toESM(require_picocolors(), 1);
9389
+ var import_picocolors31 = __toESM(require_picocolors(), 1);
9324
9390
  var STATUSES3 = ["proposed", "agreed", "working", "delivered", "abandoned"];
9325
9391
  function registerGoal(program3) {
9326
9392
  const goal = program3.command("goal").description("Business goals and the phases that deliver them");
@@ -9332,7 +9398,7 @@ function registerGoal(program3) {
9332
9398
  }) ?? [];
9333
9399
  ok(rows, () => {
9334
9400
  if (!rows.length) {
9335
- line(import_picocolors30.default.dim("No goals yet \u2014 every task here stands on its own."));
9401
+ line(import_picocolors31.default.dim("No goals yet \u2014 every task here stands on its own."));
9336
9402
  return;
9337
9403
  }
9338
9404
  for (const g of rows) line(formatGoal(g));
@@ -9409,10 +9475,10 @@ function registerGoal(program3) {
9409
9475
  }
9410
9476
  });
9411
9477
  ok(row, () => {
9412
- success(`Proposed ${import_picocolors30.default.bold(row?.title ?? "goal")}`);
9478
+ success(`Proposed ${import_picocolors31.default.bold(row?.title ?? "goal")}`);
9413
9479
  printGoal(row);
9414
9480
  line(
9415
- import_picocolors30.default.dim(
9481
+ import_picocolors31.default.dim(
9416
9482
  "\nNothing has been created yet. The owner agrees the shape first."
9417
9483
  )
9418
9484
  );
@@ -9441,7 +9507,7 @@ function registerGoal(program3) {
9441
9507
  ok(
9442
9508
  row,
9443
9509
  () => line(
9444
- 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(
9510
+ row?.recorded ? met === true ? import_picocolors31.default.green("recorded \u2014 met") : met === false ? import_picocolors31.default.yellow("recorded \u2014 not met") : import_picocolors31.default.dim("recorded \u2014 back to unchecked") : import_picocolors31.default.yellow(
9445
9511
  "couldn't record it \u2014 check the goal id, the phase name and the criterion id"
9446
9512
  )
9447
9513
  )
@@ -9484,7 +9550,7 @@ function registerGoal(program3) {
9484
9550
  }
9485
9551
  ok({ goalId, phase, filed }, () => {
9486
9552
  success(
9487
- `Filed ${filed.length} ${filed.length === 1 ? "task" : "tasks"} under ${import_picocolors30.default.bold(phase)}`
9553
+ `Filed ${filed.length} ${filed.length === 1 ? "task" : "tasks"} under ${import_picocolors31.default.bold(phase)}`
9488
9554
  );
9489
9555
  });
9490
9556
  })
@@ -9516,42 +9582,42 @@ function registerGoal(program3) {
9516
9582
  function appScope(g) {
9517
9583
  const n = g.appIds?.length ?? 0;
9518
9584
  if (!n) return "";
9519
- return import_picocolors30.default.dim(` ${n} part${n === 1 ? "" : "s"} of the system`);
9585
+ return import_picocolors31.default.dim(` ${n} part${n === 1 ? "" : "s"} of the system`);
9520
9586
  }
9521
9587
  function formatGoal(g) {
9522
- const where = g.currentPhase && g.status !== "delivered" ? import_picocolors30.default.dim(` now: ${g.currentPhase}`) : "";
9523
- const count = g.taskTotal != null ? import_picocolors30.default.dim(` ${g.taskDone}/${g.taskTotal} done`) : "";
9524
- return `${statusTag3(g.status)} ${g.title}${appScope(g)}${where}${count} ${import_picocolors30.default.dim(g.id)}`;
9588
+ const where = g.currentPhase && g.status !== "delivered" ? import_picocolors31.default.dim(` now: ${g.currentPhase}`) : "";
9589
+ const count = g.taskTotal != null ? import_picocolors31.default.dim(` ${g.taskDone}/${g.taskTotal} done`) : "";
9590
+ return `${statusTag3(g.status)} ${g.title}${appScope(g)}${where}${count} ${import_picocolors31.default.dim(g.id)}`;
9525
9591
  }
9526
9592
  function printGoal(g) {
9527
9593
  if (!g) return;
9528
- line(`${import_picocolors30.default.bold(g.title)} ${import_picocolors30.default.dim(g.id)}`);
9594
+ line(`${import_picocolors31.default.bold(g.title)} ${import_picocolors31.default.dim(g.id)}`);
9529
9595
  line(statusTag3(g.status));
9530
9596
  if (g.outcome) line(`
9531
9597
  done means: ${g.outcome}`);
9532
9598
  const progress = g.progress ?? [];
9533
9599
  if (!progress.length) {
9534
- line(import_picocolors30.default.dim("\nNo phases agreed yet."));
9600
+ line(import_picocolors31.default.dim("\nNo phases agreed yet."));
9535
9601
  return;
9536
9602
  }
9537
9603
  line(`
9538
- ${import_picocolors30.default.bold("phases")}`);
9604
+ ${import_picocolors31.default.bold("phases")}`);
9539
9605
  for (const p of progress) {
9540
- const bar2 = p.total > 0 ? `${p.done}/${p.total} done` : import_picocolors30.default.dim("nothing filed yet");
9541
- const mark = p.state === "done" ? import_picocolors30.default.green("done") : p.state === "working" ? import_picocolors30.default.blue("working") : import_picocolors30.default.dim("waiting");
9606
+ const bar2 = p.total > 0 ? `${p.done}/${p.total} done` : import_picocolors31.default.dim("nothing filed yet");
9607
+ const mark = p.state === "done" ? import_picocolors31.default.green("done") : p.state === "working" ? import_picocolors31.default.blue("working") : import_picocolors31.default.dim("waiting");
9542
9608
  line(
9543
- ` ${import_picocolors30.default.dim(String(p.index).padStart(2, "0"))} ${p.name} ${mark} ${import_picocolors30.default.dim(bar2)}`
9609
+ ` ${import_picocolors31.default.dim(String(p.index).padStart(2, "0"))} ${p.name} ${mark} ${import_picocolors31.default.dim(bar2)}`
9544
9610
  );
9545
9611
  for (const c of p.criteria ?? []) {
9546
- const tick = c.met === true ? import_picocolors30.default.green("\u2713") : c.met === false ? import_picocolors30.default.red("\u2717") : import_picocolors30.default.dim("\xB7");
9547
- line(` ${tick} ${c.text} ${import_picocolors30.default.dim(c.id)}`);
9548
- if (c.note) line(import_picocolors30.default.dim(` ${c.note}`));
9612
+ const tick = c.met === true ? import_picocolors31.default.green("\u2713") : c.met === false ? import_picocolors31.default.red("\u2717") : import_picocolors31.default.dim("\xB7");
9613
+ line(` ${tick} ${c.text} ${import_picocolors31.default.dim(c.id)}`);
9614
+ if (c.note) line(import_picocolors31.default.dim(` ${c.note}`));
9549
9615
  }
9550
9616
  }
9551
9617
  const current = progress.find((p) => p.name === g.currentPhase);
9552
9618
  if (current) {
9553
9619
  line(
9554
- import_picocolors30.default.dim(
9620
+ import_picocolors31.default.dim(
9555
9621
  `
9556
9622
  ${current.name} \u2014 ${current.done} of ${current.total} done (phase ${current.index} of ${progress.length}).`
9557
9623
  )
@@ -9561,15 +9627,15 @@ ${current.name} \u2014 ${current.done} of ${current.total} done (phase ${current
9561
9627
  function statusTag3(status) {
9562
9628
  switch (status) {
9563
9629
  case "agreed":
9564
- return import_picocolors30.default.cyan("[agreed]");
9630
+ return import_picocolors31.default.cyan("[agreed]");
9565
9631
  case "working":
9566
- return import_picocolors30.default.blue("[working]");
9632
+ return import_picocolors31.default.blue("[working]");
9567
9633
  case "delivered":
9568
- return import_picocolors30.default.green("[delivered]");
9634
+ return import_picocolors31.default.green("[delivered]");
9569
9635
  case "abandoned":
9570
- return import_picocolors30.default.dim("[abandoned]");
9636
+ return import_picocolors31.default.dim("[abandoned]");
9571
9637
  default:
9572
- return import_picocolors30.default.yellow("[proposed]");
9638
+ return import_picocolors31.default.yellow("[proposed]");
9573
9639
  }
9574
9640
  }
9575
9641
 
@@ -9622,7 +9688,15 @@ var READS = [
9622
9688
  // have `create` subcommands — these write the project's RECORD, not the
9623
9689
  // project. What stops a reviewer editing code is its filesystem mode, and
9624
9690
  // that is untouched.
9625
- "artifact"
9691
+ "artifact",
9692
+ // LEAVING A FACT FOR THE TEAM IS NOT CHANGING THE PROJECT — the same
9693
+ // argument as `artifact` directly above, and it belongs in READS rather than
9694
+ // BUILDS on purpose. The roles that DISCOVER things are the reading ones: a
9695
+ // tester that found the real cause, an analyst that found the actual column
9696
+ // name, a security engineer that found where a key is read from. A shared
9697
+ // memory only builders could write to would be missing most of what is worth
9698
+ // sharing. See the daemon's `team-memory.ts`.
9699
+ "note"
9626
9700
  ];
9627
9701
  var BUILDS = [
9628
9702
  ...READS,
@@ -9642,6 +9716,7 @@ var BUILDS = [
9642
9716
  ];
9643
9717
  var ROLE_VERBS = {
9644
9718
  pm: [...READS, "ask", "app"],
9719
+ // `note` reaches this via READS.
9645
9720
  architect: [...BUILDS, "versions"],
9646
9721
  web: BUILDS,
9647
9722
  api: BUILDS,
@@ -9744,7 +9819,7 @@ function stripLeadingGlobalOptions(argv) {
9744
9819
  }
9745
9820
 
9746
9821
  // src/commands/decision.ts
9747
- var import_picocolors31 = __toESM(require_picocolors(), 1);
9822
+ var import_picocolors32 = __toESM(require_picocolors(), 1);
9748
9823
  function registerDecision(program3) {
9749
9824
  const decision = program3.command("decision").description("Read and record the project's architecture decisions");
9750
9825
  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(
@@ -9757,11 +9832,11 @@ function registerDecision(program3) {
9757
9832
  rows = applyLimit(rows, opts.limit);
9758
9833
  ok(rows, () => {
9759
9834
  if (!rows.length) {
9760
- line(import_picocolors31.default.dim("No decisions recorded yet."));
9835
+ line(import_picocolors32.default.dim("No decisions recorded yet."));
9761
9836
  return;
9762
9837
  }
9763
9838
  for (const r of rows) {
9764
- line(`${import_picocolors31.default.dim(r.id)} ${import_picocolors31.default.dim(shortDate(r.createdAt))} ${r.title}`);
9839
+ line(`${import_picocolors32.default.dim(r.id)} ${import_picocolors32.default.dim(shortDate(r.createdAt))} ${r.title}`);
9765
9840
  line(` ${truncate(r.decision, 100)}`);
9766
9841
  }
9767
9842
  });
@@ -9775,16 +9850,16 @@ function registerDecision(program3) {
9775
9850
  `/v1/projects/${projectId}/architecture-decisions/${args[0]}`
9776
9851
  );
9777
9852
  ok(row, () => {
9778
- line(`${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.id)}`);
9779
- line(import_picocolors31.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
9853
+ line(`${import_picocolors32.default.bold(row.title)} ${import_picocolors32.default.dim(row.id)}`);
9854
+ line(import_picocolors32.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
9780
9855
  line(`
9781
- ${import_picocolors31.default.bold("Context")}
9856
+ ${import_picocolors32.default.bold("Context")}
9782
9857
  ${row.context}`);
9783
9858
  line(`
9784
- ${import_picocolors31.default.bold("Decision")}
9859
+ ${import_picocolors32.default.bold("Decision")}
9785
9860
  ${row.decision}`);
9786
9861
  if (row.consequences) line(`
9787
- ${import_picocolors31.default.bold("Consequences")}
9862
+ ${import_picocolors32.default.bold("Consequences")}
9788
9863
  ${row.consequences}`);
9789
9864
  });
9790
9865
  })
@@ -9813,7 +9888,7 @@ ${row.consequences}`);
9813
9888
  refId: row?.id,
9814
9889
  output: { decision: row }
9815
9890
  });
9816
- ok(row, () => line(`Recorded decision ${import_picocolors31.default.bold(row?.id ?? "")} \u2014 ${title}`));
9891
+ ok(row, () => line(`Recorded decision ${import_picocolors32.default.bold(row?.id ?? "")} \u2014 ${title}`));
9817
9892
  })
9818
9893
  );
9819
9894
  const requirement = program3.command("requirement").description("Read and record the project's requirements");
@@ -9825,11 +9900,11 @@ ${row.consequences}`);
9825
9900
  rows = applyLimit(rows, opts.limit);
9826
9901
  ok(rows, () => {
9827
9902
  if (!rows.length) {
9828
- line(import_picocolors31.default.dim("No requirements recorded yet."));
9903
+ line(import_picocolors32.default.dim("No requirements recorded yet."));
9829
9904
  return;
9830
9905
  }
9831
9906
  for (const r of rows) {
9832
- line(`${import_picocolors31.default.dim(r.id)} ${r.status.padEnd(9)} ${r.title}`);
9907
+ line(`${import_picocolors32.default.dim(r.id)} ${r.status.padEnd(9)} ${r.title}`);
9833
9908
  }
9834
9909
  });
9835
9910
  })
@@ -9842,8 +9917,8 @@ ${row.consequences}`);
9842
9917
  `/v1/projects/${projectId}/requirements/${args[0]}`
9843
9918
  );
9844
9919
  ok(row, () => {
9845
- line(`${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.id)}`);
9846
- line(import_picocolors31.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
9920
+ line(`${import_picocolors32.default.bold(row.title)} ${import_picocolors32.default.dim(row.id)}`);
9921
+ line(import_picocolors32.default.dim(`${row.status} \xB7 ${shortDate(row.createdAt)}`));
9847
9922
  line(`
9848
9923
  ${row.body}`);
9849
9924
  });
@@ -9869,7 +9944,7 @@ ${row.body}`);
9869
9944
  refId: row?.id,
9870
9945
  output: { requirement: row }
9871
9946
  });
9872
- ok(row, () => line(`Recorded requirement ${import_picocolors31.default.bold(row?.id ?? "")} \u2014 ${title}`));
9947
+ ok(row, () => line(`Recorded requirement ${import_picocolors32.default.bold(row?.id ?? "")} \u2014 ${title}`));
9873
9948
  })
9874
9949
  );
9875
9950
  requirement.command("update <id>").description(
@@ -9898,7 +9973,7 @@ ${row.body}`);
9898
9973
  code: "bad_request"
9899
9974
  });
9900
9975
  }
9901
- ok(row, () => line(`Updated requirement ${import_picocolors31.default.bold(row.id)} \u2014 ${row.title} (${row.status})`));
9976
+ ok(row, () => line(`Updated requirement ${import_picocolors32.default.bold(row.id)} \u2014 ${row.title} (${row.status})`));
9902
9977
  })
9903
9978
  );
9904
9979
  }
@@ -9921,7 +9996,7 @@ function shortDate(iso) {
9921
9996
  }
9922
9997
 
9923
9998
  // src/commands/doc.ts
9924
- var import_picocolors32 = __toESM(require_picocolors(), 1);
9999
+ var import_picocolors33 = __toESM(require_picocolors(), 1);
9925
10000
 
9926
10001
  // src/mermaid-fences.ts
9927
10002
  function hasDiagram(code) {
@@ -9966,13 +10041,13 @@ function registerDoc(program3) {
9966
10041
  }) ?? [];
9967
10042
  ok(rows, () => {
9968
10043
  if (!rows.length) {
9969
- line(import_picocolors32.default.dim("No documents yet."));
10044
+ line(import_picocolors33.default.dim("No documents yet."));
9970
10045
  return;
9971
10046
  }
9972
10047
  for (const r of rows) {
9973
- const link = r.workItemId ? import_picocolors32.default.dim(` \u21B3 ${r.workItemId}`) : "";
9974
- const file = r.filePath ? import_picocolors32.default.dim(` ${r.filePath}`) : "";
9975
- line(`${import_picocolors32.default.dim(r.id)} ${r.title}${link}${file}`);
10048
+ const link = r.workItemId ? import_picocolors33.default.dim(` \u21B3 ${r.workItemId}`) : "";
10049
+ const file = r.filePath ? import_picocolors33.default.dim(` ${r.filePath}`) : "";
10050
+ line(`${import_picocolors33.default.dim(r.id)} ${r.title}${link}${file}`);
9976
10051
  }
9977
10052
  });
9978
10053
  })
@@ -9986,17 +10061,17 @@ function registerDoc(program3) {
9986
10061
  );
9987
10062
  if (opts.markdown) {
9988
10063
  ok({ id: row.id, title: row.title, filePath: row.filePath }, () => {
9989
- line(`${import_picocolors32.default.bold(row.title)} ${import_picocolors32.default.dim(row.id)}`);
10064
+ line(`${import_picocolors33.default.bold(row.title)} ${import_picocolors33.default.dim(row.id)}`);
9990
10065
  line(
9991
- 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.")
10066
+ row.filePath ? `Read it at ${import_picocolors33.default.bold(row.filePath)} (relative to the project folder).` : import_picocolors33.default.dim("This document has no markdown mirror on disk yet.")
9992
10067
  );
9993
10068
  });
9994
10069
  return;
9995
10070
  }
9996
10071
  ok(row, () => {
9997
- line(`${import_picocolors32.default.bold(row.title)} ${import_picocolors32.default.dim(row.id)}`);
9998
- if (row.workItemId) line(import_picocolors32.default.dim(`linked to work item ${row.workItemId}`));
9999
- if (row.filePath) line(import_picocolors32.default.dim(`markdown mirror: ${row.filePath}`));
10072
+ line(`${import_picocolors33.default.bold(row.title)} ${import_picocolors33.default.dim(row.id)}`);
10073
+ if (row.workItemId) line(import_picocolors33.default.dim(`linked to work item ${row.workItemId}`));
10074
+ if (row.filePath) line(import_picocolors33.default.dim(`markdown mirror: ${row.filePath}`));
10000
10075
  line("");
10001
10076
  line(row.contentJson);
10002
10077
  });
@@ -10025,7 +10100,7 @@ function registerDoc(program3) {
10025
10100
  refId: row?.id,
10026
10101
  output: { document: row }
10027
10102
  });
10028
- ok(row, () => line(`Created document ${import_picocolors32.default.bold(row?.id ?? "")} \u2014 ${title}`));
10103
+ ok(row, () => line(`Created document ${import_picocolors33.default.bold(row?.id ?? "")} \u2014 ${title}`));
10029
10104
  })
10030
10105
  );
10031
10106
  doc.command("diagram <id>").description(
@@ -10051,19 +10126,19 @@ function registerDoc(program3) {
10051
10126
  diagrams: diagrams.map((code) => ({ kind: diagramKind(code), code }))
10052
10127
  };
10053
10128
  ok(payload, () => {
10054
- line(`${import_picocolors32.default.bold(row.title)} ${import_picocolors32.default.dim(row.id)}`);
10129
+ line(`${import_picocolors33.default.bold(row.title)} ${import_picocolors33.default.dim(row.id)}`);
10055
10130
  if (markdown === null) {
10056
10131
  line(
10057
- import_picocolors32.default.dim(
10132
+ import_picocolors33.default.dim(
10058
10133
  row.filePath ? `Could not read ${row.filePath} from this folder.` : "This document has no markdown mirror on disk yet."
10059
10134
  )
10060
10135
  );
10061
10136
  } else if (!diagrams.length) {
10062
- line(import_picocolors32.default.dim("No diagrams in this document."));
10137
+ line(import_picocolors33.default.dim("No diagrams in this document."));
10063
10138
  } else {
10064
10139
  for (const [i, code] of diagrams.entries()) {
10065
10140
  const kind = diagramKind(code) ?? "diagram";
10066
- line(`${import_picocolors32.default.dim(String(i + 1))} ${kind} ${import_picocolors32.default.dim(`${code.split("\n").length} lines`)}`);
10141
+ line(`${import_picocolors33.default.dim(String(i + 1))} ${kind} ${import_picocolors33.default.dim(`${code.split("\n").length} lines`)}`);
10067
10142
  }
10068
10143
  }
10069
10144
  });
@@ -10099,7 +10174,7 @@ function registerDoc(program3) {
10099
10174
  code: "bad_request"
10100
10175
  });
10101
10176
  }
10102
- ok(row, () => line(`Updated document ${import_picocolors32.default.bold(row.id)} \u2014 ${row.title}`));
10177
+ ok(row, () => line(`Updated document ${import_picocolors33.default.bold(row.id)} \u2014 ${row.title}`));
10103
10178
  })
10104
10179
  );
10105
10180
  }
@@ -10113,7 +10188,7 @@ function readMirror(cwd, filePath) {
10113
10188
  }
10114
10189
 
10115
10190
  // src/commands/design.ts
10116
- var import_picocolors33 = __toESM(require_picocolors(), 1);
10191
+ var import_picocolors34 = __toESM(require_picocolors(), 1);
10117
10192
  function registerDesign(program3) {
10118
10193
  const design = program3.command("design").description("Read the project's brand (colours, fonts, logo)");
10119
10194
  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(
@@ -10127,11 +10202,11 @@ function registerDesign(program3) {
10127
10202
  if (opts.raw) {
10128
10203
  ok(files, () => {
10129
10204
  if (!files.length) {
10130
- line(import_picocolors33.default.dim("No brand set for this project."));
10205
+ line(import_picocolors34.default.dim("No brand set for this project."));
10131
10206
  return;
10132
10207
  }
10133
10208
  for (const f of files) {
10134
- line(import_picocolors33.default.bold(f.path));
10209
+ line(import_picocolors34.default.bold(f.path));
10135
10210
  line(f.contents);
10136
10211
  line("");
10137
10212
  }
@@ -10148,21 +10223,21 @@ function registerDesign(program3) {
10148
10223
  } : { hasBrand: false, colors: {}, fonts: {}, brand: {}, files: [] };
10149
10224
  ok(summary, () => {
10150
10225
  if (!tokens) {
10151
- line(import_picocolors33.default.dim("No brand set for this project \u2014 choose sensible styling yourself."));
10226
+ line(import_picocolors34.default.dim("No brand set for this project \u2014 choose sensible styling yourself."));
10152
10227
  return;
10153
10228
  }
10154
10229
  for (const [name, value] of Object.entries(tokens.brand)) {
10155
- line(`${import_picocolors33.default.dim(name.padEnd(12))} ${value}`);
10230
+ line(`${import_picocolors34.default.dim(name.padEnd(12))} ${value}`);
10156
10231
  }
10157
10232
  for (const [name, value] of Object.entries(tokens.color)) {
10158
- line(`${import_picocolors33.default.dim(`color.${name}`.padEnd(12))} ${value}`);
10233
+ line(`${import_picocolors34.default.dim(`color.${name}`.padEnd(12))} ${value}`);
10159
10234
  }
10160
10235
  for (const [name, value] of Object.entries(tokens.font)) {
10161
- line(`${import_picocolors33.default.dim(`font.${name}`.padEnd(12))} ${value}`);
10236
+ line(`${import_picocolors34.default.dim(`font.${name}`.padEnd(12))} ${value}`);
10162
10237
  }
10163
10238
  line("");
10164
10239
  line(
10165
- import_picocolors33.default.dim(
10240
+ import_picocolors34.default.dim(
10166
10241
  `Generated into the working tree as ${files.map((f) => f.path).join(", ")} \u2014 wire those in, never edit them.`
10167
10242
  )
10168
10243
  );
@@ -10193,7 +10268,7 @@ function unwrap(group) {
10193
10268
  }
10194
10269
 
10195
10270
  // src/commands/api.ts
10196
- var import_picocolors34 = __toESM(require_picocolors(), 1);
10271
+ var import_picocolors35 = __toESM(require_picocolors(), 1);
10197
10272
  import { readdirSync, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
10198
10273
  import { join as join3, relative, sep } from "path";
10199
10274
 
@@ -10307,10 +10382,10 @@ function registerApi(program3) {
10307
10382
  const appId = requireApp2(opts.app);
10308
10383
  const res = await api(ctx, `/v1/apps/${encodeURIComponent(appId)}/api/requests`);
10309
10384
  ok(res, () => {
10310
- for (const note of res?.notes ?? []) line(import_picocolors34.default.dim(note));
10385
+ for (const note of res?.notes ?? []) line(import_picocolors35.default.dim(note));
10311
10386
  for (const r of res?.requests ?? []) {
10312
10387
  line(
10313
- `${import_picocolors34.default.dim(r.method.padEnd(6))}${r.path}${r.note ? import_picocolors34.default.dim(` ${r.note}`) : ""}`
10388
+ `${import_picocolors35.default.dim(r.method.padEnd(6))}${r.path}${r.note ? import_picocolors35.default.dim(` ${r.note}`) : ""}`
10314
10389
  );
10315
10390
  }
10316
10391
  });
@@ -10344,14 +10419,14 @@ function registerApi(program3) {
10344
10419
  );
10345
10420
  ok(res, () => {
10346
10421
  if (!res?.ok) {
10347
- line(import_picocolors34.default.red(res?.error ?? "The service did not answer."));
10422
+ line(import_picocolors35.default.red(res?.error ?? "The service did not answer."));
10348
10423
  return;
10349
10424
  }
10350
10425
  const code = `${res.status}${res.statusText ? ` ${res.statusText}` : ""}`;
10351
- const colour2 = res.status && res.status < 300 ? import_picocolors34.default.green : res.status && res.status < 500 ? import_picocolors34.default.yellow : import_picocolors34.default.red;
10352
- line(`${colour2(code)} ${import_picocolors34.default.dim(`${res.durationMs}ms ${res.url}`)}`);
10426
+ const colour2 = res.status && res.status < 300 ? import_picocolors35.default.green : res.status && res.status < 500 ? import_picocolors35.default.yellow : import_picocolors35.default.red;
10427
+ line(`${colour2(code)} ${import_picocolors35.default.dim(`${res.durationMs}ms ${res.url}`)}`);
10353
10428
  if (res.body) line(res.body);
10354
- if (res.truncated) line(import_picocolors34.default.dim("(answer truncated)"));
10429
+ if (res.truncated) line(import_picocolors35.default.dim("(answer truncated)"));
10355
10430
  });
10356
10431
  if (!res?.ok) process.exitCode = 1;
10357
10432
  })
@@ -10371,15 +10446,15 @@ function registerApi(program3) {
10371
10446
  for (const r of report.routes) {
10372
10447
  const known = report.missing.some((m) => m.path === r.path);
10373
10448
  line(
10374
- `${known ? import_picocolors34.default.yellow("undocumented") : import_picocolors34.default.green("documented ")} ${r.path}${import_picocolors34.default.dim(` ${r.file}`)}`
10449
+ `${known ? import_picocolors35.default.yellow("undocumented") : import_picocolors35.default.green("documented ")} ${r.path}${import_picocolors35.default.dim(` ${r.file}`)}`
10375
10450
  );
10376
10451
  }
10377
10452
  for (const p of report.stale) {
10378
- line(`${import_picocolors34.default.dim("in spec only ")} ${p}`);
10453
+ line(`${import_picocolors35.default.dim("in spec only ")} ${p}`);
10379
10454
  }
10380
10455
  line("");
10381
10456
  if (report.ok && specFile) success(summary);
10382
- else line(import_picocolors34.default.yellow(summary));
10457
+ else line(import_picocolors35.default.yellow(summary));
10383
10458
  });
10384
10459
  if (opts.check && !report.ok) {
10385
10460
  throw new WorkserError(summary, { code: "bad_request" });
@@ -10450,7 +10525,7 @@ function listRepoFiles(root, maxDepth = 8) {
10450
10525
  }
10451
10526
 
10452
10527
  // src/commands/analysis.ts
10453
- var import_picocolors35 = __toESM(require_picocolors(), 1);
10528
+ var import_picocolors36 = __toESM(require_picocolors(), 1);
10454
10529
  import { readFileSync as readFileSync4 } from "fs";
10455
10530
  function registerAnalysis(program3) {
10456
10531
  const cmd = program3.command("analysis").description("Run Python analysis locally, recorded in the task");
@@ -10460,14 +10535,14 @@ function registerAnalysis(program3) {
10460
10535
  const res = await api(ctx, path);
10461
10536
  ok(res, () => {
10462
10537
  line(
10463
- `${res?.available ? import_picocolors35.default.green("python") : import_picocolors35.default.red("python")} ${res?.version ?? "not found"} ${import_picocolors35.default.dim(res?.python ?? "")}`
10538
+ `${res?.available ? import_picocolors36.default.green("python") : import_picocolors36.default.red("python")} ${res?.version ?? "not found"} ${import_picocolors36.default.dim(res?.python ?? "")}`
10464
10539
  );
10465
10540
  for (const lib of res?.libraries ?? []) {
10466
10541
  line(
10467
- `${lib.present ? import_picocolors35.default.green(lib.name) : import_picocolors35.default.yellow(lib.name)}${import_picocolors35.default.dim(lib.present ? "" : " missing")}`
10542
+ `${lib.present ? import_picocolors36.default.green(lib.name) : import_picocolors36.default.yellow(lib.name)}${import_picocolors36.default.dim(lib.present ? "" : " missing")}`
10468
10543
  );
10469
10544
  }
10470
- for (const note of res?.notes ?? []) line(import_picocolors35.default.dim(note));
10545
+ for (const note of res?.notes ?? []) line(import_picocolors36.default.dim(note));
10471
10546
  });
10472
10547
  if (!res?.available) process.exitCode = 1;
10473
10548
  })
@@ -10489,15 +10564,15 @@ function registerAnalysis(program3) {
10489
10564
  );
10490
10565
  ok(res, () => {
10491
10566
  if (res?.stdout) line(res.stdout.replace(/\n$/, ""));
10492
- if (res?.stderr) line(import_picocolors35.default.dim(res.stderr.replace(/\n$/, "")));
10493
- if (res?.truncated) line(import_picocolors35.default.dim("(output truncated)"));
10567
+ if (res?.stderr) line(import_picocolors36.default.dim(res.stderr.replace(/\n$/, "")));
10568
+ if (res?.truncated) line(import_picocolors36.default.dim("(output truncated)"));
10494
10569
  const took = `${Math.round((res?.durationMs ?? 0) / 100) / 10}s`;
10495
10570
  line(
10496
- 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}`)
10571
+ res?.ok ? import_picocolors36.default.green(`\u2713 ${res.summary ?? "It finished."}`) + import_picocolors36.default.dim(` ${took}`) : import_picocolors36.default.yellow(res?.summary ?? "It did not finish.") + import_picocolors36.default.dim(` ${took}`)
10497
10572
  );
10498
10573
  if (res && !res.sandboxed) {
10499
10574
  line(
10500
- import_picocolors35.default.dim(
10575
+ import_picocolors36.default.dim(
10501
10576
  "This platform has no OS sandbox, so the script ran with your own file access."
10502
10577
  )
10503
10578
  );
@@ -10525,7 +10600,7 @@ function readCode(file, inline) {
10525
10600
  }
10526
10601
 
10527
10602
  // src/commands/scan.ts
10528
- var import_picocolors36 = __toESM(require_picocolors(), 1);
10603
+ var import_picocolors37 = __toESM(require_picocolors(), 1);
10529
10604
  import { spawnSync as spawnSync2 } from "child_process";
10530
10605
  import { existsSync as existsSync3, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
10531
10606
  import { join as join4, relative as relative2, sep as sep2 } from "path";
@@ -10809,22 +10884,22 @@ function runPermissions(cwd, findings, checked, skipped) {
10809
10884
  }
10810
10885
  function print2(report, summary) {
10811
10886
  for (const s of report.skipped) {
10812
- line(`${import_picocolors36.default.yellow("not checked")} ${s.check}${import_picocolors36.default.dim(` \u2014 ${s.reason}`)}`);
10887
+ line(`${import_picocolors37.default.yellow("not checked")} ${s.check}${import_picocolors37.default.dim(` \u2014 ${s.reason}`)}`);
10813
10888
  }
10814
10889
  for (const f of report.findings) {
10815
- const where = f.file ? import_picocolors36.default.dim(` ${f.file}${f.line ? `:${f.line}` : ""}`) : "";
10890
+ const where = f.file ? import_picocolors37.default.dim(` ${f.file}${f.line ? `:${f.line}` : ""}`) : "";
10816
10891
  line(`${severityTag(f.severity)} ${f.title}${where}`);
10817
- line(` ${import_picocolors36.default.dim(f.fix)}`);
10892
+ line(` ${import_picocolors37.default.dim(f.fix)}`);
10818
10893
  }
10819
10894
  if (report.findings.length || report.skipped.length) line("");
10820
10895
  if (report.ok && !report.skipped.length) success(summary);
10821
- else if (report.ok) line(import_picocolors36.default.yellow(summary));
10822
- else line(import_picocolors36.default.red(summary));
10896
+ else if (report.ok) line(import_picocolors37.default.yellow(summary));
10897
+ else line(import_picocolors37.default.red(summary));
10823
10898
  }
10824
10899
  function severityTag(severity) {
10825
- if (severity === "high") return import_picocolors36.default.red("serious ");
10826
- if (severity === "medium") return import_picocolors36.default.yellow("worth fixing");
10827
- return import_picocolors36.default.dim("minor ");
10900
+ if (severity === "high") return import_picocolors37.default.red("serious ");
10901
+ if (severity === "medium") return import_picocolors37.default.yellow("worth fixing");
10902
+ return import_picocolors37.default.dim("minor ");
10828
10903
  }
10829
10904
  function git(cwd, args) {
10830
10905
  try {
@@ -10885,7 +10960,7 @@ function listRepoFiles2(root, maxDepth = 8) {
10885
10960
  }
10886
10961
 
10887
10962
  // src/commands/health.ts
10888
- var import_picocolors37 = __toESM(require_picocolors(), 1);
10963
+ var import_picocolors38 = __toESM(require_picocolors(), 1);
10889
10964
  function registerHealth(program3) {
10890
10965
  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(
10891
10966
  action(async ({ ctx, opts }) => {
@@ -10899,16 +10974,16 @@ function registerHealth(program3) {
10899
10974
  }
10900
10975
  function print3(res) {
10901
10976
  if (!res?.checks?.length) {
10902
- line(import_picocolors37.default.dim(res?.note ?? "Nothing to check."));
10977
+ line(import_picocolors38.default.dim(res?.note ?? "Nothing to check."));
10903
10978
  return;
10904
10979
  }
10905
10980
  for (const c of res.checks) {
10906
- const mark = c.ok ? import_picocolors37.default.green("up ") : import_picocolors37.default.red("down");
10907
- const timing = import_picocolors37.default.dim(`${c.ms}ms`);
10908
- const detail = c.ok ? timing : import_picocolors37.default.dim(`${c.error ?? "no answer"}${c.failures > 1 ? ` \xB7 ${c.failures} in a row` : ""}`);
10909
- line(` ${mark} ${c.appName} ${import_picocolors37.default.dim(`(${c.environment})`)} ${c.url} ${detail}`);
10981
+ const mark = c.ok ? import_picocolors38.default.green("up ") : import_picocolors38.default.red("down");
10982
+ const timing = import_picocolors38.default.dim(`${c.ms}ms`);
10983
+ const detail = c.ok ? timing : import_picocolors38.default.dim(`${c.error ?? "no answer"}${c.failures > 1 ? ` \xB7 ${c.failures} in a row` : ""}`);
10984
+ line(` ${mark} ${c.appName} ${import_picocolors38.default.dim(`(${c.environment})`)} ${c.url} ${detail}`);
10910
10985
  if (c.incidentOpened) {
10911
- line(import_picocolors37.default.yellow(` An incident has been opened on the board for this.`));
10986
+ line(import_picocolors38.default.yellow(` An incident has been opened on the board for this.`));
10912
10987
  }
10913
10988
  }
10914
10989
  const down = res.checks.filter((c) => !c.ok);
@@ -10921,14 +10996,14 @@ function print3(res) {
10921
10996
  }
10922
10997
  const production = down.filter((c) => c.environment === "production").length;
10923
10998
  line(
10924
- import_picocolors37.default.red(
10999
+ import_picocolors38.default.red(
10925
11000
  `${down.length} of ${res.checks.length} not answering` + (production ? ` \u2014 ${production} customer-facing.` : " (preview only).")
10926
11001
  )
10927
11002
  );
10928
11003
  }
10929
11004
 
10930
11005
  // src/commands/urls.ts
10931
- var import_picocolors38 = __toESM(require_picocolors(), 1);
11006
+ var import_picocolors39 = __toESM(require_picocolors(), 1);
10932
11007
  function registerUrls(program3) {
10933
11008
  program3.command("urls").description("The stable preview and production addresses of every app in this project").option("--app <webAppId>", "just one app").action(
10934
11009
  action(async ({ ctx, opts }) => {
@@ -10942,20 +11017,20 @@ function registerUrls(program3) {
10942
11017
  const summary = urlsSummary(rows);
10943
11018
  ok({ rows, summary }, () => {
10944
11019
  for (const row of rows) {
10945
- const label = import_picocolors38.default.dim(row.environment.padEnd(10));
10946
- const value = row.url ? import_picocolors38.default.cyan(row.url) : import_picocolors38.default.dim(row.note ?? "not published");
11020
+ const label = import_picocolors39.default.dim(row.environment.padEnd(10));
11021
+ const value = row.url ? import_picocolors39.default.cyan(row.url) : import_picocolors39.default.dim(row.note ?? "not published");
10947
11022
  line(` ${row.appName.padEnd(22)} ${label} ${value}`);
10948
11023
  }
10949
11024
  line("");
10950
11025
  if (rows.some((r) => r.url)) success(summary);
10951
- else line(import_picocolors38.default.yellow(summary));
11026
+ else line(import_picocolors39.default.yellow(summary));
10952
11027
  });
10953
11028
  })
10954
11029
  );
10955
11030
  }
10956
11031
 
10957
11032
  // src/commands/deployments.ts
10958
- var import_picocolors39 = __toESM(require_picocolors(), 1);
11033
+ var import_picocolors40 = __toESM(require_picocolors(), 1);
10959
11034
  function registerDeployments(program3) {
10960
11035
  const cmd = program3.command("deployments").description("Deployment history, and putting a build in front of customers");
10961
11036
  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(
@@ -10973,7 +11048,7 @@ function registerDeployments(program3) {
10973
11048
  ok(res, () => {
10974
11049
  if (!items.length) {
10975
11050
  return line(
10976
- import_picocolors39.default.dim(
11051
+ import_picocolors40.default.dim(
10977
11052
  environment ? `Nothing has been deployed to ${environment} yet.` : "Nothing has been deployed yet. `workser deploy` builds the first one."
10978
11053
  )
10979
11054
  );
@@ -10993,13 +11068,13 @@ function registerDeployments(program3) {
10993
11068
  ).catch(() => null) : null;
10994
11069
  ok({ ...dep, logs }, () => {
10995
11070
  line(formatDeployment(dep));
10996
- if (dep?.error_message) line(import_picocolors39.default.red(` ${dep.error_message}`));
11071
+ if (dep?.error_message) line(import_picocolors40.default.red(` ${dep.error_message}`));
10997
11072
  const events = logs?.events ?? [];
10998
11073
  for (const e of events) {
10999
- line(` ${import_picocolors39.default.dim(String(e.type ?? "log"))} ${e.text ?? ""}`);
11074
+ line(` ${import_picocolors40.default.dim(String(e.type ?? "log"))} ${e.text ?? ""}`);
11000
11075
  }
11001
11076
  if (opts.logs && !events.length) {
11002
- line(import_picocolors39.default.dim(" That build produced no output."));
11077
+ line(import_picocolors40.default.dim(" That build produced no output."));
11003
11078
  }
11004
11079
  });
11005
11080
  })
@@ -11043,16 +11118,16 @@ function printPromoted(res, version) {
11043
11118
  const what = version === null ? "the latest build" : `version ${version}`;
11044
11119
  const url = res.url ?? res.vercel_url;
11045
11120
  success(`Production is being rebuilt from ${what}.`);
11046
- if (url) line(import_picocolors39.default.dim(`It will be at ${url}`));
11047
- line(import_picocolors39.default.dim("`workser deploy status` follows it."));
11121
+ if (url) line(import_picocolors40.default.dim(`It will be at ${url}`));
11122
+ line(import_picocolors40.default.dim("`workser deploy status` follows it."));
11048
11123
  }
11049
11124
  function formatDeployment(d) {
11050
11125
  if (!d) return "";
11051
- const version = d.version !== void 0 ? import_picocolors39.default.yellow(`v${d.version}`) : import_picocolors39.default.dim("v?");
11052
- const env = import_picocolors39.default.dim((d.environment ?? "?").padEnd(10));
11126
+ const version = d.version !== void 0 ? import_picocolors40.default.yellow(`v${d.version}`) : import_picocolors40.default.dim("v?");
11127
+ const env = import_picocolors40.default.dim((d.environment ?? "?").padEnd(10));
11053
11128
  const app = d.webAppName ? `${d.webAppName} ` : "";
11054
- const when = import_picocolors39.default.dim(formatTime2(d.created_at));
11055
- const url = d.url ? " " + import_picocolors39.default.cyan(d.url) : "";
11129
+ const when = import_picocolors40.default.dim(formatTime2(d.created_at));
11130
+ const url = d.url ? " " + import_picocolors40.default.cyan(d.url) : "";
11056
11131
  return `${version} ${env} ${colorStatus(d.status ?? "")} ${app}${when}${url}`;
11057
11132
  }
11058
11133
  function formatTime2(t) {
@@ -11062,7 +11137,7 @@ function formatTime2(t) {
11062
11137
  }
11063
11138
 
11064
11139
  // src/commands/usage.ts
11065
- var import_picocolors40 = __toESM(require_picocolors(), 1);
11140
+ var import_picocolors41 = __toESM(require_picocolors(), 1);
11066
11141
 
11067
11142
  // src/usage.ts
11068
11143
  var NEAR_LIMIT_FRACTION = 0.8;
@@ -11157,7 +11232,7 @@ function registerUsage(program3) {
11157
11232
  function print4(report) {
11158
11233
  const dims = report.dimensions ?? [];
11159
11234
  if (!dims.length) {
11160
- return line(import_picocolors40.default.dim("Nothing to measure for this project yet."));
11235
+ return line(import_picocolors41.default.dim("Nothing to measure for this project yet."));
11161
11236
  }
11162
11237
  const width = Math.max(...dims.map((d) => d.label.length));
11163
11238
  for (const d of dims) {
@@ -11166,23 +11241,23 @@ function print4(report) {
11166
11241
  line("");
11167
11242
  const summary = usageSummary(report);
11168
11243
  const worst = dims.map(usageState);
11169
- if (worst.includes("over")) line(import_picocolors40.default.red(summary));
11244
+ if (worst.includes("over")) line(import_picocolors41.default.red(summary));
11170
11245
  else if (worst.includes("near") || worst.includes("unknown"))
11171
- line(import_picocolors40.default.yellow(summary));
11246
+ line(import_picocolors41.default.yellow(summary));
11172
11247
  else success(summary);
11173
11248
  }
11174
11249
  function gauge(d, _labelWidth) {
11175
11250
  const drawn = bar(d);
11176
- return drawn ? ` ${import_picocolors40.default.dim(drawn)}` : "";
11251
+ return drawn ? ` ${import_picocolors41.default.dim(drawn)}` : "";
11177
11252
  }
11178
11253
  function colour(d) {
11179
11254
  switch (usageState(d)) {
11180
11255
  case "over":
11181
- return d.kind === "hard" ? import_picocolors40.default.red : import_picocolors40.default.yellow;
11256
+ return d.kind === "hard" ? import_picocolors41.default.red : import_picocolors41.default.yellow;
11182
11257
  case "near":
11183
- return import_picocolors40.default.yellow;
11258
+ return import_picocolors41.default.yellow;
11184
11259
  case "unknown":
11185
- return import_picocolors40.default.dim;
11260
+ return import_picocolors41.default.dim;
11186
11261
  default:
11187
11262
  return (s) => s;
11188
11263
  }
@@ -11190,7 +11265,7 @@ function colour(d) {
11190
11265
 
11191
11266
  // src/index.ts
11192
11267
  var pkg = {
11193
- version: true ? "0.6.12" : "0.0.0-dev"
11268
+ version: true ? "0.6.13" : "0.0.0-dev"
11194
11269
  };
11195
11270
  var program2 = new Command();
11196
11271
  program2.name("workser").description(
@@ -11237,6 +11312,7 @@ registerWorkflow(program2);
11237
11312
  registerConnection(program2);
11238
11313
  registerTool(program2);
11239
11314
  registerMemory(program2);
11315
+ registerNote(program2);
11240
11316
  registerBusiness(program2);
11241
11317
  registerArtifact(program2);
11242
11318
  registerImage(program2);