@workser/cli 0.6.11 → 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;
@@ -8684,6 +8750,13 @@ function parseRefs(raw) {
8684
8750
 
8685
8751
  // src/commands/task.ts
8686
8752
  var STATUSES2 = [
8753
+ /**
8754
+ * LISTED, NOT PLANNED. A goal's later phases get their tasks written down
8755
+ * when the plan is agreed, so the owner can read the whole shape — but those
8756
+ * rows have no subtasks and the runner must never pick them up. `todo` keeps
8757
+ * its meaning: the team may start this now.
8758
+ */
8759
+ "backlog",
8687
8760
  "todo",
8688
8761
  "working",
8689
8762
  "checking",
@@ -8691,6 +8764,8 @@ var STATUSES2 = [
8691
8764
  "accepted",
8692
8765
  "archived"
8693
8766
  ];
8767
+ var PRIORITIES2 = ["urgent", "high", "normal", "low"];
8768
+ var SIZES = ["small", "standard"];
8694
8769
  var ROLES = [
8695
8770
  "pm",
8696
8771
  "architect",
@@ -8743,7 +8818,7 @@ function registerTask(program3) {
8743
8818
  }) ?? [];
8744
8819
  ok(rows, () => {
8745
8820
  if (!rows.length) {
8746
- line(import_picocolors29.default.dim("No tasks on the board yet."));
8821
+ line(import_picocolors30.default.dim("No tasks on the board yet."));
8747
8822
  return;
8748
8823
  }
8749
8824
  for (const r of rows) line(formatRow2(r));
@@ -8770,10 +8845,21 @@ function registerTask(program3) {
8770
8845
  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(
8771
8846
  "--phase <name>",
8772
8847
  "which slice of that goal \u2014 must match one of its phase names"
8848
+ ).option("--priority <value>", `how urgent (${PRIORITIES2.join(" | ")})`).option(
8849
+ "--size <value>",
8850
+ `small lets the channel start it without asking; standard asks (${SIZES.join(" | ")})`
8851
+ ).option(
8852
+ "--status <value>",
8853
+ `start it somewhere other than 'todo' \u2014 use 'backlog' for a later phase's work (${STATUSES2.join(" | ")})`
8773
8854
  ).action(
8774
8855
  action(async ({ ctx, args, opts }) => {
8775
8856
  requireProject(ctx);
8776
8857
  if (opts.kind !== void 0) assertOneOf("--kind", opts.kind, KINDS2);
8858
+ if (opts.priority !== void 0)
8859
+ assertOneOf("--priority", opts.priority, PRIORITIES2);
8860
+ if (opts.size !== void 0) assertOneOf("--size", opts.size, SIZES);
8861
+ if (opts.status !== void 0)
8862
+ assertOneOf("--status", opts.status, STATUSES2);
8777
8863
  const hasChannelOrigin = Boolean(
8778
8864
  ctx.projectChannelId && ctx.projectChannelMessageId
8779
8865
  );
@@ -8787,6 +8873,11 @@ function registerTask(program3) {
8787
8873
  // a goal has to be argued for, never assumed.
8788
8874
  goalId: opts.goal,
8789
8875
  phase: opts.phase,
8876
+ priority: opts.priority,
8877
+ size: opts.size,
8878
+ // `backlog` for a later phase's work: written down so the owner can
8879
+ // read the whole plan, with nothing for the runner to pick up.
8880
+ status: opts.status,
8790
8881
  targets: [
8791
8882
  ...(opts.app ?? []).map((appId) => ({
8792
8883
  kind: "app",
@@ -8836,10 +8927,10 @@ function registerTask(program3) {
8836
8927
  };
8837
8928
  ok(result, () => {
8838
8929
  line(
8839
- `${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)}`
8840
8931
  );
8841
8932
  if (channelMessage)
8842
- 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"));
8843
8934
  if (channelMessageError) {
8844
8935
  warn(
8845
8936
  `Task opened, but its Project Manager card could not be posted: ${channelMessageError.message}`
@@ -8918,12 +9009,12 @@ function registerTask(program3) {
8918
9009
  ) : null;
8919
9010
  ok(runner ?? row, () => {
8920
9011
  line(
8921
- `${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)}`
8922
9013
  );
8923
- if (row.role) line(import_picocolors29.default.dim(`role: ${row.role}`));
9014
+ if (row.role) line(import_picocolors30.default.dim(`role: ${row.role}`));
8924
9015
  if (runner) {
8925
9016
  line(
8926
- import_picocolors29.default.dim(
9017
+ import_picocolors30.default.dim(
8927
9018
  `runs on: ${[opts.agent, opts.model, opts.effort].filter(Boolean).join(" \xB7 ")}`
8928
9019
  )
8929
9020
  );
@@ -8941,7 +9032,7 @@ function registerTask(program3) {
8941
9032
  const rows = row.subtasks ?? [];
8942
9033
  ok(rows, () => {
8943
9034
  if (!rows.length) {
8944
- line(import_picocolors29.default.dim("No subtasks yet."));
9035
+ line(import_picocolors30.default.dim("No subtasks yet."));
8945
9036
  return;
8946
9037
  }
8947
9038
  rows.forEach((r, i) => line(formatSubtask(r, i + 1)));
@@ -8989,7 +9080,7 @@ function registerTask(program3) {
8989
9080
  }
8990
9081
  }
8991
9082
  );
8992
- 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)}`));
8993
9084
  })
8994
9085
  );
8995
9086
  subtask.command("remove <id>").description("Remove a subtask (only before the work starts)").action(
@@ -8997,7 +9088,7 @@ function registerTask(program3) {
8997
9088
  await api(ctx, `/v1/project-tasks/${encodeURIComponent(args[0])}`, {
8998
9089
  method: "DELETE"
8999
9090
  });
9000
- ok({ removed: args[0] }, () => line(import_picocolors29.default.green("removed")));
9091
+ ok({ removed: args[0] }, () => line(import_picocolors30.default.green("removed")));
9001
9092
  })
9002
9093
  );
9003
9094
  task.command("move <id> <status>").description(
@@ -9012,7 +9103,7 @@ function registerTask(program3) {
9012
9103
  );
9013
9104
  ok(
9014
9105
  row,
9015
- () => 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]}`)
9016
9107
  );
9017
9108
  })
9018
9109
  );
@@ -9028,18 +9119,18 @@ function registerTask(program3) {
9028
9119
  );
9029
9120
  ok(row, () => {
9030
9121
  if (!row?.queued) {
9031
- 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"));
9032
9123
  return;
9033
9124
  }
9034
9125
  const started = row.started ?? 0;
9035
9126
  if (started > 0) {
9036
9127
  line(
9037
- `${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`
9038
9129
  );
9039
9130
  return;
9040
9131
  }
9041
9132
  line(
9042
- `${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.`
9043
9134
  );
9044
9135
  });
9045
9136
  })
@@ -9053,11 +9144,11 @@ function registerTask(program3) {
9053
9144
  );
9054
9145
  ok(row, () => {
9055
9146
  if (row?.reopened) {
9056
- 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`);
9057
9148
  return;
9058
9149
  }
9059
9150
  line(
9060
- import_picocolors29.default.yellow(
9151
+ import_picocolors30.default.yellow(
9061
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"
9062
9153
  )
9063
9154
  );
@@ -9074,7 +9165,7 @@ function registerTask(program3) {
9074
9165
  `/v1/project-tasks/${encodeURIComponent(id)}/dispatch-check`,
9075
9166
  { method: "POST" }
9076
9167
  );
9077
- 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")));
9078
9169
  })
9079
9170
  );
9080
9171
  task.command("start [id]").description(
@@ -9089,13 +9180,13 @@ function registerTask(program3) {
9089
9180
  const started = row?.started ?? null;
9090
9181
  if (started && started > 0) {
9091
9182
  line(
9092
- import_picocolors29.default.green(
9183
+ import_picocolors30.default.green(
9093
9184
  `started ${started} step${started === 1 ? "" : "s"} \u2014 they are running now`
9094
9185
  )
9095
9186
  );
9096
9187
  return;
9097
9188
  }
9098
- line(import_picocolors29.default.yellow(row?.note ?? "Nothing started."));
9189
+ line(import_picocolors30.default.yellow(row?.note ?? "Nothing started."));
9099
9190
  });
9100
9191
  })
9101
9192
  );
@@ -9110,7 +9201,7 @@ function registerTask(program3) {
9110
9201
  );
9111
9202
  ok({ awaiting: row2.approval_state === "awaiting", task: row2 }, () => {
9112
9203
  line(
9113
- row2.approval_state === "awaiting" ? import_picocolors29.default.yellow(
9204
+ row2.approval_state === "awaiting" ? import_picocolors30.default.yellow(
9114
9205
  "The plan is waiting on the owner. They see it in the task."
9115
9206
  ) : `Already ${row2.approval_state}.`
9116
9207
  );
@@ -9135,7 +9226,7 @@ function registerTask(program3) {
9135
9226
  );
9136
9227
  ok(
9137
9228
  row,
9138
- () => 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)}`)
9139
9230
  );
9140
9231
  })
9141
9232
  );
@@ -9151,7 +9242,7 @@ function registerTask(program3) {
9151
9242
  `/v1/project-tasks/${encodeURIComponent(id)}/move`,
9152
9243
  { body: { status: "ready" } }
9153
9244
  );
9154
- 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)}`));
9155
9246
  })
9156
9247
  );
9157
9248
  }
@@ -9196,24 +9287,24 @@ function assertOneOf(flag, value, allowed) {
9196
9287
  }
9197
9288
  }
9198
9289
  function formatRow2(r) {
9199
- const key = import_picocolors29.default.dim((r.key ?? r.id.slice(0, 8)).padEnd(10));
9200
- const steps = r.subtaskTotal ? import_picocolors29.default.dim(` ${r.subtaskDone}/${r.subtaskTotal}`) : "";
9201
- 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") : "";
9202
9293
  return `${key} ${statusTag2(r.status)} ${r.title}${steps}${gate}`;
9203
9294
  }
9204
9295
  function formatSubtask(r, index) {
9205
- const n = import_picocolors29.default.dim(String(index).padStart(2, "0"));
9206
- const role = r.role ? import_picocolors29.default.dim(` [${r.role}]`) : "";
9207
- 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(", ")}`) : "";
9208
9299
  const head = `${n} ${statusTag2(r.status)} ${r.title}${role}${scope}`;
9209
9300
  const summary = (r.result_summary ?? "").trim();
9210
9301
  if (!summary) return head;
9211
9302
  const wrapped = summary.split("\n").map((l) => ` ${l}`).join("\n");
9212
9303
  return `${head}
9213
- ${import_picocolors29.default.dim(wrapped)}`;
9304
+ ${import_picocolors30.default.dim(wrapped)}`;
9214
9305
  }
9215
9306
  function printTask(row, goal) {
9216
- 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)}`);
9217
9308
  line(`${statusTag2(row.status)} approval: ${row.approval_state}`);
9218
9309
  if (row.summary) line(`
9219
9310
  ${row.summary}`);
@@ -9226,53 +9317,53 @@ touches: ${row.targets.map((t) => t.appName ?? t.ref ?? t.kind).join(", ")}`
9226
9317
  }
9227
9318
  if (row.subtasks?.length) {
9228
9319
  line(`
9229
- ${import_picocolors29.default.bold("subtasks")}`);
9320
+ ${import_picocolors30.default.bold("subtasks")}`);
9230
9321
  row.subtasks.forEach((s, i) => line(formatSubtask(s, i + 1)));
9231
9322
  line(
9232
- import_picocolors29.default.dim(
9323
+ import_picocolors30.default.dim(
9233
9324
  `
9234
9325
  Run \`workser artifact list\` to see what these subtasks produced,`
9235
9326
  )
9236
9327
  );
9237
9328
  line(
9238
- import_picocolors29.default.dim(
9329
+ import_picocolors30.default.dim(
9239
9330
  `or \`workser artifact list --step <id>\` for one subtask's output alone.`
9240
9331
  )
9241
9332
  );
9242
9333
  } else {
9243
- line(import_picocolors29.default.dim("\nNo subtasks yet."));
9334
+ line(import_picocolors30.default.dim("\nNo subtasks yet."));
9244
9335
  }
9245
9336
  }
9246
9337
  function printGoalContext(row, goal) {
9247
9338
  const mine = row.phase ?? null;
9248
9339
  line(`
9249
- ${import_picocolors29.default.bold("part of")}: ${goal.title}`);
9250
- 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}`));
9251
9342
  const progress = goal.progress ?? [];
9252
9343
  for (const p of progress) {
9253
9344
  const where = p.total === 0 ? "not started" : `${p.done} of ${p.total} done`;
9254
- const here = mine && p.name === mine ? import_picocolors29.default.cyan(" <- this task") : "";
9255
- 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("-");
9256
9347
  line(` ${mark} ${p.name} \u2014 ${where}${here}`);
9257
9348
  }
9258
9349
  const next = progress.find((p) => p.state !== "done");
9259
9350
  const running = progress.some((p) => p.state === "working");
9260
9351
  if (next && !running) {
9261
9352
  line(
9262
- import_picocolors29.default.dim(
9353
+ import_picocolors30.default.dim(
9263
9354
  `
9264
9355
  Nothing is running. The next part waiting is "${next.name}" \u2014 offer it to them in a sentence rather than starting it unasked.`
9265
9356
  )
9266
9357
  );
9267
9358
  } else if (!next) {
9268
9359
  line(
9269
- import_picocolors29.default.dim(
9360
+ import_picocolors30.default.dim(
9270
9361
  "\nEvery part of this plan is done. Say so, and offer to wrap it up."
9271
9362
  )
9272
9363
  );
9273
9364
  }
9274
9365
  line(
9275
- import_picocolors29.default.dim(
9366
+ import_picocolors30.default.dim(
9276
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."
9277
9368
  )
9278
9369
  );
@@ -9280,22 +9371,22 @@ Nothing is running. The next part waiting is "${next.name}" \u2014 offer it to t
9280
9371
  function statusTag2(status) {
9281
9372
  switch (status) {
9282
9373
  case "ready":
9283
- return import_picocolors29.default.green("[ready]");
9374
+ return import_picocolors30.default.green("[ready]");
9284
9375
  case "working":
9285
- return import_picocolors29.default.blue("[working]");
9376
+ return import_picocolors30.default.blue("[working]");
9286
9377
  case "checking":
9287
- return import_picocolors29.default.cyan("[checking]");
9378
+ return import_picocolors30.default.cyan("[checking]");
9288
9379
  case "accepted":
9289
- return import_picocolors29.default.green("[accepted]");
9380
+ return import_picocolors30.default.green("[accepted]");
9290
9381
  case "archived":
9291
- return import_picocolors29.default.dim("[archived]");
9382
+ return import_picocolors30.default.dim("[archived]");
9292
9383
  default:
9293
- return import_picocolors29.default.dim("[todo]");
9384
+ return import_picocolors30.default.dim("[todo]");
9294
9385
  }
9295
9386
  }
9296
9387
 
9297
9388
  // src/commands/goal.ts
9298
- var import_picocolors30 = __toESM(require_picocolors(), 1);
9389
+ var import_picocolors31 = __toESM(require_picocolors(), 1);
9299
9390
  var STATUSES3 = ["proposed", "agreed", "working", "delivered", "abandoned"];
9300
9391
  function registerGoal(program3) {
9301
9392
  const goal = program3.command("goal").description("Business goals and the phases that deliver them");
@@ -9307,7 +9398,7 @@ function registerGoal(program3) {
9307
9398
  }) ?? [];
9308
9399
  ok(rows, () => {
9309
9400
  if (!rows.length) {
9310
- 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."));
9311
9402
  return;
9312
9403
  }
9313
9404
  for (const g of rows) line(formatGoal(g));
@@ -9384,10 +9475,10 @@ function registerGoal(program3) {
9384
9475
  }
9385
9476
  });
9386
9477
  ok(row, () => {
9387
- success(`Proposed ${import_picocolors30.default.bold(row?.title ?? "goal")}`);
9478
+ success(`Proposed ${import_picocolors31.default.bold(row?.title ?? "goal")}`);
9388
9479
  printGoal(row);
9389
9480
  line(
9390
- import_picocolors30.default.dim(
9481
+ import_picocolors31.default.dim(
9391
9482
  "\nNothing has been created yet. The owner agrees the shape first."
9392
9483
  )
9393
9484
  );
@@ -9416,13 +9507,54 @@ function registerGoal(program3) {
9416
9507
  ok(
9417
9508
  row,
9418
9509
  () => line(
9419
- 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(
9420
9511
  "couldn't record it \u2014 check the goal id, the phase name and the criterion id"
9421
9512
  )
9422
9513
  )
9423
9514
  );
9424
9515
  })
9425
9516
  );
9517
+ goal.command("adopt <id>").description(
9518
+ "File tasks that already exist under a part of this plan \u2014 for work done before the plan was written"
9519
+ ).option("--task <id...>", "the tasks to file under it").option("--phase <name>", "which part of the plan they belong to").action(
9520
+ action(async ({ ctx, args, opts }) => {
9521
+ requireProject(ctx);
9522
+ const goalId = String(args[0]);
9523
+ const taskIds = opts.task ?? [];
9524
+ if (!taskIds.length) {
9525
+ throw new WorkserError(
9526
+ "Name the tasks to file, e.g. `--task WORK-12 WORK-13`."
9527
+ );
9528
+ }
9529
+ const goal2 = await api(
9530
+ ctx,
9531
+ `/v1/project-goals/${encodeURIComponent(goalId)}`
9532
+ );
9533
+ if (!goal2) throw new WorkserError(`No goal ${goalId}.`);
9534
+ const names = (goal2.phases ?? []).map(
9535
+ (p) => typeof p === "string" ? p : p.name
9536
+ );
9537
+ const phase = String(opts.phase ?? "").trim();
9538
+ if (!phase || !names.includes(phase)) {
9539
+ throw new WorkserError(
9540
+ `--phase must be one of this goal's parts: ${names.join(", ")}.`
9541
+ );
9542
+ }
9543
+ const filed = [];
9544
+ for (const taskId of taskIds) {
9545
+ await api(ctx, `/v1/project-tasks/${encodeURIComponent(taskId)}`, {
9546
+ method: "PATCH",
9547
+ body: { goalId, phase }
9548
+ });
9549
+ filed.push(taskId);
9550
+ }
9551
+ ok({ goalId, phase, filed }, () => {
9552
+ success(
9553
+ `Filed ${filed.length} ${filed.length === 1 ? "task" : "tasks"} under ${import_picocolors31.default.bold(phase)}`
9554
+ );
9555
+ });
9556
+ })
9557
+ );
9426
9558
  goal.command("update <id>").description("Change the shape, or move the goal along").option("--title <text>", "the owner's words for what they want").option("--outcome <text>", "what 'done' means").option("--phase <name...>", "replace the ordered phase list").option("--status <value>", `one of: ${STATUSES3.join(" | ")}`).action(
9427
9559
  action(async ({ ctx, args, opts }) => {
9428
9560
  if (opts.status && !STATUSES3.includes(opts.status)) {
@@ -9450,42 +9582,42 @@ function registerGoal(program3) {
9450
9582
  function appScope(g) {
9451
9583
  const n = g.appIds?.length ?? 0;
9452
9584
  if (!n) return "";
9453
- 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`);
9454
9586
  }
9455
9587
  function formatGoal(g) {
9456
- const where = g.currentPhase && g.status !== "delivered" ? import_picocolors30.default.dim(` now: ${g.currentPhase}`) : "";
9457
- const count = g.taskTotal != null ? import_picocolors30.default.dim(` ${g.taskDone}/${g.taskTotal} done`) : "";
9458
- 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)}`;
9459
9591
  }
9460
9592
  function printGoal(g) {
9461
9593
  if (!g) return;
9462
- 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)}`);
9463
9595
  line(statusTag3(g.status));
9464
9596
  if (g.outcome) line(`
9465
9597
  done means: ${g.outcome}`);
9466
9598
  const progress = g.progress ?? [];
9467
9599
  if (!progress.length) {
9468
- line(import_picocolors30.default.dim("\nNo phases agreed yet."));
9600
+ line(import_picocolors31.default.dim("\nNo phases agreed yet."));
9469
9601
  return;
9470
9602
  }
9471
9603
  line(`
9472
- ${import_picocolors30.default.bold("phases")}`);
9604
+ ${import_picocolors31.default.bold("phases")}`);
9473
9605
  for (const p of progress) {
9474
- const bar2 = p.total > 0 ? `${p.done}/${p.total} done` : import_picocolors30.default.dim("nothing filed yet");
9475
- 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");
9476
9608
  line(
9477
- ` ${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)}`
9478
9610
  );
9479
9611
  for (const c of p.criteria ?? []) {
9480
- const tick = c.met === true ? import_picocolors30.default.green("\u2713") : c.met === false ? import_picocolors30.default.red("\u2717") : import_picocolors30.default.dim("\xB7");
9481
- line(` ${tick} ${c.text} ${import_picocolors30.default.dim(c.id)}`);
9482
- 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}`));
9483
9615
  }
9484
9616
  }
9485
9617
  const current = progress.find((p) => p.name === g.currentPhase);
9486
9618
  if (current) {
9487
9619
  line(
9488
- import_picocolors30.default.dim(
9620
+ import_picocolors31.default.dim(
9489
9621
  `
9490
9622
  ${current.name} \u2014 ${current.done} of ${current.total} done (phase ${current.index} of ${progress.length}).`
9491
9623
  )
@@ -9495,15 +9627,15 @@ ${current.name} \u2014 ${current.done} of ${current.total} done (phase ${current
9495
9627
  function statusTag3(status) {
9496
9628
  switch (status) {
9497
9629
  case "agreed":
9498
- return import_picocolors30.default.cyan("[agreed]");
9630
+ return import_picocolors31.default.cyan("[agreed]");
9499
9631
  case "working":
9500
- return import_picocolors30.default.blue("[working]");
9632
+ return import_picocolors31.default.blue("[working]");
9501
9633
  case "delivered":
9502
- return import_picocolors30.default.green("[delivered]");
9634
+ return import_picocolors31.default.green("[delivered]");
9503
9635
  case "abandoned":
9504
- return import_picocolors30.default.dim("[abandoned]");
9636
+ return import_picocolors31.default.dim("[abandoned]");
9505
9637
  default:
9506
- return import_picocolors30.default.yellow("[proposed]");
9638
+ return import_picocolors31.default.yellow("[proposed]");
9507
9639
  }
9508
9640
  }
9509
9641
 
@@ -9556,7 +9688,15 @@ var READS = [
9556
9688
  // have `create` subcommands — these write the project's RECORD, not the
9557
9689
  // project. What stops a reviewer editing code is its filesystem mode, and
9558
9690
  // that is untouched.
9559
- "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"
9560
9700
  ];
9561
9701
  var BUILDS = [
9562
9702
  ...READS,
@@ -9576,6 +9716,7 @@ var BUILDS = [
9576
9716
  ];
9577
9717
  var ROLE_VERBS = {
9578
9718
  pm: [...READS, "ask", "app"],
9719
+ // `note` reaches this via READS.
9579
9720
  architect: [...BUILDS, "versions"],
9580
9721
  web: BUILDS,
9581
9722
  api: BUILDS,
@@ -9678,7 +9819,7 @@ function stripLeadingGlobalOptions(argv) {
9678
9819
  }
9679
9820
 
9680
9821
  // src/commands/decision.ts
9681
- var import_picocolors31 = __toESM(require_picocolors(), 1);
9822
+ var import_picocolors32 = __toESM(require_picocolors(), 1);
9682
9823
  function registerDecision(program3) {
9683
9824
  const decision = program3.command("decision").description("Read and record the project's architecture decisions");
9684
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(
@@ -9691,11 +9832,11 @@ function registerDecision(program3) {
9691
9832
  rows = applyLimit(rows, opts.limit);
9692
9833
  ok(rows, () => {
9693
9834
  if (!rows.length) {
9694
- line(import_picocolors31.default.dim("No decisions recorded yet."));
9835
+ line(import_picocolors32.default.dim("No decisions recorded yet."));
9695
9836
  return;
9696
9837
  }
9697
9838
  for (const r of rows) {
9698
- 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}`);
9699
9840
  line(` ${truncate(r.decision, 100)}`);
9700
9841
  }
9701
9842
  });
@@ -9709,16 +9850,16 @@ function registerDecision(program3) {
9709
9850
  `/v1/projects/${projectId}/architecture-decisions/${args[0]}`
9710
9851
  );
9711
9852
  ok(row, () => {
9712
- line(`${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.id)}`);
9713
- 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)}`));
9714
9855
  line(`
9715
- ${import_picocolors31.default.bold("Context")}
9856
+ ${import_picocolors32.default.bold("Context")}
9716
9857
  ${row.context}`);
9717
9858
  line(`
9718
- ${import_picocolors31.default.bold("Decision")}
9859
+ ${import_picocolors32.default.bold("Decision")}
9719
9860
  ${row.decision}`);
9720
9861
  if (row.consequences) line(`
9721
- ${import_picocolors31.default.bold("Consequences")}
9862
+ ${import_picocolors32.default.bold("Consequences")}
9722
9863
  ${row.consequences}`);
9723
9864
  });
9724
9865
  })
@@ -9747,7 +9888,7 @@ ${row.consequences}`);
9747
9888
  refId: row?.id,
9748
9889
  output: { decision: row }
9749
9890
  });
9750
- 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}`));
9751
9892
  })
9752
9893
  );
9753
9894
  const requirement = program3.command("requirement").description("Read and record the project's requirements");
@@ -9759,11 +9900,11 @@ ${row.consequences}`);
9759
9900
  rows = applyLimit(rows, opts.limit);
9760
9901
  ok(rows, () => {
9761
9902
  if (!rows.length) {
9762
- line(import_picocolors31.default.dim("No requirements recorded yet."));
9903
+ line(import_picocolors32.default.dim("No requirements recorded yet."));
9763
9904
  return;
9764
9905
  }
9765
9906
  for (const r of rows) {
9766
- 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}`);
9767
9908
  }
9768
9909
  });
9769
9910
  })
@@ -9776,8 +9917,8 @@ ${row.consequences}`);
9776
9917
  `/v1/projects/${projectId}/requirements/${args[0]}`
9777
9918
  );
9778
9919
  ok(row, () => {
9779
- line(`${import_picocolors31.default.bold(row.title)} ${import_picocolors31.default.dim(row.id)}`);
9780
- 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)}`));
9781
9922
  line(`
9782
9923
  ${row.body}`);
9783
9924
  });
@@ -9803,7 +9944,7 @@ ${row.body}`);
9803
9944
  refId: row?.id,
9804
9945
  output: { requirement: row }
9805
9946
  });
9806
- 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}`));
9807
9948
  })
9808
9949
  );
9809
9950
  requirement.command("update <id>").description(
@@ -9832,7 +9973,7 @@ ${row.body}`);
9832
9973
  code: "bad_request"
9833
9974
  });
9834
9975
  }
9835
- 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})`));
9836
9977
  })
9837
9978
  );
9838
9979
  }
@@ -9855,7 +9996,7 @@ function shortDate(iso) {
9855
9996
  }
9856
9997
 
9857
9998
  // src/commands/doc.ts
9858
- var import_picocolors32 = __toESM(require_picocolors(), 1);
9999
+ var import_picocolors33 = __toESM(require_picocolors(), 1);
9859
10000
 
9860
10001
  // src/mermaid-fences.ts
9861
10002
  function hasDiagram(code) {
@@ -9900,13 +10041,13 @@ function registerDoc(program3) {
9900
10041
  }) ?? [];
9901
10042
  ok(rows, () => {
9902
10043
  if (!rows.length) {
9903
- line(import_picocolors32.default.dim("No documents yet."));
10044
+ line(import_picocolors33.default.dim("No documents yet."));
9904
10045
  return;
9905
10046
  }
9906
10047
  for (const r of rows) {
9907
- const link = r.workItemId ? import_picocolors32.default.dim(` \u21B3 ${r.workItemId}`) : "";
9908
- const file = r.filePath ? import_picocolors32.default.dim(` ${r.filePath}`) : "";
9909
- 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}`);
9910
10051
  }
9911
10052
  });
9912
10053
  })
@@ -9920,17 +10061,17 @@ function registerDoc(program3) {
9920
10061
  );
9921
10062
  if (opts.markdown) {
9922
10063
  ok({ id: row.id, title: row.title, filePath: row.filePath }, () => {
9923
- 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)}`);
9924
10065
  line(
9925
- 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.")
9926
10067
  );
9927
10068
  });
9928
10069
  return;
9929
10070
  }
9930
10071
  ok(row, () => {
9931
- line(`${import_picocolors32.default.bold(row.title)} ${import_picocolors32.default.dim(row.id)}`);
9932
- if (row.workItemId) line(import_picocolors32.default.dim(`linked to work item ${row.workItemId}`));
9933
- 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}`));
9934
10075
  line("");
9935
10076
  line(row.contentJson);
9936
10077
  });
@@ -9959,7 +10100,7 @@ function registerDoc(program3) {
9959
10100
  refId: row?.id,
9960
10101
  output: { document: row }
9961
10102
  });
9962
- 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}`));
9963
10104
  })
9964
10105
  );
9965
10106
  doc.command("diagram <id>").description(
@@ -9985,19 +10126,19 @@ function registerDoc(program3) {
9985
10126
  diagrams: diagrams.map((code) => ({ kind: diagramKind(code), code }))
9986
10127
  };
9987
10128
  ok(payload, () => {
9988
- 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)}`);
9989
10130
  if (markdown === null) {
9990
10131
  line(
9991
- import_picocolors32.default.dim(
10132
+ import_picocolors33.default.dim(
9992
10133
  row.filePath ? `Could not read ${row.filePath} from this folder.` : "This document has no markdown mirror on disk yet."
9993
10134
  )
9994
10135
  );
9995
10136
  } else if (!diagrams.length) {
9996
- line(import_picocolors32.default.dim("No diagrams in this document."));
10137
+ line(import_picocolors33.default.dim("No diagrams in this document."));
9997
10138
  } else {
9998
10139
  for (const [i, code] of diagrams.entries()) {
9999
10140
  const kind = diagramKind(code) ?? "diagram";
10000
- 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`)}`);
10001
10142
  }
10002
10143
  }
10003
10144
  });
@@ -10033,7 +10174,7 @@ function registerDoc(program3) {
10033
10174
  code: "bad_request"
10034
10175
  });
10035
10176
  }
10036
- 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}`));
10037
10178
  })
10038
10179
  );
10039
10180
  }
@@ -10047,7 +10188,7 @@ function readMirror(cwd, filePath) {
10047
10188
  }
10048
10189
 
10049
10190
  // src/commands/design.ts
10050
- var import_picocolors33 = __toESM(require_picocolors(), 1);
10191
+ var import_picocolors34 = __toESM(require_picocolors(), 1);
10051
10192
  function registerDesign(program3) {
10052
10193
  const design = program3.command("design").description("Read the project's brand (colours, fonts, logo)");
10053
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(
@@ -10061,11 +10202,11 @@ function registerDesign(program3) {
10061
10202
  if (opts.raw) {
10062
10203
  ok(files, () => {
10063
10204
  if (!files.length) {
10064
- line(import_picocolors33.default.dim("No brand set for this project."));
10205
+ line(import_picocolors34.default.dim("No brand set for this project."));
10065
10206
  return;
10066
10207
  }
10067
10208
  for (const f of files) {
10068
- line(import_picocolors33.default.bold(f.path));
10209
+ line(import_picocolors34.default.bold(f.path));
10069
10210
  line(f.contents);
10070
10211
  line("");
10071
10212
  }
@@ -10082,21 +10223,21 @@ function registerDesign(program3) {
10082
10223
  } : { hasBrand: false, colors: {}, fonts: {}, brand: {}, files: [] };
10083
10224
  ok(summary, () => {
10084
10225
  if (!tokens) {
10085
- 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."));
10086
10227
  return;
10087
10228
  }
10088
10229
  for (const [name, value] of Object.entries(tokens.brand)) {
10089
- line(`${import_picocolors33.default.dim(name.padEnd(12))} ${value}`);
10230
+ line(`${import_picocolors34.default.dim(name.padEnd(12))} ${value}`);
10090
10231
  }
10091
10232
  for (const [name, value] of Object.entries(tokens.color)) {
10092
- line(`${import_picocolors33.default.dim(`color.${name}`.padEnd(12))} ${value}`);
10233
+ line(`${import_picocolors34.default.dim(`color.${name}`.padEnd(12))} ${value}`);
10093
10234
  }
10094
10235
  for (const [name, value] of Object.entries(tokens.font)) {
10095
- line(`${import_picocolors33.default.dim(`font.${name}`.padEnd(12))} ${value}`);
10236
+ line(`${import_picocolors34.default.dim(`font.${name}`.padEnd(12))} ${value}`);
10096
10237
  }
10097
10238
  line("");
10098
10239
  line(
10099
- import_picocolors33.default.dim(
10240
+ import_picocolors34.default.dim(
10100
10241
  `Generated into the working tree as ${files.map((f) => f.path).join(", ")} \u2014 wire those in, never edit them.`
10101
10242
  )
10102
10243
  );
@@ -10127,7 +10268,7 @@ function unwrap(group) {
10127
10268
  }
10128
10269
 
10129
10270
  // src/commands/api.ts
10130
- var import_picocolors34 = __toESM(require_picocolors(), 1);
10271
+ var import_picocolors35 = __toESM(require_picocolors(), 1);
10131
10272
  import { readdirSync, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
10132
10273
  import { join as join3, relative, sep } from "path";
10133
10274
 
@@ -10241,10 +10382,10 @@ function registerApi(program3) {
10241
10382
  const appId = requireApp2(opts.app);
10242
10383
  const res = await api(ctx, `/v1/apps/${encodeURIComponent(appId)}/api/requests`);
10243
10384
  ok(res, () => {
10244
- 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));
10245
10386
  for (const r of res?.requests ?? []) {
10246
10387
  line(
10247
- `${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}`) : ""}`
10248
10389
  );
10249
10390
  }
10250
10391
  });
@@ -10278,14 +10419,14 @@ function registerApi(program3) {
10278
10419
  );
10279
10420
  ok(res, () => {
10280
10421
  if (!res?.ok) {
10281
- 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."));
10282
10423
  return;
10283
10424
  }
10284
10425
  const code = `${res.status}${res.statusText ? ` ${res.statusText}` : ""}`;
10285
- const colour2 = res.status && res.status < 300 ? import_picocolors34.default.green : res.status && res.status < 500 ? import_picocolors34.default.yellow : import_picocolors34.default.red;
10286
- 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}`)}`);
10287
10428
  if (res.body) line(res.body);
10288
- if (res.truncated) line(import_picocolors34.default.dim("(answer truncated)"));
10429
+ if (res.truncated) line(import_picocolors35.default.dim("(answer truncated)"));
10289
10430
  });
10290
10431
  if (!res?.ok) process.exitCode = 1;
10291
10432
  })
@@ -10305,15 +10446,15 @@ function registerApi(program3) {
10305
10446
  for (const r of report.routes) {
10306
10447
  const known = report.missing.some((m) => m.path === r.path);
10307
10448
  line(
10308
- `${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}`)}`
10309
10450
  );
10310
10451
  }
10311
10452
  for (const p of report.stale) {
10312
- line(`${import_picocolors34.default.dim("in spec only ")} ${p}`);
10453
+ line(`${import_picocolors35.default.dim("in spec only ")} ${p}`);
10313
10454
  }
10314
10455
  line("");
10315
10456
  if (report.ok && specFile) success(summary);
10316
- else line(import_picocolors34.default.yellow(summary));
10457
+ else line(import_picocolors35.default.yellow(summary));
10317
10458
  });
10318
10459
  if (opts.check && !report.ok) {
10319
10460
  throw new WorkserError(summary, { code: "bad_request" });
@@ -10384,7 +10525,7 @@ function listRepoFiles(root, maxDepth = 8) {
10384
10525
  }
10385
10526
 
10386
10527
  // src/commands/analysis.ts
10387
- var import_picocolors35 = __toESM(require_picocolors(), 1);
10528
+ var import_picocolors36 = __toESM(require_picocolors(), 1);
10388
10529
  import { readFileSync as readFileSync4 } from "fs";
10389
10530
  function registerAnalysis(program3) {
10390
10531
  const cmd = program3.command("analysis").description("Run Python analysis locally, recorded in the task");
@@ -10394,14 +10535,14 @@ function registerAnalysis(program3) {
10394
10535
  const res = await api(ctx, path);
10395
10536
  ok(res, () => {
10396
10537
  line(
10397
- `${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 ?? "")}`
10398
10539
  );
10399
10540
  for (const lib of res?.libraries ?? []) {
10400
10541
  line(
10401
- `${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")}`
10402
10543
  );
10403
10544
  }
10404
- 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));
10405
10546
  });
10406
10547
  if (!res?.available) process.exitCode = 1;
10407
10548
  })
@@ -10423,15 +10564,15 @@ function registerAnalysis(program3) {
10423
10564
  );
10424
10565
  ok(res, () => {
10425
10566
  if (res?.stdout) line(res.stdout.replace(/\n$/, ""));
10426
- if (res?.stderr) line(import_picocolors35.default.dim(res.stderr.replace(/\n$/, "")));
10427
- 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)"));
10428
10569
  const took = `${Math.round((res?.durationMs ?? 0) / 100) / 10}s`;
10429
10570
  line(
10430
- 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}`)
10431
10572
  );
10432
10573
  if (res && !res.sandboxed) {
10433
10574
  line(
10434
- import_picocolors35.default.dim(
10575
+ import_picocolors36.default.dim(
10435
10576
  "This platform has no OS sandbox, so the script ran with your own file access."
10436
10577
  )
10437
10578
  );
@@ -10459,7 +10600,7 @@ function readCode(file, inline) {
10459
10600
  }
10460
10601
 
10461
10602
  // src/commands/scan.ts
10462
- var import_picocolors36 = __toESM(require_picocolors(), 1);
10603
+ var import_picocolors37 = __toESM(require_picocolors(), 1);
10463
10604
  import { spawnSync as spawnSync2 } from "child_process";
10464
10605
  import { existsSync as existsSync3, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
10465
10606
  import { join as join4, relative as relative2, sep as sep2 } from "path";
@@ -10743,22 +10884,22 @@ function runPermissions(cwd, findings, checked, skipped) {
10743
10884
  }
10744
10885
  function print2(report, summary) {
10745
10886
  for (const s of report.skipped) {
10746
- 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}`)}`);
10747
10888
  }
10748
10889
  for (const f of report.findings) {
10749
- 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}` : ""}`) : "";
10750
10891
  line(`${severityTag(f.severity)} ${f.title}${where}`);
10751
- line(` ${import_picocolors36.default.dim(f.fix)}`);
10892
+ line(` ${import_picocolors37.default.dim(f.fix)}`);
10752
10893
  }
10753
10894
  if (report.findings.length || report.skipped.length) line("");
10754
10895
  if (report.ok && !report.skipped.length) success(summary);
10755
- else if (report.ok) line(import_picocolors36.default.yellow(summary));
10756
- 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));
10757
10898
  }
10758
10899
  function severityTag(severity) {
10759
- if (severity === "high") return import_picocolors36.default.red("serious ");
10760
- if (severity === "medium") return import_picocolors36.default.yellow("worth fixing");
10761
- 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 ");
10762
10903
  }
10763
10904
  function git(cwd, args) {
10764
10905
  try {
@@ -10819,7 +10960,7 @@ function listRepoFiles2(root, maxDepth = 8) {
10819
10960
  }
10820
10961
 
10821
10962
  // src/commands/health.ts
10822
- var import_picocolors37 = __toESM(require_picocolors(), 1);
10963
+ var import_picocolors38 = __toESM(require_picocolors(), 1);
10823
10964
  function registerHealth(program3) {
10824
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(
10825
10966
  action(async ({ ctx, opts }) => {
@@ -10833,16 +10974,16 @@ function registerHealth(program3) {
10833
10974
  }
10834
10975
  function print3(res) {
10835
10976
  if (!res?.checks?.length) {
10836
- line(import_picocolors37.default.dim(res?.note ?? "Nothing to check."));
10977
+ line(import_picocolors38.default.dim(res?.note ?? "Nothing to check."));
10837
10978
  return;
10838
10979
  }
10839
10980
  for (const c of res.checks) {
10840
- const mark = c.ok ? import_picocolors37.default.green("up ") : import_picocolors37.default.red("down");
10841
- const timing = import_picocolors37.default.dim(`${c.ms}ms`);
10842
- const detail = c.ok ? timing : import_picocolors37.default.dim(`${c.error ?? "no answer"}${c.failures > 1 ? ` \xB7 ${c.failures} in a row` : ""}`);
10843
- 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}`);
10844
10985
  if (c.incidentOpened) {
10845
- 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.`));
10846
10987
  }
10847
10988
  }
10848
10989
  const down = res.checks.filter((c) => !c.ok);
@@ -10855,14 +10996,14 @@ function print3(res) {
10855
10996
  }
10856
10997
  const production = down.filter((c) => c.environment === "production").length;
10857
10998
  line(
10858
- import_picocolors37.default.red(
10999
+ import_picocolors38.default.red(
10859
11000
  `${down.length} of ${res.checks.length} not answering` + (production ? ` \u2014 ${production} customer-facing.` : " (preview only).")
10860
11001
  )
10861
11002
  );
10862
11003
  }
10863
11004
 
10864
11005
  // src/commands/urls.ts
10865
- var import_picocolors38 = __toESM(require_picocolors(), 1);
11006
+ var import_picocolors39 = __toESM(require_picocolors(), 1);
10866
11007
  function registerUrls(program3) {
10867
11008
  program3.command("urls").description("The stable preview and production addresses of every app in this project").option("--app <webAppId>", "just one app").action(
10868
11009
  action(async ({ ctx, opts }) => {
@@ -10876,20 +11017,20 @@ function registerUrls(program3) {
10876
11017
  const summary = urlsSummary(rows);
10877
11018
  ok({ rows, summary }, () => {
10878
11019
  for (const row of rows) {
10879
- const label = import_picocolors38.default.dim(row.environment.padEnd(10));
10880
- 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");
10881
11022
  line(` ${row.appName.padEnd(22)} ${label} ${value}`);
10882
11023
  }
10883
11024
  line("");
10884
11025
  if (rows.some((r) => r.url)) success(summary);
10885
- else line(import_picocolors38.default.yellow(summary));
11026
+ else line(import_picocolors39.default.yellow(summary));
10886
11027
  });
10887
11028
  })
10888
11029
  );
10889
11030
  }
10890
11031
 
10891
11032
  // src/commands/deployments.ts
10892
- var import_picocolors39 = __toESM(require_picocolors(), 1);
11033
+ var import_picocolors40 = __toESM(require_picocolors(), 1);
10893
11034
  function registerDeployments(program3) {
10894
11035
  const cmd = program3.command("deployments").description("Deployment history, and putting a build in front of customers");
10895
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(
@@ -10907,7 +11048,7 @@ function registerDeployments(program3) {
10907
11048
  ok(res, () => {
10908
11049
  if (!items.length) {
10909
11050
  return line(
10910
- import_picocolors39.default.dim(
11051
+ import_picocolors40.default.dim(
10911
11052
  environment ? `Nothing has been deployed to ${environment} yet.` : "Nothing has been deployed yet. `workser deploy` builds the first one."
10912
11053
  )
10913
11054
  );
@@ -10927,13 +11068,13 @@ function registerDeployments(program3) {
10927
11068
  ).catch(() => null) : null;
10928
11069
  ok({ ...dep, logs }, () => {
10929
11070
  line(formatDeployment(dep));
10930
- 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}`));
10931
11072
  const events = logs?.events ?? [];
10932
11073
  for (const e of events) {
10933
- line(` ${import_picocolors39.default.dim(String(e.type ?? "log"))} ${e.text ?? ""}`);
11074
+ line(` ${import_picocolors40.default.dim(String(e.type ?? "log"))} ${e.text ?? ""}`);
10934
11075
  }
10935
11076
  if (opts.logs && !events.length) {
10936
- line(import_picocolors39.default.dim(" That build produced no output."));
11077
+ line(import_picocolors40.default.dim(" That build produced no output."));
10937
11078
  }
10938
11079
  });
10939
11080
  })
@@ -10977,16 +11118,16 @@ function printPromoted(res, version) {
10977
11118
  const what = version === null ? "the latest build" : `version ${version}`;
10978
11119
  const url = res.url ?? res.vercel_url;
10979
11120
  success(`Production is being rebuilt from ${what}.`);
10980
- if (url) line(import_picocolors39.default.dim(`It will be at ${url}`));
10981
- 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."));
10982
11123
  }
10983
11124
  function formatDeployment(d) {
10984
11125
  if (!d) return "";
10985
- const version = d.version !== void 0 ? import_picocolors39.default.yellow(`v${d.version}`) : import_picocolors39.default.dim("v?");
10986
- 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));
10987
11128
  const app = d.webAppName ? `${d.webAppName} ` : "";
10988
- const when = import_picocolors39.default.dim(formatTime2(d.created_at));
10989
- 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) : "";
10990
11131
  return `${version} ${env} ${colorStatus(d.status ?? "")} ${app}${when}${url}`;
10991
11132
  }
10992
11133
  function formatTime2(t) {
@@ -10996,7 +11137,7 @@ function formatTime2(t) {
10996
11137
  }
10997
11138
 
10998
11139
  // src/commands/usage.ts
10999
- var import_picocolors40 = __toESM(require_picocolors(), 1);
11140
+ var import_picocolors41 = __toESM(require_picocolors(), 1);
11000
11141
 
11001
11142
  // src/usage.ts
11002
11143
  var NEAR_LIMIT_FRACTION = 0.8;
@@ -11091,7 +11232,7 @@ function registerUsage(program3) {
11091
11232
  function print4(report) {
11092
11233
  const dims = report.dimensions ?? [];
11093
11234
  if (!dims.length) {
11094
- 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."));
11095
11236
  }
11096
11237
  const width = Math.max(...dims.map((d) => d.label.length));
11097
11238
  for (const d of dims) {
@@ -11100,23 +11241,23 @@ function print4(report) {
11100
11241
  line("");
11101
11242
  const summary = usageSummary(report);
11102
11243
  const worst = dims.map(usageState);
11103
- if (worst.includes("over")) line(import_picocolors40.default.red(summary));
11244
+ if (worst.includes("over")) line(import_picocolors41.default.red(summary));
11104
11245
  else if (worst.includes("near") || worst.includes("unknown"))
11105
- line(import_picocolors40.default.yellow(summary));
11246
+ line(import_picocolors41.default.yellow(summary));
11106
11247
  else success(summary);
11107
11248
  }
11108
11249
  function gauge(d, _labelWidth) {
11109
11250
  const drawn = bar(d);
11110
- return drawn ? ` ${import_picocolors40.default.dim(drawn)}` : "";
11251
+ return drawn ? ` ${import_picocolors41.default.dim(drawn)}` : "";
11111
11252
  }
11112
11253
  function colour(d) {
11113
11254
  switch (usageState(d)) {
11114
11255
  case "over":
11115
- 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;
11116
11257
  case "near":
11117
- return import_picocolors40.default.yellow;
11258
+ return import_picocolors41.default.yellow;
11118
11259
  case "unknown":
11119
- return import_picocolors40.default.dim;
11260
+ return import_picocolors41.default.dim;
11120
11261
  default:
11121
11262
  return (s) => s;
11122
11263
  }
@@ -11124,7 +11265,7 @@ function colour(d) {
11124
11265
 
11125
11266
  // src/index.ts
11126
11267
  var pkg = {
11127
- version: true ? "0.6.11" : "0.0.0-dev"
11268
+ version: true ? "0.6.13" : "0.0.0-dev"
11128
11269
  };
11129
11270
  var program2 = new Command();
11130
11271
  program2.name("workser").description(
@@ -11171,6 +11312,7 @@ registerWorkflow(program2);
11171
11312
  registerConnection(program2);
11172
11313
  registerTool(program2);
11173
11314
  registerMemory(program2);
11315
+ registerNote(program2);
11174
11316
  registerBusiness(program2);
11175
11317
  registerArtifact(program2);
11176
11318
  registerImage(program2);