@growthub/cli 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +1577 -727
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6067,8 +6067,8 @@ function sanitizeRestoreErrorMessage(error) {
6067
6067
  return error instanceof Error ? error.message : String(error);
6068
6068
  }
6069
6069
  function timestamp56(date2 = /* @__PURE__ */ new Date()) {
6070
- const pad = (n) => String(n).padStart(2, "0");
6071
- return `${date2.getFullYear()}${pad(date2.getMonth() + 1)}${pad(date2.getDate())}-${pad(date2.getHours())}${pad(date2.getMinutes())}${pad(date2.getSeconds())}`;
6070
+ const pad2 = (n) => String(n).padStart(2, "0");
6071
+ return `${date2.getFullYear()}${pad2(date2.getMonth() + 1)}${pad2(date2.getDate())}-${pad2(date2.getHours())}${pad2(date2.getMinutes())}${pad2(date2.getSeconds())}`;
6072
6072
  }
6073
6073
  function pruneOldBackups(backupDir, retentionDays, filenamePrefix) {
6074
6074
  if (!existsSync(backupDir)) return 0;
@@ -8023,16 +8023,16 @@ function buildUrl(apiBase, path47) {
8023
8023
  if (query) url.search = query;
8024
8024
  return url.toString();
8025
8025
  }
8026
- function safeParseJson(text64) {
8026
+ function safeParseJson(text65) {
8027
8027
  try {
8028
- return JSON.parse(text64);
8028
+ return JSON.parse(text65);
8029
8029
  } catch {
8030
- return text64;
8030
+ return text65;
8031
8031
  }
8032
8032
  }
8033
8033
  async function toApiError(response) {
8034
- const text64 = await response.text();
8035
- const parsed = safeParseJson(text64);
8034
+ const text65 = await response.text();
8035
+ const parsed = safeParseJson(text65);
8036
8036
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
8037
8037
  const body = parsed;
8038
8038
  const message = typeof body.error === "string" && body.error.trim() || typeof body.message === "string" && body.message.trim() || `Request failed with status ${response.status}`;
@@ -8127,11 +8127,11 @@ var init_http = __esm({
8127
8127
  if (response.status === 204) {
8128
8128
  return null;
8129
8129
  }
8130
- const text64 = await response.text();
8131
- if (!text64.trim()) {
8130
+ const text65 = await response.text();
8131
+ if (!text65.trim()) {
8132
8132
  return null;
8133
8133
  }
8134
- return safeParseJson(text64);
8134
+ return safeParseJson(text65);
8135
8135
  }
8136
8136
  };
8137
8137
  }
@@ -9604,9 +9604,9 @@ __export(github_exports, {
9604
9604
  registerGithubCommands: () => registerGithubCommands
9605
9605
  });
9606
9606
  import * as p26 from "@clack/prompts";
9607
- import pc38 from "picocolors";
9607
+ import pc40 from "picocolors";
9608
9608
  import open2 from "open";
9609
- async function sleep(ms) {
9609
+ async function sleep2(ms) {
9610
9610
  await new Promise((r) => setTimeout(r, ms));
9611
9611
  }
9612
9612
  async function githubLogin(opts) {
@@ -9627,14 +9627,14 @@ async function githubLogin(opts) {
9627
9627
  if (opts.json) {
9628
9628
  console.log(JSON.stringify({ status: "ok", mode: "pat", login: profile.login }, null, 2));
9629
9629
  } else {
9630
- p26.log.success(`Connected to GitHub as ${pc38.cyan(profile.login)} (PAT).`);
9630
+ p26.log.success(`Connected to GitHub as ${pc40.cyan(profile.login)} (PAT).`);
9631
9631
  }
9632
9632
  return;
9633
9633
  }
9634
- p26.intro(pc38.cyan("GitHub device flow login"));
9634
+ p26.intro(pc40.cyan("GitHub device flow login"));
9635
9635
  const start = await startDeviceFlow();
9636
9636
  p26.log.step(
9637
- `Open ${pc38.cyan(start.verificationUri)} and enter code ${pc38.yellow(start.userCode)}`
9637
+ `Open ${pc40.cyan(start.verificationUri)} and enter code ${pc40.yellow(start.userCode)}`
9638
9638
  );
9639
9639
  if (!opts.noBrowser) {
9640
9640
  try {
@@ -9648,7 +9648,7 @@ async function githubLogin(opts) {
9648
9648
  const spinner12 = p26.spinner();
9649
9649
  spinner12.start("Waiting for GitHub authorization...");
9650
9650
  while (Date.now() - startedAt < maxMs) {
9651
- await sleep(interval * 1e3);
9651
+ await sleep2(interval * 1e3);
9652
9652
  const poll = await pollDeviceFlow(start.deviceCode);
9653
9653
  if (poll.status === "authorized" && poll.token) {
9654
9654
  spinner12.stop("Authorization received.");
@@ -9663,7 +9663,7 @@ async function githubLogin(opts) {
9663
9663
  if (opts.json) {
9664
9664
  console.log(JSON.stringify({ status: "ok", mode: "device-flow", login: profile.login }));
9665
9665
  } else {
9666
- p26.outro(`Connected to GitHub as ${pc38.cyan(profile.login)}.`);
9666
+ p26.outro(`Connected to GitHub as ${pc40.cyan(profile.login)}.`);
9667
9667
  }
9668
9668
  return;
9669
9669
  }
@@ -9727,7 +9727,7 @@ async function githubWhoami(opts = {}) {
9727
9727
  return;
9728
9728
  }
9729
9729
  if (token) {
9730
- const status = directExpired ? pc38.red("expired") : pc38.green("active");
9730
+ const status = directExpired ? pc40.red("expired") : pc40.green("active");
9731
9731
  p26.log.message(
9732
9732
  `GitHub (direct): ${status} login=${profile?.login ?? token.login ?? "?"} mode=${token.authMode} scopes=[${token.scopes.join(", ")}]`
9733
9733
  );
@@ -9735,7 +9735,7 @@ async function githubWhoami(opts = {}) {
9735
9735
  if (bridge.growthubConnected) {
9736
9736
  if (bridgeGithub) {
9737
9737
  p26.log.message(
9738
- `GitHub (via Growthub bridge): ${pc38.green("connected")} handle=${bridgeGithub.handle ?? "?"} growthub=${bridge.growthubLogin ?? "?"} scopes=[${(bridgeGithub.scopes ?? []).join(", ")}]`
9738
+ `GitHub (via Growthub bridge): ${pc40.green("connected")} handle=${bridgeGithub.handle ?? "?"} growthub=${bridge.growthubLogin ?? "?"} scopes=[${(bridgeGithub.scopes ?? []).join(", ")}]`
9739
9739
  );
9740
9740
  } else if (bridge.bridgeAvailable) {
9741
9741
  p26.log.info(
@@ -9743,7 +9743,7 @@ async function githubWhoami(opts = {}) {
9743
9743
  );
9744
9744
  }
9745
9745
  }
9746
- p26.log.message(`Effective auth source: ${pc38.cyan(effectiveSource)}`);
9746
+ p26.log.message(`Effective auth source: ${pc40.cyan(effectiveSource)}`);
9747
9747
  }
9748
9748
  function githubLogout(opts = {}) {
9749
9749
  clearGithubToken();
@@ -9780,7 +9780,7 @@ init_onboard();
9780
9780
  init_doctor();
9781
9781
  import { Command } from "commander";
9782
9782
  import * as p31 from "@clack/prompts";
9783
- import pc43 from "picocolors";
9783
+ import pc45 from "picocolors";
9784
9784
  import fs38 from "node:fs";
9785
9785
  import path46 from "node:path";
9786
9786
  import { spawnSync as spawnSync4 } from "node:child_process";
@@ -10309,8 +10309,8 @@ function printClaudeStreamEvent(raw, debug) {
10309
10309
  const block = blockRaw;
10310
10310
  const blockType = typeof block.type === "string" ? block.type : "";
10311
10311
  if (blockType === "text") {
10312
- const text64 = typeof block.text === "string" ? block.text : "";
10313
- if (text64) console.log(pc9.green(`assistant: ${text64}`));
10312
+ const text65 = typeof block.text === "string" ? block.text : "";
10313
+ if (text65) console.log(pc9.green(`assistant: ${text65}`));
10314
10314
  } else if (blockType === "tool_use") {
10315
10315
  const name = typeof block.name === "string" ? block.name : "unknown";
10316
10316
  console.log(pc9.yellow(`tool_call: ${name}`));
@@ -10402,13 +10402,13 @@ function printItemStarted(item) {
10402
10402
  function printItemCompleted(item) {
10403
10403
  const itemType = asString(item.type);
10404
10404
  if (itemType === "agent_message") {
10405
- const text64 = asString(item.text);
10406
- if (text64) console.log(pc10.green(`assistant: ${text64}`));
10405
+ const text65 = asString(item.text);
10406
+ if (text65) console.log(pc10.green(`assistant: ${text65}`));
10407
10407
  return true;
10408
10408
  }
10409
10409
  if (itemType === "reasoning") {
10410
- const text64 = asString(item.text);
10411
- if (text64) console.log(pc10.gray(`thinking: ${text64}`));
10410
+ const text65 = asString(item.text);
10411
+ if (text65) console.log(pc10.gray(`thinking: ${text65}`));
10412
10412
  return true;
10413
10413
  }
10414
10414
  if (itemType === "tool_use") {
@@ -10458,9 +10458,9 @@ function printItemCompleted(item) {
10458
10458
  }
10459
10459
  if (itemType === "tool_result") {
10460
10460
  const isError = item.is_error === true || asString(item.status) === "error";
10461
- const text64 = asString(item.content) || asString(item.result) || asString(item.output);
10461
+ const text65 = asString(item.content) || asString(item.result) || asString(item.output);
10462
10462
  console.log((isError ? pc10.red : pc10.cyan)(`tool_result${isError ? " (error)" : ""}`));
10463
- if (text64) console.log((isError ? pc10.red : pc10.gray)(text64));
10463
+ if (text65) console.log((isError ? pc10.red : pc10.gray)(text65));
10464
10464
  return true;
10465
10465
  }
10466
10466
  return false;
@@ -10579,8 +10579,8 @@ function stringifyUnknown(value) {
10579
10579
  }
10580
10580
  function printUserMessage(messageRaw) {
10581
10581
  if (typeof messageRaw === "string") {
10582
- const text64 = messageRaw.trim();
10583
- if (text64) console.log(pc11.gray(`user: ${text64}`));
10582
+ const text65 = messageRaw.trim();
10583
+ if (text65) console.log(pc11.gray(`user: ${text65}`));
10584
10584
  return;
10585
10585
  }
10586
10586
  const message = asRecord2(messageRaw);
@@ -10593,14 +10593,14 @@ function printUserMessage(messageRaw) {
10593
10593
  if (!part) continue;
10594
10594
  const type = asString2(part.type).trim();
10595
10595
  if (type !== "output_text" && type !== "text") continue;
10596
- const text64 = asString2(part.text).trim();
10597
- if (text64) console.log(pc11.gray(`user: ${text64}`));
10596
+ const text65 = asString2(part.text).trim();
10597
+ if (text65) console.log(pc11.gray(`user: ${text65}`));
10598
10598
  }
10599
10599
  }
10600
10600
  function printAssistantMessage(messageRaw) {
10601
10601
  if (typeof messageRaw === "string") {
10602
- const text64 = messageRaw.trim();
10603
- if (text64) console.log(pc11.green(`assistant: ${text64}`));
10602
+ const text65 = messageRaw.trim();
10603
+ if (text65) console.log(pc11.green(`assistant: ${text65}`));
10604
10604
  return;
10605
10605
  }
10606
10606
  const message = asRecord2(messageRaw);
@@ -10613,13 +10613,13 @@ function printAssistantMessage(messageRaw) {
10613
10613
  if (!part) continue;
10614
10614
  const type = asString2(part.type).trim();
10615
10615
  if (type === "output_text" || type === "text") {
10616
- const text64 = asString2(part.text).trim();
10617
- if (text64) console.log(pc11.green(`assistant: ${text64}`));
10616
+ const text65 = asString2(part.text).trim();
10617
+ if (text65) console.log(pc11.green(`assistant: ${text65}`));
10618
10618
  continue;
10619
10619
  }
10620
10620
  if (type === "thinking") {
10621
- const text64 = asString2(part.text).trim();
10622
- if (text64) console.log(pc11.gray(`thinking: ${text64}`));
10621
+ const text65 = asString2(part.text).trim();
10622
+ if (text65) console.log(pc11.gray(`thinking: ${text65}`));
10623
10623
  continue;
10624
10624
  }
10625
10625
  if (type === "tool_call") {
@@ -10739,8 +10739,8 @@ function printCursorStreamEvent(raw, _debug) {
10739
10739
  return;
10740
10740
  }
10741
10741
  if (type === "thinking") {
10742
- const text64 = asString2(parsed.text).trim() || asString2(asRecord2(parsed.delta)?.text).trim();
10743
- if (text64) console.log(pc11.gray(`thinking: ${text64}`));
10742
+ const text65 = asString2(parsed.text).trim() || asString2(asRecord2(parsed.delta)?.text).trim();
10743
+ if (text65) console.log(pc11.gray(`thinking: ${text65}`));
10744
10744
  return;
10745
10745
  }
10746
10746
  if (type === "tool_call") {
@@ -10778,8 +10778,8 @@ function printCursorStreamEvent(raw, _debug) {
10778
10778
  }
10779
10779
  if (type === "text") {
10780
10780
  const part = asRecord2(parsed.part);
10781
- const text64 = asString2(part?.text);
10782
- if (text64) console.log(pc11.green(`assistant: ${text64}`));
10781
+ const text65 = asString2(part?.text);
10782
+ if (text65) console.log(pc11.green(`assistant: ${text65}`));
10783
10783
  return;
10784
10784
  }
10785
10785
  if (type === "tool_use") {
@@ -10842,8 +10842,8 @@ function errorText2(value) {
10842
10842
  }
10843
10843
  function printTextMessage(prefix, colorize, messageRaw) {
10844
10844
  if (typeof messageRaw === "string") {
10845
- const text64 = messageRaw.trim();
10846
- if (text64) console.log(colorize(`${prefix}: ${text64}`));
10845
+ const text65 = messageRaw.trim();
10846
+ if (text65) console.log(colorize(`${prefix}: ${text65}`));
10847
10847
  return;
10848
10848
  }
10849
10849
  const message = asRecord3(messageRaw);
@@ -10856,13 +10856,13 @@ function printTextMessage(prefix, colorize, messageRaw) {
10856
10856
  if (!part) continue;
10857
10857
  const type = asString3(part.type).trim();
10858
10858
  if (type === "output_text" || type === "text" || type === "content") {
10859
- const text64 = asString3(part.text).trim() || asString3(part.content).trim();
10860
- if (text64) console.log(colorize(`${prefix}: ${text64}`));
10859
+ const text65 = asString3(part.text).trim() || asString3(part.content).trim();
10860
+ if (text65) console.log(colorize(`${prefix}: ${text65}`));
10861
10861
  continue;
10862
10862
  }
10863
10863
  if (type === "thinking") {
10864
- const text64 = asString3(part.text).trim();
10865
- if (text64) console.log(pc12.gray(`thinking: ${text64}`));
10864
+ const text65 = asString3(part.text).trim();
10865
+ if (text65) console.log(pc12.gray(`thinking: ${text65}`));
10866
10866
  continue;
10867
10867
  }
10868
10868
  if (type === "tool_call") {
@@ -10914,8 +10914,8 @@ function printGeminiStreamEvent(raw, _debug) {
10914
10914
  return;
10915
10915
  }
10916
10916
  if (subtype === "error") {
10917
- const text64 = errorText2(parsed.error ?? parsed.message ?? parsed.detail);
10918
- if (text64) console.log(pc12.red(`error: ${text64}`));
10917
+ const text65 = errorText2(parsed.error ?? parsed.message ?? parsed.detail);
10918
+ if (text65) console.log(pc12.red(`error: ${text65}`));
10919
10919
  return;
10920
10920
  }
10921
10921
  console.log(pc12.blue(`system: ${subtype || "event"}`));
@@ -10930,8 +10930,8 @@ function printGeminiStreamEvent(raw, _debug) {
10930
10930
  return;
10931
10931
  }
10932
10932
  if (type === "thinking") {
10933
- const text64 = asString3(parsed.text).trim() || asString3(asRecord3(parsed.delta)?.text).trim();
10934
- if (text64) console.log(pc12.gray(`thinking: ${text64}`));
10933
+ const text65 = asString3(parsed.text).trim() || asString3(asRecord3(parsed.delta)?.text).trim();
10934
+ if (text65) console.log(pc12.gray(`thinking: ${text65}`));
10935
10935
  return;
10936
10936
  }
10937
10937
  if (type === "tool_call") {
@@ -10967,8 +10967,8 @@ function printGeminiStreamEvent(raw, _debug) {
10967
10967
  return;
10968
10968
  }
10969
10969
  if (type === "error") {
10970
- const text64 = errorText2(parsed.error ?? parsed.message ?? parsed.detail);
10971
- if (text64) console.log(pc12.red(`error: ${text64}`));
10970
+ const text65 = errorText2(parsed.error ?? parsed.message ?? parsed.detail);
10971
+ if (text65) console.log(pc12.red(`error: ${text65}`));
10972
10972
  return;
10973
10973
  }
10974
10974
  console.log(line);
@@ -10976,9 +10976,9 @@ function printGeminiStreamEvent(raw, _debug) {
10976
10976
 
10977
10977
  // ../packages/adapters/opencode-local/src/cli/format-event.ts
10978
10978
  import pc13 from "picocolors";
10979
- function safeJsonParse(text64) {
10979
+ function safeJsonParse(text65) {
10980
10980
  try {
10981
- return JSON.parse(text64);
10981
+ return JSON.parse(text65);
10982
10982
  } catch {
10983
10983
  return null;
10984
10984
  }
@@ -11022,14 +11022,14 @@ function printOpenCodeStreamEvent(raw, _debug) {
11022
11022
  }
11023
11023
  if (type === "text") {
11024
11024
  const part = asRecord4(parsed.part);
11025
- const text64 = asString4(part?.text).trim();
11026
- if (text64) console.log(pc13.green(`assistant: ${text64}`));
11025
+ const text65 = asString4(part?.text).trim();
11026
+ if (text65) console.log(pc13.green(`assistant: ${text65}`));
11027
11027
  return;
11028
11028
  }
11029
11029
  if (type === "reasoning") {
11030
11030
  const part = asRecord4(parsed.part);
11031
- const text64 = asString4(part?.text).trim();
11032
- if (text64) console.log(pc13.gray(`thinking: ${text64}`));
11031
+ const text65 = asString4(part?.text).trim();
11032
+ if (text65) console.log(pc13.gray(`thinking: ${text65}`));
11033
11033
  return;
11034
11034
  }
11035
11035
  if (type === "tool_use") {
@@ -11077,9 +11077,9 @@ function printOpenCodeStreamEvent(raw, _debug) {
11077
11077
 
11078
11078
  // ../packages/adapters/pi-local/src/cli/format-event.ts
11079
11079
  import pc14 from "picocolors";
11080
- function safeJsonParse2(text64) {
11080
+ function safeJsonParse2(text65) {
11081
11081
  try {
11082
- return JSON.parse(text64);
11082
+ return JSON.parse(text65);
11083
11083
  } catch {
11084
11084
  return null;
11085
11085
  }
@@ -11121,9 +11121,9 @@ function printPiStreamEvent(raw, _debug) {
11121
11121
  const message = asRecord5(parsed.message);
11122
11122
  if (message) {
11123
11123
  const content = message.content;
11124
- const text64 = extractTextContent(content);
11125
- if (text64) {
11126
- console.log(pc14.green(`assistant: ${text64}`));
11124
+ const text65 = extractTextContent(content);
11125
+ if (text65) {
11126
+ console.log(pc14.green(`assistant: ${text65}`));
11127
11127
  }
11128
11128
  }
11129
11129
  return;
@@ -13032,17 +13032,17 @@ function assertDeleteConfirmation(company, opts) {
13032
13032
  if (!opts.yes) {
13033
13033
  throw new Error("Deletion requires --yes.");
13034
13034
  }
13035
- const confirm14 = opts.confirm?.trim();
13036
- if (!confirm14) {
13035
+ const confirm15 = opts.confirm?.trim();
13036
+ if (!confirm15) {
13037
13037
  throw new Error(
13038
13038
  "Deletion requires --confirm <value> where value matches the company ID or issue prefix."
13039
13039
  );
13040
13040
  }
13041
- const confirmsById = confirm14 === company.id;
13042
- const confirmsByPrefix = confirm14.toUpperCase() === company.issuePrefix.toUpperCase();
13041
+ const confirmsById = confirm15 === company.id;
13042
+ const confirmsByPrefix = confirm15.toUpperCase() === company.issuePrefix.toUpperCase();
13043
13043
  if (!confirmsById && !confirmsByPrefix) {
13044
13044
  throw new Error(
13045
- `Confirmation '${confirm14}' does not match target company. Expected ID '${company.id}' or prefix '${company.issuePrefix}'.`
13045
+ `Confirmation '${confirm15}' does not match target company. Expected ID '${company.id}' or prefix '${company.issuePrefix}'.`
13046
13046
  );
13047
13047
  }
13048
13048
  }
@@ -13433,8 +13433,8 @@ function filterIssueRows(rows, match) {
13433
13433
  if (!match?.trim()) return rows;
13434
13434
  const needle = match.trim().toLowerCase();
13435
13435
  return rows.filter((row) => {
13436
- const text64 = [row.identifier, row.title, row.description].filter((part) => Boolean(part)).join("\n").toLowerCase();
13437
- return text64.includes(needle);
13436
+ const text65 = [row.identifier, row.title, row.description].filter((part) => Boolean(part)).join("\n").toLowerCase();
13437
+ return text65.includes(needle);
13438
13438
  });
13439
13439
  }
13440
13440
 
@@ -15321,7 +15321,7 @@ init_banner();
15321
15321
  import path33 from "node:path";
15322
15322
  import { pathToFileURL as pathToFileURL2 } from "node:url";
15323
15323
  import * as p19 from "@clack/prompts";
15324
- import pc28 from "picocolors";
15324
+ import pc30 from "picocolors";
15325
15325
 
15326
15326
  // src/commands/kit-fork.ts
15327
15327
  import * as p18 from "@clack/prompts";
@@ -16636,22 +16636,47 @@ async function kitForkConnect(opts) {
16636
16636
  async function kitForkPolicyCommand(opts) {
16637
16637
  const reg = findRegistrationOrThrow(opts.forkId);
16638
16638
  let policy = readKitForkPolicy(reg.forkPath);
16639
+ const before = JSON.parse(JSON.stringify(policy));
16639
16640
  if (opts.set && opts.set.length > 0) {
16640
16641
  for (const entry of opts.set) {
16641
16642
  policy = applyPolicyAssignment(policy, entry);
16642
16643
  }
16643
- writeKitForkPolicy(reg.forkPath, policy);
16644
- appendKitForkTraceEvent(reg.forkPath, {
16645
- forkId: reg.forkId,
16646
- kitId: reg.kitId,
16647
- type: "policy_updated",
16648
- summary: `Policy updated via CLI: ${opts.set.join(", ")}`
16649
- });
16644
+ if (!opts.dryRun) {
16645
+ writeKitForkPolicy(reg.forkPath, policy);
16646
+ appendKitForkTraceEvent(reg.forkPath, {
16647
+ forkId: reg.forkId,
16648
+ kitId: reg.kitId,
16649
+ type: "policy_updated",
16650
+ summary: `Policy updated via CLI: ${opts.set.join(", ")}`,
16651
+ detail: { changedFields: diffPolicyFields(before, policy) }
16652
+ });
16653
+ }
16654
+ }
16655
+ if (opts.edit) {
16656
+ const next = await runInteractivePolicyEditor(reg.forkId, policy);
16657
+ if (!next) {
16658
+ p17.log.info("Policy edit cancelled \u2014 no changes written.");
16659
+ return;
16660
+ }
16661
+ policy = next;
16662
+ if (!opts.dryRun) {
16663
+ writeKitForkPolicy(reg.forkPath, policy);
16664
+ appendKitForkTraceEvent(reg.forkPath, {
16665
+ forkId: reg.forkId,
16666
+ kitId: reg.kitId,
16667
+ type: "policy_updated",
16668
+ summary: `Policy updated via interactive editor`,
16669
+ detail: { changedFields: diffPolicyFields(before, policy) }
16670
+ });
16671
+ }
16650
16672
  }
16651
16673
  if (opts.json) {
16652
16674
  console.log(JSON.stringify(policy, null, 2));
16653
16675
  return;
16654
16676
  }
16677
+ if (opts.dryRun) {
16678
+ p17.log.info(`${pc26.yellow("Dry run \u2014 no changes written.")} Preview below:`);
16679
+ }
16655
16680
  p17.log.message(
16656
16681
  `Policy for fork ${pc26.cyan(reg.forkId)}:
16657
16682
  autoApprove: ${policy.autoApprove}
@@ -16663,6 +16688,150 @@ async function kitForkPolicyCommand(opts) {
16663
16688
  allowedScripts: [${policy.allowedScripts.join(", ")}]`
16664
16689
  );
16665
16690
  }
16691
+ function diffPolicyFields(before, after) {
16692
+ const fields = [
16693
+ "autoApprove",
16694
+ "autoApproveDepUpdates",
16695
+ "remoteSyncMode",
16696
+ "interactiveConflicts",
16697
+ "untouchablePaths",
16698
+ "confirmBeforeChange",
16699
+ "allowedScripts"
16700
+ ];
16701
+ const changed = [];
16702
+ for (const f of fields) {
16703
+ const a = JSON.stringify(before[f]);
16704
+ const b = JSON.stringify(after[f]);
16705
+ if (a !== b) changed.push(String(f));
16706
+ }
16707
+ return changed;
16708
+ }
16709
+ function validateProtectedPath(raw) {
16710
+ const v = raw.trim();
16711
+ if (!v) return "Path cannot be empty.";
16712
+ if (v.startsWith("/")) return "Use a relative path (no leading slash).";
16713
+ if (v.includes("\0")) return "Path contains an invalid character.";
16714
+ return void 0;
16715
+ }
16716
+ async function runInteractivePolicyEditor(forkId, current) {
16717
+ p17.intro(pc26.bold(`Edit policy: ${forkId}`));
16718
+ const autoApprove = await p17.select({
16719
+ message: "Auto-approve scaffold additions and modifications:",
16720
+ initialValue: current.autoApprove,
16721
+ options: [
16722
+ { value: "none", label: "none", hint: "every action requires confirmation (safest)" },
16723
+ { value: "additive", label: "additive", hint: "new files auto-approve; modifications confirm" },
16724
+ { value: "all", label: "all", hint: "all safe actions auto-approve (still honours protected paths)" }
16725
+ ]
16726
+ });
16727
+ if (p17.isCancel(autoApprove)) {
16728
+ p17.cancel("Cancelled.");
16729
+ return null;
16730
+ }
16731
+ const autoApproveDepUpdates = await p17.select({
16732
+ message: "Auto-approve package.json dependency changes:",
16733
+ initialValue: current.autoApproveDepUpdates,
16734
+ options: [
16735
+ { value: "none", label: "none", hint: "never auto-approve dep changes" },
16736
+ { value: "additive", label: "additive", hint: "new deps auto-approve, upgrades need confirm" },
16737
+ { value: "all", label: "all", hint: "even upgrades auto-approve (additive-only, never removes)" }
16738
+ ]
16739
+ });
16740
+ if (p17.isCancel(autoApproveDepUpdates)) {
16741
+ p17.cancel("Cancelled.");
16742
+ return null;
16743
+ }
16744
+ const remoteSyncMode = await p17.select({
16745
+ message: "Remote sync mode:",
16746
+ initialValue: current.remoteSyncMode,
16747
+ options: [
16748
+ { value: "off", label: "off", hint: "purely local \u2014 no GitHub interaction" },
16749
+ { value: "branch", label: "branch", hint: "push heal branches, no PR" },
16750
+ { value: "pr", label: "pr", hint: "push branch + open draft PR" }
16751
+ ]
16752
+ });
16753
+ if (p17.isCancel(remoteSyncMode)) {
16754
+ p17.cancel("Cancelled.");
16755
+ return null;
16756
+ }
16757
+ const interactiveConflicts = await p17.confirm({
16758
+ message: "Pause on remote conflicts for interactive resolution?",
16759
+ initialValue: current.interactiveConflicts
16760
+ });
16761
+ if (p17.isCancel(interactiveConflicts)) {
16762
+ p17.cancel("Cancelled.");
16763
+ return null;
16764
+ }
16765
+ let untouchablePaths = [...current.untouchablePaths];
16766
+ while (true) {
16767
+ const currentList = untouchablePaths.length > 0 ? untouchablePaths.join(", ") : pc26.dim("(none)");
16768
+ const action = await p17.select({
16769
+ message: `Protected paths \u2014 never modified by heal [current: ${currentList}]`,
16770
+ options: [
16771
+ { value: "__done", label: "\u2713 Done" },
16772
+ { value: "__add", label: "+ Add path" },
16773
+ ...untouchablePaths.length > 0 ? [{ value: "__remove", label: "\u2212 Remove path" }] : []
16774
+ ]
16775
+ });
16776
+ if (p17.isCancel(action)) {
16777
+ p17.cancel("Cancelled.");
16778
+ return null;
16779
+ }
16780
+ if (action === "__done") break;
16781
+ if (action === "__add") {
16782
+ const next = await p17.text({
16783
+ message: "New protected path (glob prefix, relative):",
16784
+ placeholder: "skills/ or .env.local",
16785
+ validate: validateProtectedPath
16786
+ });
16787
+ if (p17.isCancel(next)) {
16788
+ p17.cancel("Cancelled.");
16789
+ return null;
16790
+ }
16791
+ const clean = next.trim();
16792
+ if (clean && !untouchablePaths.includes(clean)) {
16793
+ untouchablePaths = [...untouchablePaths, clean];
16794
+ }
16795
+ }
16796
+ if (action === "__remove") {
16797
+ const toRemove = await p17.select({
16798
+ message: "Select path to remove:",
16799
+ options: untouchablePaths.map((v) => ({ value: v, label: v }))
16800
+ });
16801
+ if (p17.isCancel(toRemove)) {
16802
+ p17.cancel("Cancelled.");
16803
+ return null;
16804
+ }
16805
+ untouchablePaths = untouchablePaths.filter((x) => x !== toRemove);
16806
+ }
16807
+ }
16808
+ p17.note(
16809
+ [
16810
+ ` autoApprove: ${autoApprove}`,
16811
+ ` autoApproveDepUpdates: ${autoApproveDepUpdates}`,
16812
+ ` remoteSyncMode: ${remoteSyncMode}`,
16813
+ ` interactiveConflicts: ${interactiveConflicts}`,
16814
+ ` untouchablePaths: [${untouchablePaths.join(", ")}]`
16815
+ ].join("\n"),
16816
+ "New policy"
16817
+ );
16818
+ const confirmed = await p17.confirm({
16819
+ message: "Apply these settings?",
16820
+ initialValue: true
16821
+ });
16822
+ if (p17.isCancel(confirmed) || !confirmed) {
16823
+ p17.cancel("No changes written.");
16824
+ return null;
16825
+ }
16826
+ return {
16827
+ ...current,
16828
+ autoApprove,
16829
+ autoApproveDepUpdates,
16830
+ remoteSyncMode,
16831
+ interactiveConflicts: Boolean(interactiveConflicts),
16832
+ untouchablePaths
16833
+ };
16834
+ }
16666
16835
  function applyPolicyAssignment(policy, assignment) {
16667
16836
  const plusMatch = assignment.match(/^([a-zA-Z]+)\+=(.+)$/);
16668
16837
  const eqMatch = assignment.match(/^([a-zA-Z]+)=(.+)$/);
@@ -16744,8 +16913,26 @@ function registerKitForkRemoteSubcommands(kitFork) {
16744
16913
  kitFork.command("connect").description("Bind an existing registered fork to a GitHub remote repository.").requiredOption("--fork-id <id>", "Registered fork id").requiredOption("--remote <owner/repo>", "GitHub repository to connect as origin").option("--default-branch <name>", "Remote default branch (default: main)").option("--json", "Emit machine-readable output").action(async (opts) => {
16745
16914
  await kitForkConnect({ forkId: opts.forkId, remote: opts.remote, defaultBranch: opts.defaultBranch, json: opts.json });
16746
16915
  });
16747
- kitFork.command("policy").description("View or modify the per-fork heal policy.").requiredOption("--fork-id <id>", "Registered fork id").option("--set <field=value...>", "Update one or more fields (e.g. autoApprove=none untouchablePaths+=custom/)").option("--json", "Emit machine-readable output").action(async (opts) => {
16748
- await kitForkPolicyCommand({ forkId: opts.forkId, set: opts.set, json: opts.json });
16916
+ kitFork.command("policy").description("View, edit interactively, or set fields on the per-fork heal policy.").argument("[fork-id]", "Registered fork id (takes precedence over --fork-id)").option("--fork-id <id>", "Registered fork id (alternative to positional arg)").option("--set <field=value...>", "Update one or more fields (e.g. autoApprove=none untouchablePaths+=custom/)").option("--edit", "Launch interactive editor (clack prompts)").option("--dry-run", "Show planned changes without writing policy.json").option("--json", "Emit machine-readable output").addHelpText("after", `
16917
+ Examples:
16918
+ $ growthub kit fork policy <fork-id> # view policy
16919
+ $ growthub kit fork policy <fork-id> --edit # interactive editor
16920
+ $ growthub kit fork policy <fork-id> --set autoApprove=all
16921
+ $ growthub kit fork policy <fork-id> --set untouchablePaths+=skills/ --dry-run
16922
+ `).action(async (forkIdArg, opts) => {
16923
+ const forkId = forkIdArg ?? opts.forkId;
16924
+ if (!forkId) {
16925
+ console.error(pc26.red("Missing fork-id. Pass it as an argument or with --fork-id."));
16926
+ process.exitCode = 1;
16927
+ return;
16928
+ }
16929
+ await kitForkPolicyCommand({
16930
+ forkId,
16931
+ set: opts.set,
16932
+ edit: opts.edit,
16933
+ dryRun: opts.dryRun,
16934
+ json: opts.json
16935
+ });
16749
16936
  });
16750
16937
  kitFork.command("trace").description("Show the append-only event log for a fork.").requiredOption("--fork-id <id>", "Registered fork id").option("--tail <n>", "Only show the last N events", (v) => Number(v)).option("--json", "Emit machine-readable output").action((opts) => {
16751
16938
  kitForkTraceCommand({ forkId: opts.forkId, tail: opts.tail, json: opts.json });
@@ -16757,72 +16944,176 @@ function registerKitForkRemoteSubcommands(kitFork) {
16757
16944
 
16758
16945
  // src/commands/kit-fork.ts
16759
16946
  init_banner();
16947
+ import pc29 from "picocolors";
16948
+
16949
+ // src/utils/table-renderer.ts
16760
16950
  import pc27 from "picocolors";
16951
+ var ANSI_PATTERN = /\x1b\[[0-9;]*m/g;
16952
+ function stripAnsi(input) {
16953
+ return input.replace(ANSI_PATTERN, "");
16954
+ }
16955
+ function visibleLength(input) {
16956
+ return stripAnsi(input).length;
16957
+ }
16958
+ function truncate(value, max) {
16959
+ if (max <= 0) return "";
16960
+ if (visibleLength(value) <= max) return value;
16961
+ if (max <= 1) return value.slice(0, max);
16962
+ const plain = stripAnsi(value);
16963
+ const keep = Math.max(0, max - 1);
16964
+ return plain.slice(0, keep) + "\u2026";
16965
+ }
16966
+ function pad(value, width, align) {
16967
+ const vw = visibleLength(value);
16968
+ if (vw >= width) return value;
16969
+ const delta = width - vw;
16970
+ if (align === "right") return " ".repeat(delta) + value;
16971
+ if (align === "center") {
16972
+ const left = Math.floor(delta / 2);
16973
+ const right = delta - left;
16974
+ return " ".repeat(left) + value + " ".repeat(right);
16975
+ }
16976
+ return value + " ".repeat(delta);
16977
+ }
16978
+ function computeColumnWidths(columns, cells) {
16979
+ return columns.map((col, colIdx) => {
16980
+ if (col.width && col.width > 0) return col.width;
16981
+ const contentMax = cells.reduce(
16982
+ (acc, row) => Math.max(acc, visibleLength(row[colIdx] ?? "")),
16983
+ visibleLength(col.label)
16984
+ );
16985
+ if (col.maxWidth && contentMax > col.maxWidth) return col.maxWidth;
16986
+ return contentMax;
16987
+ });
16988
+ }
16989
+ function renderTable(opts) {
16990
+ const { columns, rows, showHeader = true, emptyText } = opts;
16991
+ if (rows.length === 0 && emptyText) {
16992
+ return pc27.dim(" " + emptyText);
16993
+ }
16994
+ const rawCells = rows.map(
16995
+ (row) => columns.map((col) => {
16996
+ const raw = row[col.key];
16997
+ if (col.format) return col.format(raw, row);
16998
+ if (raw === void 0 || raw === null) return "";
16999
+ return String(raw);
17000
+ })
17001
+ );
17002
+ const widths = computeColumnWidths(columns, rawCells);
17003
+ const lines = [];
17004
+ if (showHeader) {
17005
+ const header = columns.map(
17006
+ (col, i) => pad(pc27.bold(truncate(col.label, widths[i])), widths[i], col.align ?? "left")
17007
+ ).join(" ");
17008
+ lines.push(" " + header);
17009
+ lines.push(" " + widths.map((w) => pc27.dim("\u2500".repeat(w))).join(" "));
17010
+ }
17011
+ for (const cells of rawCells) {
17012
+ const line = columns.map(
17013
+ (col, i) => pad(truncate(cells[i] ?? "", widths[i]), widths[i], col.align ?? "left")
17014
+ ).join(" ");
17015
+ lines.push(" " + line);
17016
+ }
17017
+ return lines.join("\n");
17018
+ }
17019
+
17020
+ // src/utils/progress.ts
17021
+ import pc28 from "picocolors";
17022
+ function renderProgressBar(current, total, opts = {}) {
17023
+ const width = opts.width ?? 24;
17024
+ const filled = opts.filledChar ?? "\u2588";
17025
+ const empty = opts.emptyChar ?? "\u2591";
17026
+ const showCounts = opts.showCounts ?? true;
17027
+ const color = opts.color ?? true;
17028
+ const safeTotal = Math.max(0, total);
17029
+ const safeCurrent = Math.min(Math.max(0, current), safeTotal || current);
17030
+ const ratio = safeTotal > 0 ? safeCurrent / safeTotal : 0;
17031
+ const filledCells = Math.round(ratio * width);
17032
+ const bar = filled.repeat(filledCells) + empty.repeat(Math.max(0, width - filledCells));
17033
+ const pct = Math.round(ratio * 100);
17034
+ const painted = color ? pct >= 80 ? pc28.green(bar) : pct >= 50 ? pc28.yellow(bar) : pct > 0 ? pc28.red(bar) : pc28.dim(bar) : bar;
17035
+ if (!showCounts) return `[${painted}]`;
17036
+ return `[${painted}] ${safeCurrent}/${safeTotal || 0} (${pct}%)`;
17037
+ }
17038
+ function formatRelative(iso, nowMs = Date.now()) {
17039
+ if (!iso) return "\u2014";
17040
+ const ts = new Date(iso).getTime();
17041
+ if (!Number.isFinite(ts)) return "\u2014";
17042
+ const diff = Math.max(0, nowMs - ts);
17043
+ if (diff < 1e4) return "just now";
17044
+ if (diff < 6e4) return `${Math.floor(diff / 1e3)}s ago`;
17045
+ if (diff < 36e5) return `${Math.floor(diff / 6e4)}m ago`;
17046
+ if (diff < 864e5) return `${Math.floor(diff / 36e5)}h ago`;
17047
+ if (diff < 30 * 864e5) return `${Math.floor(diff / 864e5)}d ago`;
17048
+ return new Date(iso).toISOString().slice(0, 10);
17049
+ }
17050
+
17051
+ // src/commands/kit-fork.ts
16761
17052
  init_service();
16762
17053
  function hr(width = 72) {
16763
- return pc27.dim("\u2500".repeat(width));
17054
+ return pc29.dim("\u2500".repeat(width));
16764
17055
  }
16765
17056
  function severityBadge(s) {
16766
17057
  switch (s) {
16767
17058
  case "critical":
16768
- return pc27.red("\u25CF critical");
17059
+ return pc29.red("\u25CF critical");
16769
17060
  case "warning":
16770
- return pc27.yellow("\u25CF warning");
17061
+ return pc29.yellow("\u25CF warning");
16771
17062
  case "info":
16772
- return pc27.cyan("\u25CF info");
17063
+ return pc29.cyan("\u25CF info");
16773
17064
  default:
16774
- return pc27.green("\u25CF in-sync");
17065
+ return pc29.green("\u25CF in-sync");
16775
17066
  }
16776
17067
  }
16777
17068
  function jobStatusBadge(status) {
16778
17069
  switch (status) {
16779
17070
  case "running":
16780
- return pc27.cyan("\u27F3 running");
17071
+ return pc29.cyan("\u27F3 running");
16781
17072
  case "completed":
16782
- return pc27.green("\u2713 completed");
17073
+ return pc29.green("\u2713 completed");
16783
17074
  case "failed":
16784
- return pc27.red("\u2717 failed");
17075
+ return pc29.red("\u2717 failed");
16785
17076
  case "cancelled":
16786
- return pc27.dim("\u25CB cancelled");
17077
+ return pc29.dim("\u25CB cancelled");
16787
17078
  default:
16788
- return pc27.dim("\u2026 pending");
17079
+ return pc29.dim("\u2026 pending");
16789
17080
  }
16790
17081
  }
16791
17082
  function formatDate(iso) {
16792
- if (!iso) return pc27.dim("\u2014");
17083
+ if (!iso) return pc29.dim("\u2014");
16793
17084
  return new Date(iso).toLocaleString();
16794
17085
  }
16795
17086
  function printDriftReport(report) {
16796
17087
  console.log("");
16797
17088
  console.log(
16798
- pc27.bold(`Fork: ${report.forkId}`) + " " + severityBadge(report.overallSeverity)
17089
+ pc29.bold(`Fork: ${report.forkId}`) + " " + severityBadge(report.overallSeverity)
16799
17090
  );
16800
17091
  console.log(
16801
- pc27.dim(`Kit: ${report.kitId}`) + " " + pc27.dim(`fork v${report.forkVersion} \u2192 upstream v${report.upstreamVersion}`)
17092
+ pc29.dim(`Kit: ${report.kitId}`) + " " + pc29.dim(`fork v${report.forkVersion} \u2192 upstream v${report.upstreamVersion}`)
16802
17093
  );
16803
17094
  console.log(hr());
16804
17095
  if (report.fileDrifts.length === 0 && report.packageDrifts.length === 0) {
16805
- console.log(pc27.green(" No drift detected \u2014 fork is in sync."));
17096
+ console.log(pc29.green(" No drift detected \u2014 fork is in sync."));
16806
17097
  }
16807
17098
  if (report.fileDrifts.length > 0) {
16808
- console.log(pc27.bold("\n File Drift:"));
17099
+ console.log(pc29.bold("\n File Drift:"));
16809
17100
  for (const d of report.fileDrifts) {
16810
- const badge2 = d.changeType === "added" ? pc27.cyan(" +") : d.changeType === "modified" ? pc27.yellow(" ~") : pc27.red(" -");
16811
- console.log(`${badge2} ${d.relativePath} ${pc27.dim(d.description)}`);
17101
+ const badge2 = d.changeType === "added" ? pc29.cyan(" +") : d.changeType === "modified" ? pc29.yellow(" ~") : pc29.red(" -");
17102
+ console.log(`${badge2} ${d.relativePath} ${pc29.dim(d.description)}`);
16812
17103
  }
16813
17104
  }
16814
17105
  if (report.packageDrifts.length > 0) {
16815
- console.log(pc27.bold("\n Package Drift:"));
17106
+ console.log(pc29.bold("\n Package Drift:"));
16816
17107
  for (const d of report.packageDrifts) {
16817
- const badge2 = d.changeType === "added" ? pc27.cyan(" +") : d.changeType === "updated" ? pc27.yellow(" ~") : pc27.red(" -");
17108
+ const badge2 = d.changeType === "added" ? pc29.cyan(" +") : d.changeType === "updated" ? pc29.yellow(" ~") : pc29.red(" -");
16818
17109
  const ver = d.forkVersion ? `${d.forkVersion} \u2192 ${d.upstreamVersion}` : `(new) ${d.upstreamVersion}`;
16819
- console.log(`${badge2} ${d.packageName} ${pc27.dim(ver)}`);
17110
+ console.log(`${badge2} ${d.packageName} ${pc29.dim(ver)}`);
16820
17111
  }
16821
17112
  }
16822
17113
  if (report.customSkillsDetected.length > 0) {
16823
- console.log(pc27.bold("\n Custom Skills Detected (always preserved):"));
17114
+ console.log(pc29.bold("\n Custom Skills Detected (always preserved):"));
16824
17115
  for (const s of report.customSkillsDetected) {
16825
- console.log(` ${pc27.magenta("\u2691")} ${s}`);
17116
+ console.log(` ${pc29.magenta("\u2691")} ${s}`);
16826
17117
  }
16827
17118
  }
16828
17119
  console.log("");
@@ -16831,56 +17122,381 @@ function printDriftReport(report) {
16831
17122
  function printHealPlan(plan) {
16832
17123
  console.log("");
16833
17124
  console.log(
16834
- pc27.bold(`Heal Plan: ${plan.forkId}`) + pc27.dim(` v${plan.fromVersion} \u2192 v${plan.toVersion}`)
17125
+ pc29.bold(`Heal Plan: ${plan.forkId}`) + pc29.dim(` v${plan.fromVersion} \u2192 v${plan.toVersion}`)
16835
17126
  );
16836
- console.log(pc27.dim("Estimated risk: ") + severityBadge(plan.estimatedRisk));
17127
+ console.log(pc29.dim("Estimated risk: ") + severityBadge(plan.estimatedRisk));
16837
17128
  console.log(hr());
16838
17129
  if (plan.actions.length === 0) {
16839
- console.log(pc27.green(" No actions needed."));
17130
+ console.log(pc29.green(" No actions needed."));
16840
17131
  } else {
16841
- console.log(pc27.bold(` ${plan.actions.length} action(s) planned:`));
17132
+ console.log(pc29.bold(` ${plan.actions.length} action(s) planned:`));
16842
17133
  for (const a of plan.actions) {
16843
- const icon = a.actionType === "skip_user_modified" ? pc27.dim(" \u25CB") : pc27.cyan(" \u2192");
17134
+ const icon = a.actionType === "skip_user_modified" ? pc29.dim(" \u25CB") : pc29.cyan(" \u2192");
16844
17135
  console.log(`${icon} ${a.description}`);
16845
17136
  }
16846
17137
  }
16847
17138
  if (plan.preservedPaths.length > 0) {
16848
- console.log(pc27.bold(`
17139
+ console.log(pc29.bold(`
16849
17140
  ${plan.preservedPaths.length} path(s) preserved (user modifications kept):`));
16850
17141
  for (const pp of plan.preservedPaths) {
16851
- console.log(pc27.dim(` \u2691 ${pp}`));
17142
+ console.log(pc29.dim(` \u2691 ${pp}`));
16852
17143
  }
16853
17144
  }
16854
17145
  console.log("");
16855
17146
  console.log(hr());
16856
17147
  }
17148
+ function statusIconForDrift(severity) {
17149
+ switch (severity) {
17150
+ case "critical":
17151
+ return pc29.red("\u2717 drift-major");
17152
+ case "warning":
17153
+ return pc29.yellow("\u26A0 drift-warn");
17154
+ case "info":
17155
+ return pc29.cyan("~ drift-minor");
17156
+ default:
17157
+ return pc29.green("\u2713 synced");
17158
+ }
17159
+ }
17160
+ function summarizeFork(fork, opts = {}) {
17161
+ let severity = "unknown";
17162
+ let upstreamVersion = null;
17163
+ let lastHealAt = fork.lastSyncedAt ?? null;
17164
+ if (!opts.skipUpstreamCheck) {
17165
+ try {
17166
+ const report = detectKitForkDrift(fork);
17167
+ severity = report.overallSeverity;
17168
+ upstreamVersion = report.upstreamVersion;
17169
+ } catch {
17170
+ severity = "unknown";
17171
+ }
17172
+ }
17173
+ let protectedPaths = [];
17174
+ try {
17175
+ const policy = readKitForkPolicy(fork.forkPath);
17176
+ protectedPaths = policy.untouchablePaths.slice(0, 3);
17177
+ } catch {
17178
+ }
17179
+ if (!lastHealAt) {
17180
+ try {
17181
+ const events = readKitForkTrace(fork.forkPath);
17182
+ const last = [...events].reverse().find((e) => e.type === "heal_applied");
17183
+ if (last) lastHealAt = last.timestamp;
17184
+ } catch {
17185
+ }
17186
+ }
17187
+ return {
17188
+ forkId: fork.forkId,
17189
+ label: fork.label ?? null,
17190
+ kitId: fork.kitId,
17191
+ baseVersion: fork.baseVersion,
17192
+ forkPath: fork.forkPath,
17193
+ severity,
17194
+ upstreamVersion,
17195
+ protectedPaths,
17196
+ lastHealAt,
17197
+ hasRemote: Boolean(fork.remote)
17198
+ };
17199
+ }
17200
+ function renderForkTable(summaries) {
17201
+ return renderTable({
17202
+ columns: [
17203
+ {
17204
+ key: "forkId",
17205
+ label: "Fork ID",
17206
+ maxWidth: 26,
17207
+ format: (v, row) => pc29.cyan(row.label ?? String(v))
17208
+ },
17209
+ {
17210
+ key: "kitId",
17211
+ label: "Kit",
17212
+ maxWidth: 22
17213
+ },
17214
+ {
17215
+ key: "baseVersion",
17216
+ label: "Base",
17217
+ format: (v) => `v${v}`
17218
+ },
17219
+ {
17220
+ key: "upstreamVersion",
17221
+ label: "Upstream",
17222
+ format: (v) => v ? `v${v}` : pc29.dim("\u2014")
17223
+ },
17224
+ {
17225
+ key: "severity",
17226
+ label: "Status",
17227
+ format: (v) => v === "unknown" ? pc29.dim("\u25CB unknown") : statusIconForDrift(v)
17228
+ },
17229
+ {
17230
+ key: "protectedPaths",
17231
+ label: "Protected",
17232
+ maxWidth: 18,
17233
+ format: (v) => {
17234
+ const arr = v;
17235
+ if (!arr || arr.length === 0) return pc29.dim("\u2014");
17236
+ return arr.join(",");
17237
+ }
17238
+ },
17239
+ {
17240
+ key: "lastHealAt",
17241
+ label: "Last Heal",
17242
+ format: (v) => v ? formatRelative(v) : pc29.dim("\u2014")
17243
+ }
17244
+ ],
17245
+ rows: summaries,
17246
+ emptyText: "No forks registered yet. Run `growthub kit fork register <path>` to get started."
17247
+ });
17248
+ }
16857
17249
  function printForkList(forks) {
16858
17250
  if (forks.length === 0) {
16859
- console.log(pc27.dim(" No forks registered yet. Run `growthub kit fork register <path>` to get started."));
17251
+ console.log(pc29.dim(" No forks registered yet. Run `growthub kit fork register <path>` to get started."));
16860
17252
  return;
16861
17253
  }
17254
+ const summaries = forks.map((f) => summarizeFork(f, { skipUpstreamCheck: true }));
16862
17255
  console.log("");
16863
- console.log(pc27.bold("Registered Kit Forks") + pc27.dim(` ${forks.length} total`));
17256
+ console.log(pc29.bold("Registered Kit Forks") + pc29.dim(` ${forks.length} total`));
16864
17257
  console.log(hr());
16865
- for (const fork of forks) {
16866
- const label = fork.label ? pc27.bold(fork.label) + " " : "";
16867
- console.log(`
16868
- ${label}${pc27.cyan(fork.forkId)}`);
16869
- console.log(` ${pc27.dim("Kit:")} ${fork.kitId} ${pc27.dim("v" + fork.baseVersion)}`);
16870
- console.log(` ${pc27.dim("Path:")} ${fork.forkPath}`);
16871
- if (fork.lastSyncedAt) {
16872
- console.log(` ${pc27.dim("Last synced:")} ${formatDate(fork.lastSyncedAt)}`);
17258
+ console.log(renderForkTable(summaries));
17259
+ console.log("");
17260
+ console.log(hr());
17261
+ }
17262
+ function groupHealActions(plan) {
17263
+ const safeAdd = [];
17264
+ const safeUpdate = [];
17265
+ const protectedActions = [];
17266
+ const unresolved = [];
17267
+ for (const a of plan.actions) {
17268
+ if (a.actionType === "skip_user_modified") {
17269
+ protectedActions.push(a);
17270
+ continue;
17271
+ }
17272
+ if (a.needsConfirmation) {
17273
+ unresolved.push(a);
17274
+ continue;
17275
+ }
17276
+ if (a.actionType === "add_file" || a.actionType === "add_custom_skill") {
17277
+ safeAdd.push(a);
17278
+ continue;
17279
+ }
17280
+ safeUpdate.push(a);
17281
+ }
17282
+ return { safeAdd, safeUpdate, protected: protectedActions, unresolved };
17283
+ }
17284
+ function printRichHealPreview(plan, policy) {
17285
+ const g = groupHealActions(plan);
17286
+ console.log("");
17287
+ console.log(
17288
+ pc29.bold(`Heal Plan: ${plan.forkId}`) + pc29.dim(` v${plan.fromVersion} \u2192 v${plan.toVersion}`)
17289
+ );
17290
+ console.log(pc29.dim("Estimated risk: ") + severityBadge(plan.estimatedRisk));
17291
+ console.log(hr());
17292
+ if (g.safeAdd.length > 0) {
17293
+ console.log(pc29.bold(`
17294
+ SAFE ADDITIONS (${g.safeAdd.length}):`));
17295
+ for (const a of g.safeAdd) {
17296
+ console.log(` ${pc29.green("+")} ${a.targetPath} ${pc29.dim(a.description)}`);
17297
+ }
17298
+ }
17299
+ if (g.safeUpdate.length > 0) {
17300
+ console.log(pc29.bold(`
17301
+ SAFE UPDATES (${g.safeUpdate.length}):`));
17302
+ for (const a of g.safeUpdate) {
17303
+ console.log(` ${pc29.yellow("~")} ${a.targetPath} ${pc29.dim(a.description)}`);
17304
+ }
17305
+ }
17306
+ if (g.protected.length > 0 || plan.preservedPaths.length > 0) {
17307
+ const paths = /* @__PURE__ */ new Set([
17308
+ ...g.protected.map((a) => a.targetPath),
17309
+ ...plan.preservedPaths
17310
+ ]);
17311
+ console.log(pc29.bold(`
17312
+ PROTECTED (${paths.size}):`));
17313
+ for (const pth of paths) {
17314
+ const reason = policy && isUntouchable(policy, pth) ? "policy.untouchablePaths" : "user-modified";
17315
+ console.log(` ${pc29.dim("\u25CB")} ${pth} ${pc29.dim(`(${reason})`)}`);
17316
+ }
17317
+ }
17318
+ if (g.unresolved.length > 0) {
17319
+ console.log(pc29.bold(`
17320
+ UNRESOLVED \u2014 needs confirmation (${g.unresolved.length}):`));
17321
+ for (const a of g.unresolved) {
17322
+ console.log(` ${pc29.red("!")} ${a.targetPath} ${pc29.dim(a.confirmationReason ?? "policy.confirmBeforeChange")}`);
17323
+ }
17324
+ }
17325
+ console.log("");
17326
+ console.log(pc29.bold(" DECISION:"));
17327
+ const applyCount = g.safeAdd.length + g.safeUpdate.length;
17328
+ const skipCount = g.protected.length + plan.preservedPaths.length;
17329
+ console.log(` ${pc29.green(String(applyCount))} will apply \xB7 ${pc29.dim(String(skipCount) + " protected")} \xB7 ${g.unresolved.length > 0 ? pc29.red(String(g.unresolved.length) + " unresolved") : pc29.dim("0 unresolved")}`);
17330
+ console.log(hr());
17331
+ }
17332
+ function printNextStepsAfterStatus(forkId, hasDrift) {
17333
+ console.log("");
17334
+ console.log(pc29.bold(" Next steps:"));
17335
+ if (hasDrift) {
17336
+ console.log(` ${pc29.cyan("growthub kit fork heal " + forkId + " --preview")} ${pc29.dim("rich heal preview")}`);
17337
+ console.log(` ${pc29.cyan("growthub kit fork heal " + forkId)} ${pc29.dim("apply interactively")}`);
17338
+ }
17339
+ console.log(` ${pc29.cyan("growthub kit fork policy " + forkId)} ${pc29.dim("interactive policy editor")}`);
17340
+ console.log(` ${pc29.cyan("growthub kit fork history " + forkId)} ${pc29.dim("audit timeline")}`);
17341
+ console.log("");
17342
+ }
17343
+ function estimateJobProgress(job) {
17344
+ if (!job.healPlan) return null;
17345
+ const total = job.healPlan.actions.length;
17346
+ if (total === 0) return null;
17347
+ if (job.healResult) {
17348
+ const done = job.healResult.appliedCount + job.healResult.skippedCount;
17349
+ return { current: Math.min(done, total), total };
17350
+ }
17351
+ return { current: 0, total };
17352
+ }
17353
+ function renderJobTable(jobs) {
17354
+ return renderTable({
17355
+ columns: [
17356
+ {
17357
+ key: "jobId",
17358
+ label: "Job ID",
17359
+ maxWidth: 28,
17360
+ format: (v) => pc29.cyan(String(v))
17361
+ },
17362
+ {
17363
+ key: "forkId",
17364
+ label: "Fork ID",
17365
+ maxWidth: 22,
17366
+ format: (v) => pc29.dim(String(v))
17367
+ },
17368
+ {
17369
+ key: "status",
17370
+ label: "Status",
17371
+ format: (v) => jobStatusBadge(v)
17372
+ },
17373
+ {
17374
+ key: "healPlan",
17375
+ label: "Progress",
17376
+ maxWidth: 28,
17377
+ format: (_v, row) => {
17378
+ const prog = estimateJobProgress(row);
17379
+ if (!prog) {
17380
+ if (row.status === "completed") return pc29.green("\u2713 100%");
17381
+ if (row.status === "failed") return pc29.red("\u2717");
17382
+ return pc29.dim("\u2014");
17383
+ }
17384
+ return renderProgressBar(prog.current, prog.total, { width: 14, showCounts: true });
17385
+ }
17386
+ },
17387
+ {
17388
+ key: "createdAt",
17389
+ label: "Age",
17390
+ format: (_v, row) => formatRelative(row.completedAt ?? row.createdAt)
17391
+ }
17392
+ ],
17393
+ rows: jobs,
17394
+ emptyText: "No jobs found."
17395
+ });
17396
+ }
17397
+ function printJobDetail(job) {
17398
+ console.log(` ${jobStatusBadge(job.status)} ${pc29.cyan(job.jobId)} ${pc29.dim(job.forkId)}`);
17399
+ const prog = estimateJobProgress(job);
17400
+ if (prog) {
17401
+ console.log(` ${pc29.dim("Progress:")} ${renderProgressBar(prog.current, prog.total, { width: 24 })}`);
17402
+ }
17403
+ if (job.healPlan) {
17404
+ console.log(` ${pc29.dim("Plan:")} ${job.healPlan.actions.length} action(s), risk=${job.healPlan.estimatedRisk}`);
17405
+ }
17406
+ if (job.startedAt) console.log(` ${pc29.dim("Started:")} ${formatRelative(job.startedAt)} (${job.startedAt})`);
17407
+ if (job.completedAt) console.log(` ${pc29.dim("Completed:")} ${formatRelative(job.completedAt)} (${job.completedAt})`);
17408
+ if (job.error) console.log(` ${pc29.red("Error:")} ${job.error}`);
17409
+ }
17410
+ var TERMINAL_JOB_STATUSES = [
17411
+ "completed",
17412
+ "failed",
17413
+ "cancelled"
17414
+ ];
17415
+ async function watchJob(jobId, jsonMode) {
17416
+ const initial = getKitForkSyncJob(jobId);
17417
+ if (!initial) {
17418
+ console.error(pc29.red(`Job not found: ${jobId}`));
17419
+ process.exitCode = 1;
17420
+ return;
17421
+ }
17422
+ if (jsonMode) {
17423
+ const snapshot = await pollUntilTerminal(jobId);
17424
+ console.log(JSON.stringify(snapshot, null, 2));
17425
+ return;
17426
+ }
17427
+ console.log("");
17428
+ console.log(pc29.bold(`Watching job ${pc29.cyan(jobId)}`));
17429
+ console.log(hr());
17430
+ let lastStatus = null;
17431
+ let lastProgress = -1;
17432
+ while (true) {
17433
+ const job = getKitForkSyncJob(jobId);
17434
+ if (!job) {
17435
+ console.error(pc29.red(` Job disappeared: ${jobId}`));
17436
+ process.exitCode = 1;
17437
+ return;
16873
17438
  }
16874
- if (fork.customSkills && fork.customSkills.length > 0) {
16875
- console.log(` ${pc27.dim("Custom skills:")} ${fork.customSkills.length}`);
17439
+ const prog = estimateJobProgress(job);
17440
+ const progNum = prog ? Math.round(prog.current / (prog.total || 1) * 100) : -1;
17441
+ if (job.status !== lastStatus || progNum !== lastProgress) {
17442
+ printJobDetail(job);
17443
+ lastStatus = job.status;
17444
+ lastProgress = progNum;
16876
17445
  }
17446
+ if (TERMINAL_JOB_STATUSES.includes(job.status)) {
17447
+ console.log("");
17448
+ if (job.status === "failed") process.exitCode = 1;
17449
+ return;
17450
+ }
17451
+ await sleep(500);
17452
+ }
17453
+ }
17454
+ async function pollUntilTerminal(jobId) {
17455
+ while (true) {
17456
+ const job = getKitForkSyncJob(jobId);
17457
+ if (!job) throw new Error(`Job disappeared: ${jobId}`);
17458
+ if (TERMINAL_JOB_STATUSES.includes(job.status)) return job;
17459
+ await sleep(500);
17460
+ }
17461
+ }
17462
+ function sleep(ms) {
17463
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
17464
+ }
17465
+ function tailJobTrace(jobId, limit, jsonMode) {
17466
+ const job = getKitForkSyncJob(jobId);
17467
+ if (!job) {
17468
+ console.error(pc29.red(`Job not found: ${jobId}`));
17469
+ process.exitCode = 1;
17470
+ return;
17471
+ }
17472
+ const reg = listKitForkRegistrations().find((f) => f.forkId === job.forkId);
17473
+ if (!reg) {
17474
+ console.error(pc29.red(`Fork not registered for job ${jobId}: ${job.forkId}`));
17475
+ process.exitCode = 1;
17476
+ return;
17477
+ }
17478
+ const events = readKitForkTrace(reg.forkPath).filter((e) => e.jobId === jobId).slice(-Math.max(1, limit));
17479
+ if (jsonMode) {
17480
+ console.log(JSON.stringify(events, null, 2));
17481
+ return;
16877
17482
  }
16878
17483
  console.log("");
17484
+ console.log(pc29.bold(`Trace tail: ${pc29.cyan(jobId)}`) + pc29.dim(` ${events.length} event(s)`));
16879
17485
  console.log(hr());
17486
+ if (events.length === 0) {
17487
+ console.log(pc29.dim(` No trace events recorded for this job yet.`));
17488
+ console.log("");
17489
+ return;
17490
+ }
17491
+ for (const e of events) {
17492
+ const ts = e.timestamp.replace("T", " ").replace(/\..+Z$/, "Z");
17493
+ console.log(` ${pc29.dim(ts)} ${pc29.cyan("[" + e.type + "]")} ${e.summary ?? ""}`);
17494
+ }
17495
+ console.log("");
16880
17496
  }
16881
17497
  async function runKitForkHub(opts = {}) {
16882
17498
  printPaperclipCliBanner();
16883
- p18.intro(pc27.bold("Kit Fork Sync Agent"));
17499
+ p18.intro(pc29.bold("Kit Fork Sync Agent"));
16884
17500
  while (true) {
16885
17501
  const choice = await p18.select({
16886
17502
  message: "What do you want to do?",
@@ -16958,7 +17574,7 @@ async function runRegisterFlow() {
16958
17574
  options: [
16959
17575
  ...kits.map((k) => ({
16960
17576
  value: k.id,
16961
- label: k.id + " " + pc27.dim("v" + k.version),
17577
+ label: k.id + " " + pc29.dim("v" + k.version),
16962
17578
  hint: k.description
16963
17579
  })),
16964
17580
  { value: "__cancel", label: "\u2190 Cancel" }
@@ -16986,19 +17602,19 @@ async function runRegisterFlow() {
16986
17602
  baseVersion: kitVersion,
16987
17603
  label: labelInput.trim() || void 0
16988
17604
  });
16989
- spinner12.stop(pc27.green("Fork registered."));
17605
+ spinner12.stop(pc29.green("Fork registered."));
16990
17606
  p18.note(
16991
17607
  [
16992
- `Fork ID: ${pc27.cyan(reg.forkId)}`,
17608
+ `Fork ID: ${pc29.cyan(reg.forkId)}`,
16993
17609
  `Kit: ${reg.kitId} v${reg.baseVersion}`,
16994
17610
  `Path: ${reg.forkPath}`,
16995
17611
  "",
16996
- `Next: ${pc27.cyan("growthub kit fork status " + reg.forkId)}`
17612
+ `Next: ${pc29.cyan("growthub kit fork status " + reg.forkId)}`
16997
17613
  ].join("\n"),
16998
17614
  "Registration complete"
16999
17615
  );
17000
17616
  } catch (err) {
17001
- spinner12.stop(pc27.red("Registration failed."));
17617
+ spinner12.stop(pc29.red("Registration failed."));
17002
17618
  p18.log.error(err.message);
17003
17619
  }
17004
17620
  }
@@ -17016,7 +17632,7 @@ async function runStatusFlow() {
17016
17632
  options: [
17017
17633
  ...forks.map((f) => ({
17018
17634
  value: f.forkId,
17019
- label: (f.label ?? f.forkId) + " " + pc27.dim("v" + f.baseVersion),
17635
+ label: (f.label ?? f.forkId) + " " + pc29.dim("v" + f.baseVersion),
17020
17636
  hint: f.kitId
17021
17637
  })),
17022
17638
  { value: "__back", label: "\u2190 Back" }
@@ -17032,10 +17648,10 @@ async function runStatusFlow() {
17032
17648
  spinner12.start("Detecting drift...");
17033
17649
  try {
17034
17650
  const report = detectKitForkDrift(reg);
17035
- spinner12.stop(pc27.green("Analysis complete."));
17651
+ spinner12.stop(pc29.green("Analysis complete."));
17036
17652
  printDriftReport(report);
17037
17653
  } catch (err) {
17038
- spinner12.stop(pc27.red("Drift detection failed."));
17654
+ spinner12.stop(pc29.red("Drift detection failed."));
17039
17655
  p18.log.error(err.message);
17040
17656
  }
17041
17657
  }
@@ -17050,7 +17666,7 @@ async function runHealFlow() {
17050
17666
  options: [
17051
17667
  ...forks.map((f) => ({
17052
17668
  value: f.forkId,
17053
- label: (f.label ?? f.forkId) + " " + pc27.dim("v" + f.baseVersion),
17669
+ label: (f.label ?? f.forkId) + " " + pc29.dim("v" + f.baseVersion),
17054
17670
  hint: f.kitId
17055
17671
  })),
17056
17672
  { value: "__back", label: "\u2190 Back" }
@@ -17069,7 +17685,7 @@ async function runHealFlow() {
17069
17685
  driftReport = detectKitForkDrift(reg);
17070
17686
  driftSpinner.stop("Drift analysis complete.");
17071
17687
  } catch (err) {
17072
- driftSpinner.stop(pc27.red("Drift detection failed."));
17688
+ driftSpinner.stop(pc29.red("Drift detection failed."));
17073
17689
  p18.log.error(err.message);
17074
17690
  return;
17075
17691
  }
@@ -17098,9 +17714,9 @@ async function runHealFlow() {
17098
17714
  const jobId = dispatchKitForkSyncJobBackground(reg.forkId, reg.kitId);
17099
17715
  p18.note(
17100
17716
  [
17101
- `Job ID: ${pc27.cyan(jobId)}`,
17717
+ `Job ID: ${pc29.cyan(jobId)}`,
17102
17718
  "",
17103
- `Check: ${pc27.cyan("growthub kit fork jobs")}`
17719
+ `Check: ${pc29.cyan("growthub kit fork jobs")}`
17104
17720
  ].join("\n"),
17105
17721
  "Background sync dispatched"
17106
17722
  );
@@ -17116,16 +17732,16 @@ async function runHealFlow() {
17116
17732
  }
17117
17733
  });
17118
17734
  healSpinner.stop(
17119
- job.status === "completed" ? pc27.green(isDryRun ? "Dry run complete." : "Heal complete.") : pc27.red("Heal encountered errors.")
17735
+ job.status === "completed" ? pc29.green(isDryRun ? "Dry run complete." : "Heal complete.") : pc29.red("Heal encountered errors.")
17120
17736
  );
17121
17737
  if (job.healResult) {
17122
17738
  const r = job.healResult;
17123
17739
  console.log("");
17124
- console.log(pc27.bold("Result:"));
17125
- console.log(` ${pc27.green("Applied:")} ${r.appliedCount} ${pc27.dim("Skipped:")} ${r.skippedCount} ${r.errorCount > 0 ? pc27.red("Errors: " + r.errorCount) : pc27.dim("Errors: 0")}`);
17740
+ console.log(pc29.bold("Result:"));
17741
+ console.log(` ${pc29.green("Applied:")} ${r.appliedCount} ${pc29.dim("Skipped:")} ${r.skippedCount} ${r.errorCount > 0 ? pc29.red("Errors: " + r.errorCount) : pc29.dim("Errors: 0")}`);
17126
17742
  for (const ar of r.actionResults) {
17127
17743
  if (ar.status === "error") {
17128
- console.log(` ${pc27.red(" \u2717")} ${ar.action.targetPath}: ${ar.detail}`);
17744
+ console.log(` ${pc29.red(" \u2717")} ${ar.action.targetPath}: ${ar.detail}`);
17129
17745
  }
17130
17746
  }
17131
17747
  console.log("");
@@ -17142,12 +17758,12 @@ async function runJobsFlow() {
17142
17758
  return;
17143
17759
  }
17144
17760
  console.log("");
17145
- console.log(pc27.bold("Kit Fork Sync Jobs") + pc27.dim(` ${jobs.length} total`));
17761
+ console.log(pc29.bold("Kit Fork Sync Jobs") + pc29.dim(` ${jobs.length} total`));
17146
17762
  console.log(hr());
17147
17763
  for (const job of jobs.slice(-10).reverse()) {
17148
- console.log(` ${jobStatusBadge(job.status)} ${pc27.cyan(job.jobId)} ${pc27.dim(job.forkId)}`);
17149
- if (job.completedAt) console.log(` ${pc27.dim("Completed:")} ${formatDate(job.completedAt)}`);
17150
- if (job.error) console.log(` ${pc27.red("Error:")} ${job.error}`);
17764
+ console.log(` ${jobStatusBadge(job.status)} ${pc29.cyan(job.jobId)} ${pc29.dim(job.forkId)}`);
17765
+ if (job.completedAt) console.log(` ${pc29.dim("Completed:")} ${formatDate(job.completedAt)}`);
17766
+ if (job.error) console.log(` ${pc29.red("Error:")} ${job.error}`);
17151
17767
  }
17152
17768
  console.log("");
17153
17769
  console.log(hr());
@@ -17184,15 +17800,44 @@ async function runJobsFlow() {
17184
17800
  function registerKitForkSubcommands(kitCommand) {
17185
17801
  const forkCmd = kitCommand.command("fork").description("Fork Sync Agent \u2014 register, track, and self-heal forked worker kits").addHelpText("after", `
17186
17802
  Examples:
17187
- $ growthub kit fork # interactive hub
17188
- $ growthub kit fork register ./my-kit-fork # register a fork
17189
- $ growthub kit fork list # list all forks
17190
- $ growthub kit fork status <fork-id> # check drift
17191
- $ growthub kit fork heal <fork-id> # heal a fork
17192
- $ growthub kit fork heal <fork-id> --dry-run # preview only
17803
+ # Interactive hub
17804
+ $ growthub kit fork # start interactive fork menu
17805
+
17806
+ # List all forks (with drift + policy at a glance)
17807
+ $ growthub kit fork list # beautiful table
17808
+ $ growthub kit fork list --json # machine-readable
17809
+ $ growthub kit fork list --filter status=drift-major
17810
+ $ growthub kit fork list --sort-by last-heal
17811
+
17812
+ # Status with policy eval + heal plan preview + next steps
17813
+ $ growthub kit fork status <fork-id>
17814
+ $ growthub kit fork status <fork-id> --policy-only
17815
+ $ growthub kit fork status <fork-id> --no-upstream-check
17816
+
17817
+ # Edit policy (interactive) or set fields non-interactively
17818
+ $ growthub kit fork policy <fork-id> --edit
17819
+ $ growthub kit fork policy <fork-id> --set autoApprove=all --set untouchablePaths+=skills/
17820
+
17821
+ # Heal (preview, apply, or background)
17822
+ $ growthub kit fork heal <fork-id> --preview # rich grouped preview + decision prompt
17823
+ $ growthub kit fork heal <fork-id> # apply (foreground)
17193
17824
  $ growthub kit fork heal <fork-id> --background
17194
- $ growthub kit fork jobs # view job queue
17195
- $ growthub kit fork deregister <fork-id> # remove registration
17825
+ $ growthub kit fork heal <fork-id> --dry-run
17826
+
17827
+ # Monitor background jobs
17828
+ $ growthub kit fork jobs # table view with progress
17829
+ $ growthub kit fork jobs --watch <job-id> # live progress until terminal
17830
+ $ growthub kit fork jobs --tail <job-id> # trace events for a job
17831
+ $ growthub kit fork jobs --filter status=running
17832
+
17833
+ # Audit history
17834
+ $ growthub kit fork history <fork-id> # timeline
17835
+ $ growthub kit fork history <fork-id> --csv > audit.csv
17836
+ $ growthub kit fork history <fork-id> --since 2024-01-01
17837
+
17838
+ # Manage forks
17839
+ $ growthub kit fork register ./my-fork # register existing fork
17840
+ $ growthub kit fork deregister <fork-id>
17196
17841
  `);
17197
17842
  forkCmd.action(async () => {
17198
17843
  await runKitForkHub();
@@ -17204,13 +17849,13 @@ function registerKitForkCommands(program2) {
17204
17849
  const forkSync = program2.command("fork-sync").description("Kit Fork Sync Agent \u2014 alias for `growthub kit fork`").addHelpText("after", `
17205
17850
  Examples:
17206
17851
  $ growthub fork-sync # interactive hub
17207
- $ growthub fork-sync register ./my-fork
17208
- $ growthub fork-sync list
17209
- $ growthub fork-sync status <fork-id>
17210
- $ growthub fork-sync heal <fork-id>
17211
- $ growthub fork-sync heal <fork-id> --dry-run
17852
+ $ growthub fork-sync list # beautiful table of all forks
17853
+ $ growthub fork-sync status <fork-id> # drift + policy + next steps
17854
+ $ growthub fork-sync policy <fork-id> --edit # interactive policy editor
17855
+ $ growthub fork-sync heal <fork-id> --preview # rich heal preview
17212
17856
  $ growthub fork-sync heal <fork-id> --background
17213
- $ growthub fork-sync jobs
17857
+ $ growthub fork-sync jobs --watch <job-id> # live job progress
17858
+ $ growthub fork-sync history <fork-id> # audit timeline
17214
17859
  `);
17215
17860
  forkSync.action(async () => {
17216
17861
  await runKitForkHub();
@@ -17235,14 +17880,14 @@ function addForkSubcommands(parentCmd) {
17235
17880
  }
17236
17881
  }
17237
17882
  if (!kitId) {
17238
- console.error(pc27.yellow("Could not auto-detect kit ID from kit.json. Use --kit <kit-id>."));
17239
- console.error(pc27.dim("Available: " + kits.map((k) => k.id).join(", ")));
17883
+ console.error(pc29.yellow("Could not auto-detect kit ID from kit.json. Use --kit <kit-id>."));
17884
+ console.error(pc29.dim("Available: " + kits.map((k) => k.id).join(", ")));
17240
17885
  process.exitCode = 1;
17241
17886
  return;
17242
17887
  }
17243
17888
  const kit = kits.find((k) => k.id === kitId);
17244
17889
  if (!kit) {
17245
- console.error(pc27.red(`Unknown kit: ${kitId}`));
17890
+ console.error(pc29.red(`Unknown kit: ${kitId}`));
17246
17891
  process.exitCode = 1;
17247
17892
  return;
17248
17893
  }
@@ -17253,111 +17898,316 @@ function addForkSubcommands(parentCmd) {
17253
17898
  baseVersion: kit.version,
17254
17899
  label: opts.label
17255
17900
  });
17256
- console.log(pc27.green("Fork registered:"), reg.forkId);
17257
- console.log(pc27.dim("Kit: "), reg.kitId, "v" + reg.baseVersion);
17258
- console.log(pc27.dim("Path: "), reg.forkPath);
17901
+ console.log(pc29.green("Fork registered:"), reg.forkId);
17902
+ console.log(pc29.dim("Kit: "), reg.kitId, "v" + reg.baseVersion);
17903
+ console.log(pc29.dim("Path: "), reg.forkPath);
17259
17904
  } catch (err) {
17260
- console.error(pc27.red(err.message));
17905
+ console.error(pc29.red(err.message));
17261
17906
  process.exitCode = 1;
17262
17907
  }
17263
17908
  });
17264
- parentCmd.command("list").description("List all registered forks").option("--kit <kit-id>", "Filter by kit ID").option("--json", "Output raw JSON").action((opts) => {
17265
- const forks = listKitForkRegistrations(opts.kit);
17909
+ parentCmd.command("list").description("List all registered forks with rich drift + policy summary").option("--kit <kit-id>", "Filter by kit ID").option("--filter <expr>", "Filter expression, e.g. status=synced, status=drift-major, kit=<id>").option("--sort-by <key>", "Sort by: id | kit | status | last-heal (default: id)").option("--no-upstream-check", "Skip upstream drift detection (faster, shows cached status only)").option("--json", "Output raw JSON").action((opts) => {
17910
+ const raw = listKitForkRegistrations(opts.kit);
17911
+ const skipUpstream = opts.upstreamCheck === false;
17912
+ let summaries = raw.map((f) => summarizeFork(f, { skipUpstreamCheck: skipUpstream }));
17913
+ if (opts.filter) {
17914
+ const [key, value] = opts.filter.split("=").map((s) => s.trim());
17915
+ if (!key || !value) {
17916
+ console.error(pc29.red(`Invalid --filter expression: ${opts.filter}`));
17917
+ console.error(pc29.dim("Use --filter status=<synced|drift-minor|drift-warn|drift-major|unknown> or kit=<id>"));
17918
+ process.exitCode = 1;
17919
+ return;
17920
+ }
17921
+ summaries = summaries.filter((s) => {
17922
+ if (key === "kit") return s.kitId === value;
17923
+ if (key === "status") {
17924
+ const mapping = {
17925
+ synced: "none",
17926
+ "drift-minor": "info",
17927
+ "drift-warn": "warning",
17928
+ "drift-major": "critical",
17929
+ unknown: "unknown"
17930
+ };
17931
+ const want = mapping[value] ?? value;
17932
+ return s.severity === want;
17933
+ }
17934
+ return true;
17935
+ });
17936
+ }
17937
+ const sortKey = opts.sortBy ?? "id";
17938
+ summaries.sort((a, b) => {
17939
+ if (sortKey === "kit") return a.kitId.localeCompare(b.kitId);
17940
+ if (sortKey === "status") {
17941
+ const order = ["none", "info", "warning", "critical", "unknown"];
17942
+ return order.indexOf(a.severity) - order.indexOf(b.severity);
17943
+ }
17944
+ if (sortKey === "last-heal") {
17945
+ return (b.lastHealAt ?? "").localeCompare(a.lastHealAt ?? "");
17946
+ }
17947
+ return a.forkId.localeCompare(b.forkId);
17948
+ });
17266
17949
  if (opts.json) {
17267
- console.log(JSON.stringify(forks, null, 2));
17950
+ console.log(JSON.stringify(summaries, null, 2));
17951
+ return;
17952
+ }
17953
+ if (summaries.length === 0) {
17954
+ console.log(pc29.dim(" No forks match the given filters."));
17268
17955
  return;
17269
17956
  }
17270
- printForkList(forks);
17957
+ console.log("");
17958
+ console.log(pc29.bold("Registered Kit Forks") + pc29.dim(` ${summaries.length} total`));
17959
+ console.log(hr());
17960
+ console.log(renderForkTable(summaries));
17961
+ console.log("");
17962
+ console.log(hr());
17271
17963
  });
17272
- parentCmd.command("status").description("Detect drift between a fork and the latest upstream kit").argument("<fork-id>", "Fork ID from list").option("--json", "Output raw JSON drift report").action(async (forkId, opts) => {
17964
+ parentCmd.command("status").description("Detect drift + show policy evaluation + heal plan preview + next steps").argument("<fork-id>", "Fork ID from list").option("--policy-only", "Show only the fork's policy (skip drift detection)").option("--no-upstream-check", "Use cached registration fields; do not query the upstream bundled kit").option("--json", "Output raw JSON drift report").action(async (forkId, opts) => {
17273
17965
  const reg = listKitForkRegistrations().find((f) => f.forkId === forkId);
17274
17966
  if (!reg) {
17275
- console.error(pc27.red(`Fork not found: ${forkId}`));
17967
+ console.error(pc29.red(`Fork not found: ${forkId}`));
17968
+ console.error(pc29.dim("Hint: run `growthub kit fork list` to see registered forks."));
17276
17969
  process.exitCode = 1;
17277
17970
  return;
17278
17971
  }
17972
+ const policy = readKitForkPolicy(reg.forkPath);
17973
+ if (opts.policyOnly) {
17974
+ if (opts.json) {
17975
+ console.log(JSON.stringify(policy, null, 2));
17976
+ return;
17977
+ }
17978
+ console.log("");
17979
+ console.log(pc29.bold(`Policy: ${reg.forkId}`));
17980
+ console.log(hr());
17981
+ console.log(` ${pc29.dim("autoApprove:")} ${policy.autoApprove}`);
17982
+ console.log(` ${pc29.dim("autoApproveDepUpdates:")} ${policy.autoApproveDepUpdates}`);
17983
+ console.log(` ${pc29.dim("remoteSyncMode:")} ${policy.remoteSyncMode}`);
17984
+ console.log(` ${pc29.dim("interactiveConflicts:")} ${policy.interactiveConflicts}`);
17985
+ console.log(` ${pc29.dim("untouchablePaths:")} [${policy.untouchablePaths.join(", ")}]`);
17986
+ console.log(` ${pc29.dim("confirmBeforeChange:")} [${policy.confirmBeforeChange.join(", ")}]`);
17987
+ console.log(` ${pc29.dim("allowedScripts:")} [${policy.allowedScripts.join(", ")}]`);
17988
+ console.log("");
17989
+ return;
17990
+ }
17991
+ if (opts.upstreamCheck === false) {
17992
+ if (opts.json) {
17993
+ console.log(JSON.stringify({ forkId: reg.forkId, kitId: reg.kitId, forkVersion: reg.baseVersion, policy }, null, 2));
17994
+ return;
17995
+ }
17996
+ console.log("");
17997
+ console.log(pc29.bold(`Fork: ${reg.forkId}`) + " " + pc29.dim("(no upstream check)"));
17998
+ console.log(pc29.dim(`Kit: ${reg.kitId} v${reg.baseVersion}`));
17999
+ console.log(hr());
18000
+ console.log(` ${pc29.dim("Path:")} ${reg.forkPath}`);
18001
+ console.log(` ${pc29.dim("Policy:")} autoApprove=${policy.autoApprove}, remoteSyncMode=${policy.remoteSyncMode}`);
18002
+ if (policy.untouchablePaths.length > 0) {
18003
+ console.log(` ${pc29.dim("Protected paths:")} ${policy.untouchablePaths.join(", ")}`);
18004
+ }
18005
+ console.log("");
18006
+ console.log(hr());
18007
+ printNextStepsAfterStatus(reg.forkId, true);
18008
+ return;
18009
+ }
17279
18010
  try {
17280
18011
  const report = detectKitForkDrift(reg);
18012
+ appendKitForkTraceEvent(reg.forkPath, {
18013
+ forkId: reg.forkId,
18014
+ kitId: reg.kitId,
18015
+ type: "status_ran",
18016
+ summary: `status inspected \u2014 severity=${report.overallSeverity}`
18017
+ });
17281
18018
  if (opts.json) {
17282
- console.log(JSON.stringify(report, null, 2));
18019
+ const plan = buildKitForkHealPlan(report, { policy });
18020
+ console.log(JSON.stringify({ drift: report, plan, policy }, null, 2));
17283
18021
  return;
17284
18022
  }
17285
18023
  printDriftReport(report);
18024
+ const hasDrift = report.hasUpstreamUpdate || report.overallSeverity !== "none";
18025
+ if (hasDrift) {
18026
+ const plan = buildKitForkHealPlan(report, { policy });
18027
+ printRichHealPreview(plan, policy);
18028
+ }
18029
+ printNextStepsAfterStatus(reg.forkId, hasDrift);
17286
18030
  } catch (err) {
17287
- console.error(pc27.red(err.message));
18031
+ console.error(pc29.red(err.message));
17288
18032
  process.exitCode = 1;
17289
18033
  }
17290
18034
  });
17291
- parentCmd.command("heal").description("Apply a safe non-destructive heal to bring a fork up to date").argument("<fork-id>", "Fork ID from list").option("--dry-run", "Preview the plan without writing any files").option("--background", "Dispatch as an async background job").option("--skip <paths>", "Comma-separated relative paths to skip").option("--json", "Output heal plan as JSON (implies --dry-run)").action(async (forkId, opts) => {
18035
+ parentCmd.command("heal").description("Apply a safe non-destructive heal to bring a fork up to date").argument("<fork-id>", "Fork ID from list").option("--preview", "Rich grouped preview (safe additions / updates / protected / unresolved); does not write").option("--dry-run", "Preview the plan without writing any files").option("--background", "Dispatch as an async background job").option("--skip <paths>", "Comma-separated relative paths to skip").option("--json", "Output heal plan as JSON (implies --dry-run)").action(async (forkId, opts) => {
17292
18036
  const reg = listKitForkRegistrations().find((f) => f.forkId === forkId);
17293
18037
  if (!reg) {
17294
- console.error(pc27.red(`Fork not found: ${forkId}`));
18038
+ console.error(pc29.red(`Fork not found: ${forkId}`));
18039
+ console.error(pc29.dim("Hint: run `growthub kit fork list` to see registered forks."));
17295
18040
  process.exitCode = 1;
17296
18041
  return;
17297
18042
  }
18043
+ const policy = readKitForkPolicy(reg.forkPath);
17298
18044
  if (opts.json) {
17299
18045
  const report = detectKitForkDrift(reg);
17300
- const plan = buildKitForkHealPlan(report);
18046
+ const plan = buildKitForkHealPlan(report, { policy });
17301
18047
  console.log(JSON.stringify(plan, null, 2));
17302
18048
  return;
17303
18049
  }
18050
+ if (opts.preview) {
18051
+ const report = detectKitForkDrift(reg);
18052
+ const plan = buildKitForkHealPlan(report, { policy });
18053
+ appendKitForkTraceEvent(reg.forkPath, {
18054
+ forkId: reg.forkId,
18055
+ kitId: reg.kitId,
18056
+ type: "heal_proposed",
18057
+ summary: `preview requested \u2014 ${plan.actions.length} action(s), risk=${plan.estimatedRisk}`,
18058
+ detail: { mode: "preview" }
18059
+ });
18060
+ printRichHealPreview(plan, policy);
18061
+ if (plan.actions.length === 0) {
18062
+ console.log(pc29.dim(" No actions needed. Fork is structurally clean."));
18063
+ return;
18064
+ }
18065
+ const decision = await p18.select({
18066
+ message: "Apply this plan?",
18067
+ options: [
18068
+ { value: "apply", label: "\u25B6 Yes, apply now", hint: "Run synchronously in this terminal" },
18069
+ { value: "background", label: "\u2699\uFE0F Run in background", hint: "Dispatch as an async job" },
18070
+ { value: "cancel", label: "\u2190 No, cancel" }
18071
+ ]
18072
+ });
18073
+ if (p18.isCancel(decision) || decision === "cancel") {
18074
+ console.log(pc29.dim(" Cancelled. Plan was not applied."));
18075
+ console.log(pc29.dim(` Next: ${pc29.cyan("growthub kit fork policy " + reg.forkId)} or ${pc29.cyan("growthub kit fork heal " + reg.forkId)}`));
18076
+ return;
18077
+ }
18078
+ if (decision === "background") {
18079
+ const jobId = dispatchKitForkSyncJobBackground(reg.forkId, reg.kitId, {
18080
+ skipFiles: opts.skip?.split(",").map((s) => s.trim())
18081
+ });
18082
+ console.log("");
18083
+ console.log(pc29.green(" \u2713 Background heal dispatched"));
18084
+ console.log(` Job ID: ${pc29.cyan(jobId)}`);
18085
+ console.log(` Watch: ${pc29.cyan("growthub kit fork jobs --watch " + jobId)}`);
18086
+ return;
18087
+ }
18088
+ opts.dryRun = false;
18089
+ }
17304
18090
  if (opts.background) {
17305
18091
  const jobId = dispatchKitForkSyncJobBackground(reg.forkId, reg.kitId, {
17306
18092
  dryRun: opts.dryRun,
17307
18093
  skipFiles: opts.skip?.split(",").map((s) => s.trim())
17308
18094
  });
17309
- console.log(pc27.green("Background job dispatched:"), jobId);
17310
- console.log(pc27.dim("Check status: growthub fork-sync jobs (or growthub kit fork jobs)"));
18095
+ console.log(pc29.green("Background job dispatched:"), jobId);
18096
+ console.log(pc29.dim(` Watch: growthub kit fork jobs --watch ${jobId}`));
18097
+ console.log(pc29.dim(` List: growthub kit fork jobs`));
17311
18098
  return;
17312
18099
  }
17313
18100
  const job = await runKitForkSyncJob(reg.forkId, reg.kitId, {
17314
18101
  dryRun: opts.dryRun,
17315
18102
  skipFiles: opts.skip?.split(",").map((s) => s.trim()),
17316
- onProgress: (step) => process.stderr.write(pc27.dim(step) + "\n")
18103
+ onProgress: (step) => process.stderr.write(pc29.dim(step) + "\n")
17317
18104
  });
17318
18105
  const r = job.healResult;
17319
18106
  if (r) {
17320
- console.log(pc27.bold("Heal result:"));
17321
- console.log(` Applied: ${r.appliedCount} Skipped: ${r.skippedCount} Errors: ${r.errorCount}`);
18107
+ console.log(pc29.bold("Heal result:"));
18108
+ console.log(` ${pc29.green("Applied:")} ${r.appliedCount} ${pc29.dim("Skipped:")} ${r.skippedCount} ${r.errorCount > 0 ? pc29.red("Errors: " + r.errorCount) : pc29.dim("Errors: 0")}`);
17322
18109
  }
17323
18110
  if (job.status === "failed") {
17324
- console.error(pc27.red("Heal failed: " + (job.error ?? "unknown error")));
18111
+ console.error(pc29.red("Heal failed: " + (job.error ?? "unknown error")));
18112
+ console.error(pc29.dim(` Review: growthub kit fork history ${reg.forkId}`));
17325
18113
  process.exitCode = 1;
17326
18114
  }
17327
18115
  });
17328
- parentCmd.command("jobs").description("List background fork-sync jobs").option("--fork <fork-id>", "Filter by fork ID").option("--status <status>", "Filter by status").option("--json", "Output raw JSON").action((opts) => {
18116
+ parentCmd.command("jobs").description("List background fork-sync jobs, watch live progress, or tail a job's trace").option("--fork <fork-id>", "Filter by fork ID").option("--status <status>", "Filter by status (pending | running | completed | failed | cancelled | awaiting_confirmation)").option("--filter <expr>", "Filter expression, e.g. status=running").option("--watch <job-id>", "Poll the given job and print live progress until terminal").option("--tail <job-id>", "Print trace events from the fork of the given job (default 50)").option("--limit <n>", "Limit entries when using --tail (default 50)", (v) => parseInt(v, 10)).option("--json", "Output raw JSON").action(async (opts) => {
18117
+ if (opts.watch) {
18118
+ await watchJob(opts.watch, Boolean(opts.json));
18119
+ return;
18120
+ }
18121
+ if (opts.tail) {
18122
+ tailJobTrace(opts.tail, opts.limit ?? 50, Boolean(opts.json));
18123
+ return;
18124
+ }
18125
+ let effectiveStatus = opts.status;
18126
+ if (!effectiveStatus && opts.filter) {
18127
+ const [key, value] = opts.filter.split("=").map((s) => s.trim());
18128
+ if (key === "status" && value) effectiveStatus = value;
18129
+ }
17329
18130
  const jobs = listKitForkSyncJobs({
17330
18131
  forkId: opts.fork,
17331
- status: opts.status
18132
+ status: effectiveStatus
17332
18133
  });
17333
18134
  if (opts.json) {
17334
18135
  console.log(JSON.stringify(jobs, null, 2));
17335
18136
  return;
17336
18137
  }
17337
18138
  if (jobs.length === 0) {
17338
- console.log(pc27.dim("No jobs found."));
18139
+ console.log(pc29.dim(" No jobs found."));
17339
18140
  return;
17340
18141
  }
17341
18142
  console.log("");
17342
- console.log(pc27.bold("Kit Fork Sync Jobs") + pc27.dim(` ${jobs.length} total`));
18143
+ console.log(pc29.bold("Kit Fork Sync Jobs") + pc29.dim(` ${jobs.length} total`));
17343
18144
  console.log(hr());
17344
- for (const job of jobs) {
17345
- console.log(` ${jobStatusBadge(job.status)} ${pc27.cyan(job.jobId)} ${pc27.dim(job.forkId)}`);
17346
- if (job.completedAt) console.log(` ${pc27.dim("Completed:")} ${formatDate(job.completedAt)}`);
17347
- if (job.error) console.log(` ${pc27.red("Error:")} ${job.error}`);
18145
+ console.log(renderJobTable(jobs));
18146
+ console.log("");
18147
+ console.log(hr());
18148
+ console.log(pc29.dim(" Live progress: growthub kit fork jobs --watch <job-id>"));
18149
+ console.log(pc29.dim(" Trace events: growthub kit fork jobs --tail <job-id>"));
18150
+ console.log("");
18151
+ });
18152
+ parentCmd.command("history").description("Export fork operation history from trace.jsonl").argument("<fork-id>", "Fork ID from list").option("--since <iso>", "ISO-8601 start date (inclusive)").option("--until <iso>", "ISO-8601 end date (inclusive)").option("--event-type <type>", "Filter by event type (e.g. heal_applied, policy_updated)").option("--limit <n>", "Return at most N events (applied after filters)", (v) => parseInt(v, 10)).option("--json", "Emit machine-readable JSON").option("--csv", "Emit CSV for compliance tools").action((forkId, opts) => {
18153
+ const reg = listKitForkRegistrations().find((f) => f.forkId === forkId);
18154
+ if (!reg) {
18155
+ console.error(pc29.red(`Fork not found: ${forkId}`));
18156
+ console.error(pc29.dim("Hint: run `growthub kit fork list` to see registered forks."));
18157
+ process.exitCode = 1;
18158
+ return;
18159
+ }
18160
+ const all = readKitForkTrace(reg.forkPath);
18161
+ const sinceMs = opts.since ? new Date(opts.since).getTime() : void 0;
18162
+ const untilMs = opts.until ? new Date(opts.until).getTime() : void 0;
18163
+ let events = all.filter((e) => {
18164
+ const ts = new Date(e.timestamp).getTime();
18165
+ if (sinceMs !== void 0 && ts < sinceMs) return false;
18166
+ if (untilMs !== void 0 && ts > untilMs) return false;
18167
+ if (opts.eventType && e.type !== opts.eventType) return false;
18168
+ return true;
18169
+ });
18170
+ if (opts.limit && opts.limit > 0) {
18171
+ events = events.slice(-opts.limit);
18172
+ }
18173
+ if (opts.json) {
18174
+ console.log(JSON.stringify(events, null, 2));
18175
+ return;
18176
+ }
18177
+ if (opts.csv) {
18178
+ console.log("timestamp,forkId,kitId,jobId,type,summary");
18179
+ for (const e of events) {
18180
+ const summary = (e.summary ?? "").replace(/"/g, '""');
18181
+ console.log(`${e.timestamp},${e.forkId},${e.kitId},${e.jobId ?? ""},${e.type},"${summary}"`);
18182
+ }
18183
+ return;
18184
+ }
18185
+ console.log("");
18186
+ console.log(pc29.bold(`Fork History: ${reg.forkId}`) + pc29.dim(` ${events.length} event(s)`));
18187
+ console.log(hr());
18188
+ if (events.length === 0) {
18189
+ console.log(pc29.dim(" No matching events."));
18190
+ console.log("");
18191
+ return;
17348
18192
  }
18193
+ for (const e of events) {
18194
+ const ts = e.timestamp.replace("T", " ").replace(/\..+Z$/, "Z");
18195
+ console.log(` ${pc29.dim(ts)} ${pc29.cyan("[" + e.type + "]")} ${e.summary ?? ""}`);
18196
+ }
18197
+ console.log("");
18198
+ console.log(hr());
17349
18199
  console.log("");
17350
18200
  });
17351
18201
  parentCmd.command("deregister").description("Remove a fork registration (does not delete your fork directory)").argument("<fork-id>", "Fork ID to deregister").action(async (forkId) => {
17352
18202
  const allForks = listKitForkRegistrations();
17353
18203
  const reg = allForks.find((f) => f.forkId === forkId);
17354
18204
  if (!reg) {
17355
- console.error(pc27.red(`Fork not found: ${forkId}`));
18205
+ console.error(pc29.red(`Fork not found: ${forkId}`));
17356
18206
  process.exitCode = 1;
17357
18207
  return;
17358
18208
  }
17359
18209
  const confirmed = await p18.confirm({
17360
- message: `Remove registration for ${pc27.cyan(forkId)}? (Your fork directory will not be touched)`,
18210
+ message: `Remove registration for ${pc29.cyan(forkId)}? (Your fork directory will not be touched)`,
17361
18211
  initialValue: false
17362
18212
  });
17363
18213
  if (p18.isCancel(confirmed) || !confirmed) {
@@ -17366,9 +18216,9 @@ function addForkSubcommands(parentCmd) {
17366
18216
  }
17367
18217
  const ok = deregisterKitFork(reg.kitId, forkId);
17368
18218
  if (ok) {
17369
- console.log(pc27.green("Fork deregistered:"), forkId);
18219
+ console.log(pc29.green("Fork deregistered:"), forkId);
17370
18220
  } else {
17371
- console.error(pc27.red("Deregistration failed."));
18221
+ console.error(pc29.red("Deregistration failed."));
17372
18222
  process.exitCode = 1;
17373
18223
  }
17374
18224
  });
@@ -17376,18 +18226,18 @@ function addForkSubcommands(parentCmd) {
17376
18226
 
17377
18227
  // src/commands/kit.ts
17378
18228
  var TYPE_CONFIG = {
17379
- studio: { color: pc28.cyan, emoji: "\u{1F6E0}\uFE0F", label: "Custom Workspaces" },
17380
- specialized_agents: { color: pc28.magenta, emoji: "\u{1F9E0}", label: "Specialized Agents" },
17381
- ops: { color: pc28.yellow, emoji: "\u2699\uFE0F ", label: "Ops" }
18229
+ studio: { color: pc30.cyan, emoji: "\u{1F6E0}\uFE0F", label: "Custom Workspaces" },
18230
+ specialized_agents: { color: pc30.magenta, emoji: "\u{1F9E0}", label: "Specialized Agents" },
18231
+ ops: { color: pc30.yellow, emoji: "\u2699\uFE0F ", label: "Ops" }
17382
18232
  };
17383
18233
  function displayTypeForFamily(family) {
17384
18234
  if (family === "workflow" || family === "operator") return "specialized_agents";
17385
18235
  if (family === "studio" || family === "ops") return family;
17386
18236
  return family;
17387
18237
  }
17388
- function typeColor(family, text64) {
18238
+ function typeColor(family, text65) {
17389
18239
  const type = displayTypeForFamily(family);
17390
- return TYPE_CONFIG[type]?.color(text64) ?? text64;
18240
+ return TYPE_CONFIG[type]?.color(text65) ?? text65;
17391
18241
  }
17392
18242
  function typeBadge(family) {
17393
18243
  const type = displayTypeForFamily(family);
@@ -17395,7 +18245,7 @@ function typeBadge(family) {
17395
18245
  if (!cfg) return String(type);
17396
18246
  return cfg.color(`${cfg.emoji} ${cfg.label}`);
17397
18247
  }
17398
- function truncate(str, max) {
18248
+ function truncate2(str, max) {
17399
18249
  if (str.length <= max) return str;
17400
18250
  return str.slice(0, max - 1) + "\u2026";
17401
18251
  }
@@ -17403,20 +18253,20 @@ function displayKitName(name) {
17403
18253
  return name.replace(/^Growthub Agent Worker Kit\s+[—-]\s+/u, "").trim();
17404
18254
  }
17405
18255
  function hr2(width = 72) {
17406
- return pc28.dim("\u2500".repeat(width));
18256
+ return pc30.dim("\u2500".repeat(width));
17407
18257
  }
17408
18258
  function box(lines) {
17409
18259
  const padded = lines.map((l) => " " + l);
17410
- const width = Math.max(...padded.map((l) => stripAnsi(l).length)) + 4;
17411
- const top = pc28.dim("\u250C" + "\u2500".repeat(width) + "\u2510");
17412
- const bottom = pc28.dim("\u2514" + "\u2500".repeat(width) + "\u2518");
18260
+ const width = Math.max(...padded.map((l) => stripAnsi2(l).length)) + 4;
18261
+ const top = pc30.dim("\u250C" + "\u2500".repeat(width) + "\u2510");
18262
+ const bottom = pc30.dim("\u2514" + "\u2500".repeat(width) + "\u2518");
17413
18263
  const body = padded.map((l) => {
17414
- const pad = width - stripAnsi(l).length;
17415
- return pc28.dim("\u2502") + l + " ".repeat(pad) + pc28.dim("\u2502");
18264
+ const pad2 = width - stripAnsi2(l).length;
18265
+ return pc30.dim("\u2502") + l + " ".repeat(pad2) + pc30.dim("\u2502");
17416
18266
  });
17417
18267
  return [top, ...body, bottom].join("\n");
17418
18268
  }
17419
- function stripAnsi(str) {
18269
+ function stripAnsi2(str) {
17420
18270
  return str.replace(/\x1B\[[0-9;]*m/g, "");
17421
18271
  }
17422
18272
  function terminalLink(label, href) {
@@ -17427,13 +18277,13 @@ function folderOpenLabel(folderPath) {
17427
18277
  const label = process.platform === "darwin" ? "Open in Finder" : process.platform === "win32" ? "Open in Explorer" : "Open folder";
17428
18278
  return terminalLink(label, href);
17429
18279
  }
17430
- function renderProgressBar(progress) {
18280
+ function renderProgressBar2(progress) {
17431
18281
  if (!process.stdout.isTTY) return;
17432
18282
  const width = 24;
17433
18283
  const filled = Math.max(0, Math.min(width, Math.round(progress.percent / 100 * width)));
17434
18284
  const bar = `${"=".repeat(filled)}${"-".repeat(width - filled)}`;
17435
- const detail = truncate(progress.detail, 48);
17436
- const line = `\r${pc28.cyan("Exporting kit")} ${pc28.dim("[")}${pc28.green(bar)}${pc28.dim("]")} ${String(progress.percent).padStart(3)}% ${pc28.dim(detail)}`;
18285
+ const detail = truncate2(progress.detail, 48);
18286
+ const line = `\r${pc30.cyan("Exporting kit")} ${pc30.dim("[")}${pc30.green(bar)}${pc30.dim("]")} ${String(progress.percent).padStart(3)}% ${pc30.dim(detail)}`;
17437
18287
  process.stdout.write(line);
17438
18288
  if (progress.phase === "done") {
17439
18289
  process.stdout.write("\n");
@@ -17443,12 +18293,12 @@ function printKitCard(item) {
17443
18293
  const badge2 = typeBadge(item.family);
17444
18294
  console.log("");
17445
18295
  console.log(box([
17446
- `${pc28.bold(item.name)} ${pc28.dim("v" + item.version)}`,
17447
- `${badge2} ${pc28.dim(item.id)}`,
18296
+ `${pc30.bold(item.name)} ${pc30.dim("v" + item.version)}`,
18297
+ `${badge2} ${pc30.dim(item.id)}`,
17448
18298
  "",
17449
- truncate(item.description, 62),
18299
+ truncate2(item.description, 62),
17450
18300
  "",
17451
- `${pc28.dim("Brief:")} ${pc28.dim(item.briefType)} ${pc28.dim("Mode:")} ${pc28.dim(item.executionMode)}`
18301
+ `${pc30.dim("Brief:")} ${pc30.dim(item.briefType)} ${pc30.dim("Mode:")} ${pc30.dim(item.executionMode)}`
17452
18302
  ]));
17453
18303
  }
17454
18304
  function getActionLabel(action) {
@@ -17462,10 +18312,10 @@ async function confirmKitActions(input) {
17462
18312
  return getActionLabel(action);
17463
18313
  });
17464
18314
  const summaryLines = [
17465
- pc28.bold("Selected kits"),
18315
+ pc30.bold("Selected kits"),
17466
18316
  ...input.kits.map((kit) => `${typeBadge(kit.family)} ${displayKitName(kit.name)}`),
17467
18317
  "",
17468
- pc28.bold("Selected actions"),
18318
+ pc30.bold("Selected actions"),
17469
18319
  actionLabels.join(", ")
17470
18320
  ];
17471
18321
  console.log("");
@@ -17490,28 +18340,28 @@ function printGroupedList(kits) {
17490
18340
  const totalTypes = types.length;
17491
18341
  console.log("");
17492
18342
  console.log(
17493
- pc28.bold("Growthub Agent Worker Kits") + pc28.dim(` ${kits.length} kit${kits.length !== 1 ? "s" : ""} \xB7 ${totalTypes} type${totalTypes !== 1 ? "s" : ""}`)
18343
+ pc30.bold("Growthub Agent Worker Kits") + pc30.dim(` ${kits.length} kit${kits.length !== 1 ? "s" : ""} \xB7 ${totalTypes} type${totalTypes !== 1 ? "s" : ""}`)
17494
18344
  );
17495
18345
  console.log(hr2());
17496
18346
  for (const type of types) {
17497
18347
  const groupKits = byType[type];
17498
18348
  const header = typeBadge(type);
17499
18349
  console.log(`
17500
- ${header} ${pc28.dim("(" + groupKits.length + ")")}`);
18350
+ ${header} ${pc30.dim("(" + groupKits.length + ")")}`);
17501
18351
  for (const kit of groupKits) {
17502
- console.log(` ${typeColor(kit.family, pc28.bold(kit.id))} ${pc28.dim("v" + kit.version)}`);
17503
- console.log(` ${pc28.dim(truncate(kit.description, 62))}`);
17504
- console.log(` ${pc28.dim("\u2192")} ${pc28.cyan("growthub kit download " + kit.id)}`);
18352
+ console.log(` ${typeColor(kit.family, pc30.bold(kit.id))} ${pc30.dim("v" + kit.version)}`);
18353
+ console.log(` ${pc30.dim(truncate2(kit.description, 62))}`);
18354
+ console.log(` ${pc30.dim("\u2192")} ${pc30.cyan("growthub kit download " + kit.id)}`);
17505
18355
  console.log("");
17506
18356
  }
17507
18357
  }
17508
18358
  console.log(hr2());
17509
- console.log(pc28.dim(" growthub kit download <id> \xB7 growthub kit inspect <id> \xB7 growthub kit families"));
18359
+ console.log(pc30.dim(" growthub kit download <id> \xB7 growthub kit inspect <id> \xB7 growthub kit families"));
17510
18360
  console.log("");
17511
18361
  }
17512
18362
  async function runInteractivePicker(opts) {
17513
18363
  printPaperclipCliBanner();
17514
- p19.intro(pc28.bold("Growthub Agent Worker Kits"));
18364
+ p19.intro(pc30.bold("Growthub Agent Worker Kits"));
17515
18365
  let kits;
17516
18366
  try {
17517
18367
  kits = listBundledKits();
@@ -17553,8 +18403,8 @@ async function runInteractivePicker(opts) {
17553
18403
  options: [
17554
18404
  ...filtered.map((k) => ({
17555
18405
  value: k.id,
17556
- label: (showTypeBadgeInKitChoices ? typeBadge(k.family) + " " : "") + pc28.bold(displayKitName(k.name)) + " " + pc28.dim("v" + k.version),
17557
- hint: truncate(k.description, 55)
18406
+ label: (showTypeBadgeInKitChoices ? typeBadge(k.family) + " " : "") + pc30.bold(displayKitName(k.name)) + " " + pc30.dim("v" + k.version),
18407
+ hint: truncate2(k.description, 55)
17558
18408
  })),
17559
18409
  { value: "__back_to_type", label: "\u2190 Back to type filter" }
17560
18410
  ]
@@ -17618,16 +18468,16 @@ async function runInteractivePicker(opts) {
17618
18468
  }
17619
18469
  if (action === "copy-id") {
17620
18470
  console.log(selected.id);
17621
- p19.outro(pc28.dim("Kit ID printed above."));
18471
+ p19.outro(pc30.dim("Kit ID printed above."));
17622
18472
  return "done";
17623
18473
  }
17624
18474
  if (action === "inspect") {
17625
18475
  runInspect(selected.id, opts.out);
17626
- p19.outro(pc28.dim("Done."));
18476
+ p19.outro(pc30.dim("Done."));
17627
18477
  return "done";
17628
18478
  }
17629
18479
  await runDownload(selected.id, opts);
17630
- p19.outro(pc28.green("Kit exported successfully."));
18480
+ p19.outro(pc30.green("Kit exported successfully."));
17631
18481
  return "done";
17632
18482
  }
17633
18483
  }
@@ -17636,58 +18486,58 @@ async function runInteractivePicker(opts) {
17636
18486
  async function runDownload(kitId, opts) {
17637
18487
  const resolvedId = fuzzyResolveKitId(kitId);
17638
18488
  if (!resolvedId) {
17639
- console.error(pc28.red("Unknown kit '" + kitId + "'.") + pc28.dim(" Run `growthub kit list` to browse."));
18489
+ console.error(pc30.red("Unknown kit '" + kitId + "'.") + pc30.dim(" Run `growthub kit list` to browse."));
17640
18490
  process.exit(1);
17641
18491
  }
17642
18492
  if (resolvedId !== kitId) {
17643
- console.log(pc28.dim("Resolved '" + kitId + "' \u2192 " + resolvedId));
18493
+ console.log(pc30.dim("Resolved '" + kitId + "' \u2192 " + resolvedId));
17644
18494
  }
17645
18495
  const kits = listBundledKits();
17646
18496
  const item = kits.find((k) => k.id === resolvedId);
17647
18497
  printKitCard(item);
17648
18498
  if (!opts.yes) {
17649
- const confirmed = await p19.confirm({ message: "Download " + pc28.bold(displayKitName(item.name)) + "?" });
18499
+ const confirmed = await p19.confirm({ message: "Download " + pc30.bold(displayKitName(item.name)) + "?" });
17650
18500
  if (p19.isCancel(confirmed) || !confirmed) {
17651
18501
  p19.cancel("Cancelled.");
17652
18502
  process.exit(0);
17653
18503
  }
17654
18504
  }
17655
18505
  const result = downloadBundledKit(resolvedId, opts.out, {
17656
- onProgress: renderProgressBar
18506
+ onProgress: renderProgressBar2
17657
18507
  });
17658
18508
  console.log("");
17659
- console.log(pc28.green(pc28.bold("Kit exported successfully.")));
18509
+ console.log(pc30.green(pc30.bold("Kit exported successfully.")));
17660
18510
  console.log("");
17661
18511
  const nextSteps = [
17662
- pc28.bold("Next steps"),
18512
+ pc30.bold("Next steps"),
17663
18513
  "",
17664
- pc28.dim("1.") + " Point Working Directory at:",
17665
- " " + pc28.cyan(result.folderPath),
18514
+ pc30.dim("1.") + " Point Working Directory at:",
18515
+ " " + pc30.cyan(result.folderPath),
17666
18516
  "",
17667
- pc28.dim("2.") + " " + pc28.cyan("cp .env.example .env") + " \u2192 add your API key",
17668
- pc28.dim("3.") + " " + pc28.cyan("bash setup/clone-fork.sh") + " \u2192 boot local studio",
17669
- pc28.dim("4.") + " Open Growthub local \u2014 the agent loads automatically",
18517
+ pc30.dim("2.") + " " + pc30.cyan("cp .env.example .env") + " \u2192 add your API key",
18518
+ pc30.dim("3.") + " " + pc30.cyan("bash setup/clone-fork.sh") + " \u2192 boot local studio",
18519
+ pc30.dim("4.") + " Open Growthub local \u2014 the agent loads automatically",
17670
18520
  "",
17671
- pc28.dim("Docs: QUICKSTART.md \xB7 validation-checklist.md")
18521
+ pc30.dim("Docs: QUICKSTART.md \xB7 validation-checklist.md")
17672
18522
  ];
17673
18523
  console.log("");
17674
18524
  console.log(box(nextSteps));
17675
18525
  console.log("");
17676
- console.log(pc28.bold("Open folder: ") + folderOpenLabel(result.folderPath));
17677
- console.log(pc28.dim("Folder: ") + result.folderPath);
18526
+ console.log(pc30.bold("Open folder: ") + folderOpenLabel(result.folderPath));
18527
+ console.log(pc30.dim("Folder: ") + result.folderPath);
17678
18528
  console.log("");
17679
- console.log(pc28.dim("Zip: ") + result.zipPath);
18529
+ console.log(pc30.dim("Zip: ") + result.zipPath);
17680
18530
  console.log("");
17681
18531
  }
17682
18532
  function runInspect(kitId, outDir) {
17683
18533
  const info = inspectBundledKit(kitId, outDir);
17684
- const kv = (label, value) => console.log(" " + pc28.bold(label.padEnd(24)) + " " + value);
18534
+ const kv = (label, value) => console.log(" " + pc30.bold(label.padEnd(24)) + " " + value);
17685
18535
  console.log("");
17686
- console.log(pc28.bold("Kit: " + info.id) + pc28.dim(" v" + info.version));
17687
- console.log(typeBadge(info.family) + pc28.dim(" schema v" + info.schemaVersion));
18536
+ console.log(pc30.bold("Kit: " + info.id) + pc30.dim(" v" + info.version));
18537
+ console.log(typeBadge(info.family) + pc30.dim(" schema v" + info.schemaVersion));
17688
18538
  console.log(hr2());
17689
18539
  kv("Name:", info.name);
17690
- kv("Description:", truncate(info.description, 55));
18540
+ kv("Description:", truncate2(info.description, 55));
17691
18541
  kv("Entrypoint:", info.entrypointPath);
17692
18542
  kv("Agent Contract:", info.agentContractPath);
17693
18543
  kv("Bundle:", info.bundleId + " @ " + info.bundleVersion);
@@ -17700,8 +18550,8 @@ function runInspect(kitId, outDir) {
17700
18550
  kv("Compatibility:", JSON.stringify(info.compatibility));
17701
18551
  }
17702
18552
  console.log(hr2());
17703
- console.log(pc28.bold(" Required Paths:"));
17704
- for (const rp of info.requiredPaths) console.log(" " + pc28.dim("\xB7") + " " + rp);
18553
+ console.log(pc30.bold(" Required Paths:"));
18554
+ for (const rp of info.requiredPaths) console.log(" " + pc30.dim("\xB7") + " " + rp);
17705
18555
  console.log("");
17706
18556
  }
17707
18557
  function registerKitCommands(program2) {
@@ -17737,8 +18587,8 @@ Examples:
17737
18587
  const wanted = opts.family.split(",").map((f) => f.trim().toLowerCase());
17738
18588
  kits = kits.filter((k) => wanted.includes(k.family));
17739
18589
  if (kits.length === 0) {
17740
- console.error(pc28.yellow("No kits found for family: " + opts.family));
17741
- console.error(pc28.dim("Valid families: studio, workflow, operator, ops"));
18590
+ console.error(pc30.yellow("No kits found for family: " + opts.family));
18591
+ console.error(pc30.dim("Valid families: studio, workflow, operator, ops"));
17742
18592
  process.exitCode = 1;
17743
18593
  return;
17744
18594
  }
@@ -17756,7 +18606,7 @@ Examples:
17756
18606
  `).action((kitId, opts) => {
17757
18607
  const resolvedId = fuzzyResolveKitId(kitId);
17758
18608
  if (!resolvedId) {
17759
- console.error(pc28.red("Unknown kit '" + kitId + "'.") + pc28.dim(" Run `growthub kit list` to browse."));
18609
+ console.error(pc30.red("Unknown kit '" + kitId + "'.") + pc30.dim(" Run `growthub kit list` to browse."));
17760
18610
  process.exitCode = 1;
17761
18611
  return;
17762
18612
  }
@@ -17780,23 +18630,23 @@ Examples:
17780
18630
  }
17781
18631
  const resolvedId = fuzzyResolveKitId(kitId);
17782
18632
  if (!resolvedId) {
17783
- console.error(pc28.red("Unknown kit '" + kitId + "'.") + pc28.dim(" Run `growthub kit list` to browse."));
18633
+ console.error(pc30.red("Unknown kit '" + kitId + "'.") + pc30.dim(" Run `growthub kit list` to browse."));
17784
18634
  process.exitCode = 1;
17785
18635
  return;
17786
18636
  }
17787
18637
  if (opts.yes) {
17788
18638
  const result = downloadBundledKit(resolvedId, opts.out, {
17789
- onProgress: renderProgressBar
18639
+ onProgress: renderProgressBar2
17790
18640
  });
17791
18641
  console.log("");
17792
- console.log(pc28.bold("Exported folder:"), pc28.cyan(result.folderPath));
17793
- console.log(pc28.bold("Open folder: "), folderOpenLabel(result.folderPath));
17794
- console.log(pc28.bold("Zip: "), pc28.dim(result.zipPath));
18642
+ console.log(pc30.bold("Exported folder:"), pc30.cyan(result.folderPath));
18643
+ console.log(pc30.bold("Open folder: "), folderOpenLabel(result.folderPath));
18644
+ console.log(pc30.bold("Zip: "), pc30.dim(result.zipPath));
17795
18645
  console.log("");
17796
- console.log(pc28.bold("Next steps:"));
17797
- console.log(" 1. Point Working Directory at: " + pc28.cyan(result.folderPath));
17798
- console.log(" 2. " + pc28.cyan("cp .env.example .env") + " \u2192 add your API key");
17799
- console.log(" 3. " + pc28.cyan("bash setup/clone-fork.sh") + " \u2192 boot local studio");
18646
+ console.log(pc30.bold("Next steps:"));
18647
+ console.log(" 1. Point Working Directory at: " + pc30.cyan(result.folderPath));
18648
+ console.log(" 2. " + pc30.cyan("cp .env.example .env") + " \u2192 add your API key");
18649
+ console.log(" 3. " + pc30.cyan("bash setup/clone-fork.sh") + " \u2192 boot local studio");
17800
18650
  console.log(" 4. Open Growthub local \u2014 the agent loads automatically");
17801
18651
  console.log("");
17802
18652
  return;
@@ -17806,7 +18656,7 @@ Examples:
17806
18656
  kit.command("path").description("Resolve the expected export folder path without exporting").argument("<kit-id>", "Kit id or fuzzy slug").option("--out <path>", "Override the export root").action((kitId, opts) => {
17807
18657
  const resolvedId = fuzzyResolveKitId(kitId);
17808
18658
  if (!resolvedId) {
17809
- console.error(pc28.red("Unknown kit '" + kitId + "'."));
18659
+ console.error(pc30.red("Unknown kit '" + kitId + "'."));
17810
18660
  process.exitCode = 1;
17811
18661
  return;
17812
18662
  }
@@ -17820,20 +18670,20 @@ Examples:
17820
18670
  const resolvedPath = path33.resolve(kitPath);
17821
18671
  const result = validateKitDirectory(resolvedPath);
17822
18672
  console.log("");
17823
- console.log(pc28.bold("Kit: " + result.kitId) + pc28.dim(" schema v" + result.schemaVersion));
18673
+ console.log(pc30.bold("Kit: " + result.kitId) + pc30.dim(" schema v" + result.schemaVersion));
17824
18674
  console.log(hr2());
17825
18675
  for (const w of result.warnings) {
17826
- console.log(pc28.yellow(" WARN " + w.field + ": " + w.message));
18676
+ console.log(pc30.yellow(" WARN " + w.field + ": " + w.message));
17827
18677
  }
17828
18678
  for (const e of result.errors) {
17829
- console.log(pc28.red(" ERROR " + e.field + ": " + e.message));
18679
+ console.log(pc30.red(" ERROR " + e.field + ": " + e.message));
17830
18680
  }
17831
18681
  if (result.errors.length > 0) {
17832
18682
  console.log("");
17833
- console.log(pc28.red(pc28.bold(" Result: INVALID")) + pc28.dim(" (" + result.errors.length + " error" + (result.errors.length !== 1 ? "s" : "") + ")"));
18683
+ console.log(pc30.red(pc30.bold(" Result: INVALID")) + pc30.dim(" (" + result.errors.length + " error" + (result.errors.length !== 1 ? "s" : "") + ")"));
17834
18684
  process.exitCode = 1;
17835
18685
  } else {
17836
- console.log(pc28.green(pc28.bold(" Result: VALID")));
18686
+ console.log(pc30.green(pc30.bold(" Result: VALID")));
17837
18687
  }
17838
18688
  console.log("");
17839
18689
  });
@@ -17845,17 +18695,17 @@ Examples:
17845
18695
  { family: "ops", tagline: "Infrastructure / toolchain operator (provider optional)", surfaces: "local-fork (primary)", example: "(coming soon)" }
17846
18696
  ];
17847
18697
  console.log("");
17848
- console.log(pc28.bold("Kit Family Taxonomy"));
18698
+ console.log(pc30.bold("Kit Family Taxonomy"));
17849
18699
  console.log(hr2());
17850
18700
  for (const def of defs) {
17851
18701
  console.log("\n " + typeBadge(def.family));
17852
- console.log(" " + pc28.dim(def.tagline));
17853
- console.log(" " + pc28.dim("Surfaces: ") + pc28.dim(def.surfaces));
17854
- console.log(" " + pc28.dim("Example: ") + pc28.cyan(def.example));
18702
+ console.log(" " + pc30.dim(def.tagline));
18703
+ console.log(" " + pc30.dim("Surfaces: ") + pc30.dim(def.surfaces));
18704
+ console.log(" " + pc30.dim("Example: ") + pc30.cyan(def.example));
17855
18705
  }
17856
18706
  console.log("");
17857
18707
  console.log(hr2());
17858
- console.log(pc28.dim(" growthub kit list --family <family> to filter by internal family"));
18708
+ console.log(pc30.dim(" growthub kit list --family <family> to filter by internal family"));
17859
18709
  console.log("");
17860
18710
  });
17861
18711
  registerKitForkSubcommands(kit);
@@ -17864,7 +18714,7 @@ Examples:
17864
18714
  // src/commands/template.ts
17865
18715
  import path35 from "node:path";
17866
18716
  import * as p20 from "@clack/prompts";
17867
- import pc29 from "picocolors";
18717
+ import pc31 from "picocolors";
17868
18718
 
17869
18719
  // src/templates/service.ts
17870
18720
  import fs26 from "node:fs";
@@ -18209,44 +19059,44 @@ function getCatalogStats() {
18209
19059
  }
18210
19060
 
18211
19061
  // src/commands/template.ts
18212
- function stripAnsi2(s) {
19062
+ function stripAnsi3(s) {
18213
19063
  return s.replace(/\x1B\[[0-9;]*m/g, "");
18214
19064
  }
18215
19065
  function hr3(w = 72) {
18216
- return pc29.dim("\u2500".repeat(w));
19066
+ return pc31.dim("\u2500".repeat(w));
18217
19067
  }
18218
- function truncate2(s, max) {
19068
+ function truncate3(s, max) {
18219
19069
  return s.length <= max ? s : s.slice(0, max - 1) + "\u2026";
18220
19070
  }
18221
19071
  function box2(lines) {
18222
19072
  const padded = lines.map((l) => " " + l);
18223
- const width = Math.max(...padded.map((l) => stripAnsi2(l).length)) + 4;
18224
- const top = pc29.dim("\u250C" + "\u2500".repeat(width) + "\u2510");
18225
- const bottom = pc29.dim("\u2514" + "\u2500".repeat(width) + "\u2518");
18226
- const body = padded.map((l) => pc29.dim("\u2502") + l + " ".repeat(width - stripAnsi2(l).length) + pc29.dim("\u2502"));
19073
+ const width = Math.max(...padded.map((l) => stripAnsi3(l).length)) + 4;
19074
+ const top = pc31.dim("\u250C" + "\u2500".repeat(width) + "\u2510");
19075
+ const bottom = pc31.dim("\u2514" + "\u2500".repeat(width) + "\u2518");
19076
+ const body = padded.map((l) => pc31.dim("\u2502") + l + " ".repeat(width - stripAnsi3(l).length) + pc31.dim("\u2502"));
18227
19077
  return [top, ...body, bottom].join("\n");
18228
19078
  }
18229
19079
  function badge(a) {
18230
- if (a.type === "ad-format") return pc29.cyan("\u{1F3AC} Ad Format");
19080
+ if (a.type === "ad-format") return pc31.cyan("\u{1F3AC} Ad Format");
18231
19081
  if (a.type === "scene-module") {
18232
- if (a.subtype === "hook") return pc29.yellow("\u{1FA9D} Hook");
18233
- if (a.subtype === "body") return pc29.blue("\u{1F9E9} Body");
18234
- if (a.subtype === "cta") return pc29.green("\u{1F3AF} CTA");
19082
+ if (a.subtype === "hook") return pc31.yellow("\u{1FA9D} Hook");
19083
+ if (a.subtype === "body") return pc31.blue("\u{1F9E9} Body");
19084
+ if (a.subtype === "cta") return pc31.green("\u{1F3AF} CTA");
18235
19085
  }
18236
- return pc29.magenta("\u{1F9E9} Module");
19086
+ return pc31.magenta("\u{1F9E9} Module");
18237
19087
  }
18238
19088
  function printCard(a) {
18239
- const compat = a.compatibleFormats.length ? pc29.dim("Works with: ") + a.compatibleFormats.map((f) => pc29.cyan(f)).join(", ") : pc29.dim("Works with: any format");
19089
+ const compat = a.compatibleFormats.length ? pc31.dim("Works with: ") + a.compatibleFormats.map((f) => pc31.cyan(f)).join(", ") : pc31.dim("Works with: any format");
18240
19090
  const rows = [
18241
- pc29.bold(a.name),
18242
- `${badge(a)} ${pc29.dim(a.id)}`,
19091
+ pc31.bold(a.name),
19092
+ `${badge(a)} ${pc31.dim(a.id)}`,
18243
19093
  "",
18244
- truncate2(a.category, 62),
19094
+ truncate3(a.category, 62),
18245
19095
  "",
18246
19096
  compat
18247
19097
  ];
18248
19098
  if (a.type === "ad-format" && a.scenes != null) {
18249
- rows.push(pc29.dim("Scenes: ") + a.scenes + (a.hookVariations ? pc29.dim(" \xB7 Hook variations: ") + a.hookVariations : ""));
19099
+ rows.push(pc31.dim("Scenes: ") + a.scenes + (a.hookVariations ? pc31.dim(" \xB7 Hook variations: ") + a.hookVariations : ""));
18250
19100
  }
18251
19101
  console.log("");
18252
19102
  console.log(box2(rows));
@@ -18254,32 +19104,32 @@ function printCard(a) {
18254
19104
  function printSummary2(filter) {
18255
19105
  const artifacts = listArtifacts(filter);
18256
19106
  if (!artifacts.length) {
18257
- console.log(pc29.yellow("No templates matched. Try: growthub template list"));
19107
+ console.log(pc31.yellow("No templates matched. Try: growthub template list"));
18258
19108
  return;
18259
19109
  }
18260
19110
  const stats = getCatalogStats();
18261
19111
  const groups = groupArtifacts(artifacts);
18262
19112
  console.log("");
18263
- console.log(pc29.bold("Growthub Shared Template Library") + pc29.dim(` ${artifacts.length} of ${stats.total} artifacts`));
18264
- console.log(pc29.dim(" " + Object.entries(stats.byFamily).map(([f, n]) => `${f} (${n})`).join(" \xB7 ")));
19113
+ console.log(pc31.bold("Growthub Shared Template Library") + pc31.dim(` ${artifacts.length} of ${stats.total} artifacts`));
19114
+ console.log(pc31.dim(" " + Object.entries(stats.byFamily).map(([f, n]) => `${f} (${n})`).join(" \xB7 ")));
18265
19115
  console.log(hr3());
18266
19116
  for (const g of groups) {
18267
19117
  console.log(`
18268
- ${pc29.bold(g.label)} ${pc29.dim("(" + g.count + ")")}`);
18269
- console.log(pc29.dim(" " + g.description));
19118
+ ${pc31.bold(g.label)} ${pc31.dim("(" + g.count + ")")}`);
19119
+ console.log(pc31.dim(" " + g.description));
18270
19120
  console.log("");
18271
19121
  for (const a of g.artifacts) {
18272
- const compat = a.compatibleFormats.length ? pc29.dim(" \xB7 " + a.compatibleFormats.join(", ")) : "";
18273
- console.log(` ${pc29.cyan(pc29.bold(a.name))}${compat}`);
18274
- console.log(` ${pc29.dim("growthub template get " + a.slug)}`);
19122
+ const compat = a.compatibleFormats.length ? pc31.dim(" \xB7 " + a.compatibleFormats.join(", ")) : "";
19123
+ console.log(` ${pc31.cyan(pc31.bold(a.name))}${compat}`);
19124
+ console.log(` ${pc31.dim("growthub template get " + a.slug)}`);
18275
19125
  console.log("");
18276
19126
  }
18277
19127
  }
18278
19128
  console.log(hr3());
18279
- console.log(pc29.dim(" growthub template get <slug>"));
18280
- console.log(pc29.dim(" growthub template list --type ad-formats"));
18281
- console.log(pc29.dim(" growthub template list --type scene-modules --subtype hooks"));
18282
- console.log(pc29.dim(" growthub template (interactive picker)"));
19129
+ console.log(pc31.dim(" growthub template get <slug>"));
19130
+ console.log(pc31.dim(" growthub template list --type ad-formats"));
19131
+ console.log(pc31.dim(" growthub template list --type scene-modules --subtype hooks"));
19132
+ console.log(pc31.dim(" growthub template (interactive picker)"));
18283
19133
  console.log("");
18284
19134
  }
18285
19135
  var TEMPLATE_FAMILY_META = {
@@ -18305,7 +19155,7 @@ var TEMPLATE_FAMILY_META = {
18305
19155
  }
18306
19156
  };
18307
19157
  async function runTemplatePicker(opts) {
18308
- p20.intro(pc29.bold("Growthub Shared Template Library"));
19158
+ p20.intro(pc31.bold("Growthub Shared Template Library"));
18309
19159
  let artifacts;
18310
19160
  try {
18311
19161
  artifacts = listArtifacts();
@@ -18357,8 +19207,8 @@ async function runTemplatePicker(opts) {
18357
19207
  message: `Select from: ${group.label}`,
18358
19208
  options: group.artifacts.map((a) => ({
18359
19209
  value: a.id,
18360
- label: pc29.bold(a.name),
18361
- hint: truncate2(a.category, 52)
19210
+ label: pc31.bold(a.name),
19211
+ hint: truncate3(a.category, 52)
18362
19212
  }))
18363
19213
  });
18364
19214
  if (p20.isCancel(artifactChoice)) {
@@ -18382,7 +19232,7 @@ async function runTemplatePicker(opts) {
18382
19232
  }
18383
19233
  if (action === "slug") {
18384
19234
  console.log(selected.slug);
18385
- p20.outro(pc29.dim("Use with: growthub template get " + selected.slug));
19235
+ p20.outro(pc31.dim("Use with: growthub template get " + selected.slug));
18386
19236
  return "done";
18387
19237
  }
18388
19238
  if (action === "print") {
@@ -18390,7 +19240,7 @@ async function runTemplatePicker(opts) {
18390
19240
  console.log("\n" + hr3());
18391
19241
  console.log(r.content);
18392
19242
  console.log(hr3());
18393
- p20.outro(pc29.dim("Source: " + r.absolutePath));
19243
+ p20.outro(pc31.dim("Source: " + r.absolutePath));
18394
19244
  return "done";
18395
19245
  }
18396
19246
  if (action === "copy") {
@@ -18405,7 +19255,7 @@ async function runTemplatePicker(opts) {
18405
19255
  }
18406
19256
  const destDir = path35.resolve(destInput.replace(/^~/, process.env["HOME"] ?? ""));
18407
19257
  const destPath = copyArtifact(selected.id, destDir);
18408
- p20.outro(pc29.green("Copied \u2192 ") + destPath);
19258
+ p20.outro(pc31.green("Copied \u2192 ") + destPath);
18409
19259
  return "done";
18410
19260
  }
18411
19261
  return "done";
@@ -18432,7 +19282,7 @@ Any agent or kit resolves them by slug.
18432
19282
  if (opts.type) {
18433
19283
  const t = opts.type.replace(/s$/, "");
18434
19284
  if (t !== "ad-format" && t !== "scene-module") {
18435
- console.error(pc29.red(`Unknown --type '${opts.type}'.`) + pc29.dim(" Valid: ad-formats, scene-modules"));
19285
+ console.error(pc31.red(`Unknown --type '${opts.type}'.`) + pc31.dim(" Valid: ad-formats, scene-modules"));
18436
19286
  process.exitCode = 1;
18437
19287
  return;
18438
19288
  }
@@ -18441,7 +19291,7 @@ Any agent or kit resolves them by slug.
18441
19291
  if (opts.subtype) {
18442
19292
  const sub = opts.subtype.replace(/s$/, "");
18443
19293
  if (!["hook", "body", "cta"].includes(sub)) {
18444
- console.error(pc29.red(`Unknown --subtype '${opts.subtype}'.`) + pc29.dim(" Valid: hooks, body, cta"));
19294
+ console.error(pc31.red(`Unknown --subtype '${opts.subtype}'.`) + pc31.dim(" Valid: hooks, body, cta"));
18445
19295
  process.exitCode = 1;
18446
19296
  return;
18447
19297
  }
@@ -18457,18 +19307,18 @@ Any agent or kit resolves them by slug.
18457
19307
  cmd.command("get").description("Print or copy a template \u2014 fuzzy slug resolution").argument("<slug>", "Artifact slug (e.g. villain-animation, meme-overlay)").option("--out <path>", "Copy to this directory").option("--json", "Artifact metadata + content as JSON").action((slug, opts) => {
18458
19308
  const artifact = resolveSlug(slug);
18459
19309
  if (!artifact) {
18460
- console.error(pc29.red(`Unknown template '${slug}'.`) + pc29.dim(" Run `growthub template list` to browse."));
19310
+ console.error(pc31.red(`Unknown template '${slug}'.`) + pc31.dim(" Run `growthub template list` to browse."));
18461
19311
  process.exitCode = 1;
18462
19312
  return;
18463
19313
  }
18464
19314
  if (artifact.id !== slug && artifact.slug !== slug) {
18465
- console.error(pc29.dim(`Resolved '${slug}' \u2192 ${artifact.slug}`));
19315
+ console.error(pc31.dim(`Resolved '${slug}' \u2192 ${artifact.slug}`));
18466
19316
  }
18467
19317
  let resolved;
18468
19318
  try {
18469
19319
  resolved = getArtifact(artifact.id);
18470
19320
  } catch (err) {
18471
- console.error(pc29.red(err.message));
19321
+ console.error(pc31.red(err.message));
18472
19322
  process.exitCode = 1;
18473
19323
  return;
18474
19324
  }
@@ -18480,9 +19330,9 @@ Any agent or kit resolves them by slug.
18480
19330
  const destDir = path35.resolve(opts.out.replace(/^~/, process.env["HOME"] ?? ""));
18481
19331
  try {
18482
19332
  const dest = copyArtifact(artifact.id, destDir);
18483
- console.log(pc29.green("Copied \u2192 ") + dest);
19333
+ console.log(pc31.green("Copied \u2192 ") + dest);
18484
19334
  } catch (err) {
18485
- console.error(pc29.red(err.message));
19335
+ console.error(pc31.red(err.message));
18486
19336
  process.exitCode = 1;
18487
19337
  }
18488
19338
  return;
@@ -18491,14 +19341,14 @@ Any agent or kit resolves them by slug.
18491
19341
  console.log(hr3());
18492
19342
  console.log(resolved.content);
18493
19343
  console.log(hr3());
18494
- console.log(pc29.dim("Source: " + resolved.absolutePath));
19344
+ console.log(pc31.dim("Source: " + resolved.absolutePath));
18495
19345
  console.log("");
18496
19346
  });
18497
19347
  }
18498
19348
 
18499
19349
  // src/commands/capability.ts
18500
19350
  import * as p21 from "@clack/prompts";
18501
- import pc30 from "picocolors";
19351
+ import pc32 from "picocolors";
18502
19352
 
18503
19353
  // src/runtime/hosted-execution-client/index.ts
18504
19354
  init_http();
@@ -18877,15 +19727,15 @@ function summarizeExecution(executionLog) {
18877
19727
  async function toHostedExecutionError(response) {
18878
19728
  let message = `Request failed with status ${response.status}`;
18879
19729
  try {
18880
- const text64 = await response.text();
18881
- if (text64.trim()) {
18882
- const parsed = JSON.parse(text64);
19730
+ const text65 = await response.text();
19731
+ if (text65.trim()) {
19732
+ const parsed = JSON.parse(text65);
18883
19733
  if (typeof parsed.error === "string" && parsed.error.trim()) {
18884
19734
  message = parsed.error;
18885
19735
  } else if (typeof parsed.message === "string" && parsed.message.trim()) {
18886
19736
  message = parsed.message;
18887
19737
  } else {
18888
- message = text64;
19738
+ message = text65;
18889
19739
  }
18890
19740
  }
18891
19741
  } catch {
@@ -19257,12 +20107,12 @@ function getWorkflowAccess() {
19257
20107
  // src/commands/capability.ts
19258
20108
  init_banner();
19259
20109
  var FAMILY_CONFIG = {
19260
- video: { color: pc30.magenta, emoji: "\u{1F3AC}", label: "Video" },
19261
- image: { color: pc30.cyan, emoji: "\u{1F5BC}\uFE0F ", label: "Image" },
19262
- slides: { color: pc30.yellow, emoji: "\u{1F4CA}", label: "Slides" },
19263
- text: { color: pc30.green, emoji: "\u{1F4DD}", label: "Text" },
19264
- data: { color: pc30.blue, emoji: "\u{1F4E6}", label: "Data" },
19265
- ops: { color: pc30.red, emoji: "\u2699\uFE0F ", label: "Ops" }
20110
+ video: { color: pc32.magenta, emoji: "\u{1F3AC}", label: "Video" },
20111
+ image: { color: pc32.cyan, emoji: "\u{1F5BC}\uFE0F ", label: "Image" },
20112
+ slides: { color: pc32.yellow, emoji: "\u{1F4CA}", label: "Slides" },
20113
+ text: { color: pc32.green, emoji: "\u{1F4DD}", label: "Text" },
20114
+ data: { color: pc32.blue, emoji: "\u{1F4E6}", label: "Data" },
20115
+ ops: { color: pc32.red, emoji: "\u2699\uFE0F ", label: "Ops" }
19266
20116
  };
19267
20117
  function familyBadge(family) {
19268
20118
  const cfg = FAMILY_CONFIG[family];
@@ -19270,25 +20120,25 @@ function familyBadge(family) {
19270
20120
  return cfg.color(`${cfg.emoji} ${cfg.label}`);
19271
20121
  }
19272
20122
  function executionKindLabel(kind) {
19273
- if (kind === "hosted-execute") return pc30.cyan("hosted");
19274
- if (kind === "provider-assembly") return pc30.yellow("provider");
19275
- if (kind === "local-only") return pc30.green("local");
20123
+ if (kind === "hosted-execute") return pc32.cyan("hosted");
20124
+ if (kind === "provider-assembly") return pc32.yellow("provider");
20125
+ if (kind === "local-only") return pc32.green("local");
19276
20126
  return kind;
19277
20127
  }
19278
20128
  function hr4(width = 72) {
19279
- return pc30.dim("\u2500".repeat(width));
20129
+ return pc32.dim("\u2500".repeat(width));
19280
20130
  }
19281
- function stripAnsi3(str) {
20131
+ function stripAnsi4(str) {
19282
20132
  return str.replace(/\x1B\[[0-9;]*m/g, "");
19283
20133
  }
19284
20134
  function box3(lines) {
19285
20135
  const padded = lines.map((l) => " " + l);
19286
- const width = Math.max(...padded.map((l) => stripAnsi3(l).length)) + 4;
19287
- const top = pc30.dim("\u250C" + "\u2500".repeat(width) + "\u2510");
19288
- const bottom = pc30.dim("\u2514" + "\u2500".repeat(width) + "\u2518");
20136
+ const width = Math.max(...padded.map((l) => stripAnsi4(l).length)) + 4;
20137
+ const top = pc32.dim("\u250C" + "\u2500".repeat(width) + "\u2510");
20138
+ const bottom = pc32.dim("\u2514" + "\u2500".repeat(width) + "\u2518");
19289
20139
  const body = padded.map((l) => {
19290
- const pad = width - stripAnsi3(l).length;
19291
- return pc30.dim("\u2502") + l + " ".repeat(pad) + pc30.dim("\u2502");
20140
+ const pad2 = width - stripAnsi4(l).length;
20141
+ return pc32.dim("\u2502") + l + " ".repeat(pad2) + pc32.dim("\u2502");
19292
20142
  });
19293
20143
  return [top, ...body, bottom].join("\n");
19294
20144
  }
@@ -19301,48 +20151,48 @@ function printGroupedCapabilities(nodes) {
19301
20151
  const totalFamilies = families.length;
19302
20152
  console.log("");
19303
20153
  console.log(
19304
- pc30.bold("CMS Capability Registry") + pc30.dim(` ${nodes.length} capabilit${nodes.length !== 1 ? "ies" : "y"} \xB7 ${totalFamilies} ${totalFamilies !== 1 ? "families" : "family"}`)
20154
+ pc32.bold("CMS Capability Registry") + pc32.dim(` ${nodes.length} capabilit${nodes.length !== 1 ? "ies" : "y"} \xB7 ${totalFamilies} ${totalFamilies !== 1 ? "families" : "family"}`)
19305
20155
  );
19306
20156
  console.log(hr4());
19307
20157
  for (const family of families) {
19308
20158
  const groupNodes = byFamily[family];
19309
20159
  const header = familyBadge(family);
19310
20160
  console.log(`
19311
- ${header} ${pc30.dim("(" + groupNodes.length + ")")}`);
20161
+ ${header} ${pc32.dim("(" + groupNodes.length + ")")}`);
19312
20162
  for (const node of groupNodes) {
19313
- const enabledTag = node.enabled ? pc30.green("enabled") : pc30.red("disabled");
19314
- console.log(` ${pc30.bold(node.slug)} ${pc30.dim(node.displayName)} ${enabledTag}`);
19315
- console.log(` ${pc30.dim("Execution:")} ${executionKindLabel(node.executionKind)} ${pc30.dim("Outputs:")} ${pc30.dim(node.outputTypes.join(", "))}`);
20163
+ const enabledTag = node.enabled ? pc32.green("enabled") : pc32.red("disabled");
20164
+ console.log(` ${pc32.bold(node.slug)} ${pc32.dim(node.displayName)} ${enabledTag}`);
20165
+ console.log(` ${pc32.dim("Execution:")} ${executionKindLabel(node.executionKind)} ${pc32.dim("Outputs:")} ${pc32.dim(node.outputTypes.join(", "))}`);
19316
20166
  if (node.description) {
19317
- console.log(` ${pc30.dim(node.description)}`);
20167
+ console.log(` ${pc32.dim(node.description)}`);
19318
20168
  }
19319
20169
  console.log("");
19320
20170
  }
19321
20171
  }
19322
20172
  console.log(hr4());
19323
- console.log(pc30.dim(" growthub capability inspect <slug> \xB7 growthub capability resolve"));
20173
+ console.log(pc32.dim(" growthub capability inspect <slug> \xB7 growthub capability resolve"));
19324
20174
  console.log("");
19325
20175
  }
19326
20176
  function printCapabilityCard(node) {
19327
20177
  const iconPrefix = node.icon ? `${node.icon} ` : "";
19328
20178
  const lines = [
19329
- `${iconPrefix}${pc30.bold(node.displayName)} ${pc30.dim(node.slug)}`,
19330
- `${familyBadge(node.family)} ${node.enabled ? pc30.green("enabled") : pc30.red("disabled")}`,
20179
+ `${iconPrefix}${pc32.bold(node.displayName)} ${pc32.dim(node.slug)}`,
20180
+ `${familyBadge(node.family)} ${node.enabled ? pc32.green("enabled") : pc32.red("disabled")}`,
19331
20181
  "",
19332
- `${pc30.dim("Category:")} ${node.category}`,
19333
- `${pc30.dim("Node Type:")} ${node.nodeType}`,
19334
- `${pc30.dim("Execution Kind:")} ${executionKindLabel(node.executionKind)}`,
19335
- `${pc30.dim("Execution Strategy:")} ${node.executionBinding.strategy}`,
19336
- `${pc30.dim("Tool Name:")} ${node.executionTokens.tool_name}`,
19337
- `${pc30.dim("Output Types:")} ${node.outputTypes.join(", ")}`,
19338
- `${pc30.dim("Required Bindings:")} ${node.requiredBindings.length > 0 ? node.requiredBindings.join(", ") : pc30.dim("(none)")}`
20182
+ `${pc32.dim("Category:")} ${node.category}`,
20183
+ `${pc32.dim("Node Type:")} ${node.nodeType}`,
20184
+ `${pc32.dim("Execution Kind:")} ${executionKindLabel(node.executionKind)}`,
20185
+ `${pc32.dim("Execution Strategy:")} ${node.executionBinding.strategy}`,
20186
+ `${pc32.dim("Tool Name:")} ${node.executionTokens.tool_name}`,
20187
+ `${pc32.dim("Output Types:")} ${node.outputTypes.join(", ")}`,
20188
+ `${pc32.dim("Required Bindings:")} ${node.requiredBindings.length > 0 ? node.requiredBindings.join(", ") : pc32.dim("(none)")}`
19339
20189
  ];
19340
20190
  if (node.description) {
19341
- lines.push("", pc30.dim(node.description));
20191
+ lines.push("", pc32.dim(node.description));
19342
20192
  }
19343
20193
  const inputKeys = Object.keys(node.executionTokens.input_template);
19344
20194
  if (inputKeys.length > 0) {
19345
- lines.push("", `${pc30.dim("Input fields:")} ${inputKeys.join(", ")}`);
20195
+ lines.push("", `${pc32.dim("Input fields:")} ${inputKeys.join(", ")}`);
19346
20196
  }
19347
20197
  console.log("");
19348
20198
  console.log(box3(lines));
@@ -19350,7 +20200,7 @@ function printCapabilityCard(node) {
19350
20200
  }
19351
20201
  async function runCapabilityPicker(opts) {
19352
20202
  printPaperclipCliBanner();
19353
- p21.intro(pc30.bold("CMS Capability Registry"));
20203
+ p21.intro(pc32.bold("CMS Capability Registry"));
19354
20204
  const access = getWorkflowAccess();
19355
20205
  if (access.state !== "ready") {
19356
20206
  p21.note(
@@ -19401,7 +20251,7 @@ async function runCapabilityPicker(opts) {
19401
20251
  options: [
19402
20252
  ...result.nodes.map((n) => ({
19403
20253
  value: n.slug,
19404
- label: `${familyBadge(n.family)} ` + pc30.bold(n.displayName) + " " + pc30.dim(n.slug),
20254
+ label: `${familyBadge(n.family)} ` + pc32.bold(n.displayName) + " " + pc32.dim(n.slug),
19405
20255
  hint: n.description ? n.description.slice(0, 55) : void 0
19406
20256
  })),
19407
20257
  { value: "__back_to_family", label: "\u2190 Back to family filter" }
@@ -19432,13 +20282,13 @@ async function runCapabilityPicker(opts) {
19432
20282
  const resolver = createMachineCapabilityResolver();
19433
20283
  const binding = await resolver.resolveCapability(selected.slug);
19434
20284
  if (binding) {
19435
- const statusColor3 = binding.allowed ? pc30.green : pc30.red;
20285
+ const statusColor3 = binding.allowed ? pc32.green : pc32.red;
19436
20286
  console.log("");
19437
20287
  console.log(box3([
19438
- `${pc30.bold("Machine Binding:")} ${selected.slug}`,
19439
- `${pc30.dim("Allowed:")} ${statusColor3(String(binding.allowed))}`,
19440
- `${pc30.dim("Reason:")} ${binding.reason ?? "\u2014"}`,
19441
- ...binding.machineConnectionId ? [`${pc30.dim("Connection:")} ${binding.machineConnectionId}`] : []
20288
+ `${pc32.bold("Machine Binding:")} ${selected.slug}`,
20289
+ `${pc32.dim("Allowed:")} ${statusColor3(String(binding.allowed))}`,
20290
+ `${pc32.dim("Reason:")} ${binding.reason ?? "\u2014"}`,
20291
+ ...binding.machineConnectionId ? [`${pc32.dim("Connection:")} ${binding.machineConnectionId}`] : []
19442
20292
  ]));
19443
20293
  console.log("");
19444
20294
  }
@@ -19465,7 +20315,7 @@ Examples:
19465
20315
  cap.command("list").description("List all CMS-backed runtime node capabilities").option("--family <family>", "Filter by family (video, image, slides, text, data, ops)").option("--json", "Output raw JSON for scripting").action(async (opts) => {
19466
20316
  const access = getWorkflowAccess();
19467
20317
  if (access.state !== "ready") {
19468
- console.error(pc30.red(`${access.reason}.`));
20318
+ console.error(pc32.red(`${access.reason}.`));
19469
20319
  process.exitCode = 1;
19470
20320
  return;
19471
20321
  }
@@ -19478,23 +20328,23 @@ Examples:
19478
20328
  return;
19479
20329
  }
19480
20330
  if (nodes.length === 0) {
19481
- console.error(pc30.yellow("No capabilities found" + (opts.family ? ` for family: ${opts.family}` : "") + "."));
19482
- console.error(pc30.dim("Valid families: " + CAPABILITY_FAMILIES.join(", ")));
20331
+ console.error(pc32.yellow("No capabilities found" + (opts.family ? ` for family: ${opts.family}` : "") + "."));
20332
+ console.error(pc32.dim("Valid families: " + CAPABILITY_FAMILIES.join(", ")));
19483
20333
  process.exitCode = 1;
19484
20334
  return;
19485
20335
  }
19486
20336
  printGroupedCapabilities(nodes);
19487
- console.log(pc30.dim(` Source: ${meta.source} \xB7 Fetched: ${meta.fetchedAt}`));
20337
+ console.log(pc32.dim(` Source: ${meta.source} \xB7 Fetched: ${meta.fetchedAt}`));
19488
20338
  console.log("");
19489
20339
  } catch (err) {
19490
- console.error(pc30.red("Failed to list capabilities: " + err.message));
20340
+ console.error(pc32.red("Failed to list capabilities: " + err.message));
19491
20341
  process.exitCode = 1;
19492
20342
  }
19493
20343
  });
19494
20344
  cap.command("inspect").description("Inspect a specific CMS capability node").argument("<slug>", "Capability slug (e.g. 'video-gen', 'text-gen')").option("--json", "Output raw JSON").action(async (slug, opts) => {
19495
20345
  const access = getWorkflowAccess();
19496
20346
  if (access.state !== "ready") {
19497
- console.error(pc30.red(`${access.reason}.`));
20347
+ console.error(pc32.red(`${access.reason}.`));
19498
20348
  process.exitCode = 1;
19499
20349
  return;
19500
20350
  }
@@ -19502,7 +20352,7 @@ Examples:
19502
20352
  try {
19503
20353
  const node = await registry.getCapability(slug);
19504
20354
  if (!node) {
19505
- console.error(pc30.red(`Unknown capability: "${slug}".`) + pc30.dim(" Run `growthub capability list` to browse."));
20355
+ console.error(pc32.red(`Unknown capability: "${slug}".`) + pc32.dim(" Run `growthub capability list` to browse."));
19506
20356
  process.exitCode = 1;
19507
20357
  return;
19508
20358
  }
@@ -19512,14 +20362,14 @@ Examples:
19512
20362
  }
19513
20363
  printCapabilityCard(node);
19514
20364
  } catch (err) {
19515
- console.error(pc30.red("Failed to inspect capability: " + err.message));
20365
+ console.error(pc32.red("Failed to inspect capability: " + err.message));
19516
20366
  process.exitCode = 1;
19517
20367
  }
19518
20368
  });
19519
20369
  cap.command("resolve").description("Resolve machine-scoped capability bindings for all capabilities").option("--json", "Output raw JSON").action(async (opts) => {
19520
20370
  const access = getWorkflowAccess();
19521
20371
  if (access.state !== "ready") {
19522
- console.error(pc30.red(`${access.reason}.`));
20372
+ console.error(pc32.red(`${access.reason}.`));
19523
20373
  process.exitCode = 1;
19524
20374
  return;
19525
20375
  }
@@ -19531,28 +20381,28 @@ Examples:
19531
20381
  return;
19532
20382
  }
19533
20383
  console.log("");
19534
- console.log(pc30.bold("Machine Capability Resolution"));
20384
+ console.log(pc32.bold("Machine Capability Resolution"));
19535
20385
  console.log(hr4());
19536
- console.log(` ${pc30.dim("Hostname:")} ${result.machineContext.hostname}`);
19537
- console.log(` ${pc30.dim("Instance:")} ${result.machineContext.instanceId}`);
19538
- console.log(` ${pc30.dim("Session:")} ${result.machineContext.hasActiveSession ? pc30.green("active") : pc30.red("none")}`);
20386
+ console.log(` ${pc32.dim("Hostname:")} ${result.machineContext.hostname}`);
20387
+ console.log(` ${pc32.dim("Instance:")} ${result.machineContext.instanceId}`);
20388
+ console.log(` ${pc32.dim("Session:")} ${result.machineContext.hasActiveSession ? pc32.green("active") : pc32.red("none")}`);
19539
20389
  if (result.machineContext.machineLabel) {
19540
- console.log(` ${pc30.dim("Machine:")} ${result.machineContext.machineLabel}`);
20390
+ console.log(` ${pc32.dim("Machine:")} ${result.machineContext.machineLabel}`);
19541
20391
  }
19542
- console.log(` ${pc30.dim("Entitlements:")} ${result.entitlements.length > 0 ? result.entitlements.join(", ") : pc30.dim("(none)")}`);
20392
+ console.log(` ${pc32.dim("Entitlements:")} ${result.entitlements.length > 0 ? result.entitlements.join(", ") : pc32.dim("(none)")}`);
19543
20393
  console.log(hr4());
19544
20394
  for (const binding of result.bindings) {
19545
- const statusColor3 = binding.allowed ? pc30.green : pc30.red;
20395
+ const statusColor3 = binding.allowed ? pc32.green : pc32.red;
19546
20396
  const statusIcon = binding.allowed ? "\u2713" : "\u2717";
19547
20397
  console.log(
19548
- ` ${statusColor3(statusIcon)} ${pc30.bold(binding.capabilitySlug)} ${pc30.dim(binding.reason ?? "")}`
20398
+ ` ${statusColor3(statusIcon)} ${pc32.bold(binding.capabilitySlug)} ${pc32.dim(binding.reason ?? "")}`
19549
20399
  );
19550
20400
  }
19551
20401
  console.log("");
19552
- console.log(pc30.dim(` Resolved at: ${result.resolvedAt}`));
20402
+ console.log(pc32.dim(` Resolved at: ${result.resolvedAt}`));
19553
20403
  console.log("");
19554
20404
  } catch (err) {
19555
- console.error(pc30.red("Failed to resolve capabilities: " + err.message));
20405
+ console.error(pc32.red("Failed to resolve capabilities: " + err.message));
19556
20406
  process.exitCode = 1;
19557
20407
  }
19558
20408
  });
@@ -19564,7 +20414,7 @@ init_hosted_client();
19564
20414
  import fs29 from "node:fs";
19565
20415
  import path38 from "node:path";
19566
20416
  import * as p22 from "@clack/prompts";
19567
- import pc32 from "picocolors";
20417
+ import pc34 from "picocolors";
19568
20418
 
19569
20419
  // src/runtime/dynamic-registry-pipeline/index.ts
19570
20420
  import { randomBytes as randomBytes6 } from "node:crypto";
@@ -19953,10 +20803,10 @@ function compileToHostedWorkflowConfig(pipeline, opts) {
19953
20803
  }
19954
20804
 
19955
20805
  // src/runtime/cms-node-contracts/presenter.ts
19956
- import pc31 from "picocolors";
20806
+ import pc33 from "picocolors";
19957
20807
  function renderInputLine(input) {
19958
- const required = input.required ? pc31.red("required") : pc31.green("optional");
19959
- return `${pc31.dim("\xB7")} ${input.label} ${pc31.dim(`(${input.type})`)} ${required}`;
20808
+ const required = input.required ? pc33.red("required") : pc33.green("optional");
20809
+ return `${pc33.dim("\xB7")} ${input.label} ${pc33.dim(`(${input.type})`)} ${required}`;
19960
20810
  }
19961
20811
  function countNodeAssets(bindings) {
19962
20812
  let count = 0;
@@ -19969,20 +20819,20 @@ function countNodeAssets(bindings) {
19969
20819
  }
19970
20820
  function renderContractCard(contract) {
19971
20821
  const lines = [
19972
- `${pc31.bold(contract.displayName)} ${pc31.dim(contract.slug)}`,
19973
- `${pc31.dim("Family:")} ${contract.family} ${pc31.dim("Execution:")} ${contract.executionStrategy}`,
19974
- `${pc31.dim("Kind:")} ${contract.executionKind} ${pc31.dim("Node Type:")} ${contract.nodeType}`,
19975
- `${pc31.dim("Bindings:")} ${contract.requiredBindings.length > 0 ? contract.requiredBindings.join(", ") : "none"}`,
19976
- `${pc31.dim("Outputs:")} ${contract.outputTypes.length > 0 ? contract.outputTypes.join(", ") : "none"}`
20822
+ `${pc33.bold(contract.displayName)} ${pc33.dim(contract.slug)}`,
20823
+ `${pc33.dim("Family:")} ${contract.family} ${pc33.dim("Execution:")} ${contract.executionStrategy}`,
20824
+ `${pc33.dim("Kind:")} ${contract.executionKind} ${pc33.dim("Node Type:")} ${contract.nodeType}`,
20825
+ `${pc33.dim("Bindings:")} ${contract.requiredBindings.length > 0 ? contract.requiredBindings.join(", ") : "none"}`,
20826
+ `${pc33.dim("Outputs:")} ${contract.outputTypes.length > 0 ? contract.outputTypes.join(", ") : "none"}`
19977
20827
  ];
19978
20828
  if (contract.inputs.length > 0) {
19979
- lines.push("", pc31.bold("Input Contract"));
20829
+ lines.push("", pc33.bold("Input Contract"));
19980
20830
  lines.push(...contract.inputs.map(renderInputLine));
19981
20831
  }
19982
20832
  if (contract.outputs.length > 0) {
19983
- lines.push("", pc31.bold("Output Contract"));
20833
+ lines.push("", pc33.bold("Output Contract"));
19984
20834
  lines.push(
19985
- ...contract.outputs.map((output) => `${pc31.dim("\xB7")} ${output.key} ${pc31.dim(`(${output.type})`)}`)
20835
+ ...contract.outputs.map((output) => `${pc33.dim("\xB7")} ${output.key} ${pc33.dim(`(${output.type})`)}`)
19986
20836
  );
19987
20837
  }
19988
20838
  return lines;
@@ -20039,33 +20889,33 @@ function buildPreExecutionSummary(input) {
20039
20889
  }
20040
20890
  function renderPreExecutionSummary(summary) {
20041
20891
  const lines = [
20042
- `${pc31.bold("Pre-Execution Contract Summary")} ${pc31.dim(summary.pipelineId)}`,
20043
- `${pc31.dim("Mode:")} ${summary.executionMode} ${pc31.dim("Nodes:")} ${summary.nodeCount}`,
20044
- `${pc31.dim("Compiled:")} ${summary.compiledConfig.nodes.length} nodes / ${summary.compiledConfig.edges.length} edges`,
20892
+ `${pc33.bold("Pre-Execution Contract Summary")} ${pc33.dim(summary.pipelineId)}`,
20893
+ `${pc33.dim("Mode:")} ${summary.executionMode} ${pc33.dim("Nodes:")} ${summary.nodeCount}`,
20894
+ `${pc33.dim("Compiled:")} ${summary.compiledConfig.nodes.length} nodes / ${summary.compiledConfig.edges.length} edges`,
20045
20895
  ""
20046
20896
  ];
20047
20897
  for (const [index51, node] of summary.nodes.entries()) {
20048
- const missing = node.requiredMissing.length > 0 ? pc31.red(`missing: ${node.requiredMissing.join(", ")}`) : pc31.green("ready");
20898
+ const missing = node.requiredMissing.length > 0 ? pc33.red(`missing: ${node.requiredMissing.join(", ")}`) : pc33.green("ready");
20049
20899
  const outputs = node.outputTypes.length > 0 ? node.outputTypes.join(", ") : "none";
20050
20900
  lines.push(
20051
- `${pc31.dim(`${index51 + 1}.`)} ${pc31.bold(node.slug)} ${pc31.dim(node.nodeId)} \xB7 bindings=${node.bindingCount} \xB7 assets=${node.assetCount} \xB7 outputs=${outputs} \xB7 ${missing}`
20901
+ `${pc33.dim(`${index51 + 1}.`)} ${pc33.bold(node.slug)} ${pc33.dim(node.nodeId)} \xB7 bindings=${node.bindingCount} \xB7 assets=${node.assetCount} \xB7 outputs=${outputs} \xB7 ${missing}`
20052
20902
  );
20053
20903
  }
20054
20904
  if (summary.warnings.length > 0) {
20055
- lines.push("", pc31.yellow("Warnings"));
20056
- lines.push(...summary.warnings.map((warning) => `${pc31.dim("\xB7")} ${warning}`));
20905
+ lines.push("", pc33.yellow("Warnings"));
20906
+ lines.push(...summary.warnings.map((warning) => `${pc33.dim("\xB7")} ${warning}`));
20057
20907
  }
20058
20908
  return lines;
20059
20909
  }
20060
20910
  function renderPreSaveReview(input) {
20061
20911
  const lines = [
20062
- `${pc31.bold("Pre-Save Workflow Review")} ${pc31.dim(input.workflowName)}`,
20063
- `${pc31.dim("Pipeline:")} ${input.summary.pipelineId}`,
20064
- `${pc31.dim("Mode:")} ${input.summary.executionMode}`,
20065
- `${pc31.dim("Compiled:")} ${input.summary.compiledConfig.nodes.length} nodes / ${input.summary.compiledConfig.edges.length} edges`
20912
+ `${pc33.bold("Pre-Save Workflow Review")} ${pc33.dim(input.workflowName)}`,
20913
+ `${pc33.dim("Pipeline:")} ${input.summary.pipelineId}`,
20914
+ `${pc33.dim("Mode:")} ${input.summary.executionMode}`,
20915
+ `${pc33.dim("Compiled:")} ${input.summary.compiledConfig.nodes.length} nodes / ${input.summary.compiledConfig.edges.length} edges`
20066
20916
  ];
20067
20917
  if (input.summary.warnings.length > 0) {
20068
- lines.push("", pc31.yellow(`Warnings: ${input.summary.warnings.length}`));
20918
+ lines.push("", pc33.yellow(`Warnings: ${input.summary.warnings.length}`));
20069
20919
  }
20070
20920
  return lines;
20071
20921
  }
@@ -20276,9 +21126,9 @@ function createNativeIntelligenceBackend(config) {
20276
21126
  throw lastError ?? new NativeIntelligenceBackendError(502, "Model backend returned no response.");
20277
21127
  }
20278
21128
  const latencyMs = Date.now() - startMs;
20279
- const text64 = extractCompletionText(result);
21129
+ const text65 = extractCompletionText(result);
20280
21130
  return {
20281
- text: text64,
21131
+ text: text65,
20282
21132
  usage: result.usage ? {
20283
21133
  promptTokens: result.usage.prompt_tokens ?? 0,
20284
21134
  completionTokens: result.usage.completion_tokens ?? 0,
@@ -20533,9 +21383,9 @@ function buildSummarizerPrompt(input) {
20533
21383
  }
20534
21384
  return sections.join("\n");
20535
21385
  }
20536
- function parseJsonSafe(text64) {
21386
+ function parseJsonSafe(text65) {
20537
21387
  try {
20538
- const trimmed = text64.trim();
21388
+ const trimmed = text65.trim();
20539
21389
  const jsonStart = trimmed.indexOf("{");
20540
21390
  const jsonEnd = trimmed.lastIndexOf("}");
20541
21391
  if (jsonStart >= 0 && jsonEnd > jsonStart) {
@@ -20787,9 +21637,9 @@ function validateAction(action) {
20787
21637
  }
20788
21638
  return "kept";
20789
21639
  }
20790
- function parseJsonSafe2(text64) {
21640
+ function parseJsonSafe2(text65) {
20791
21641
  try {
20792
- const trimmed = text64.trim();
21642
+ const trimmed = text65.trim();
20793
21643
  const jsonStart = trimmed.indexOf("{");
20794
21644
  const jsonEnd = trimmed.lastIndexOf("}");
20795
21645
  if (jsonStart >= 0 && jsonEnd > jsonStart) {
@@ -21030,9 +21880,9 @@ function validateStrategy(strategy) {
21030
21880
  }
21031
21881
  return "synthesize-new";
21032
21882
  }
21033
- function parseJsonSafe3(text64) {
21883
+ function parseJsonSafe3(text65) {
21034
21884
  try {
21035
- const trimmed = text64.trim();
21885
+ const trimmed = text65.trim();
21036
21886
  const jsonStart = trimmed.indexOf("{");
21037
21887
  const jsonEnd = trimmed.lastIndexOf("}");
21038
21888
  if (jsonStart >= 0 && jsonEnd > jsonStart) {
@@ -21278,9 +22128,9 @@ function validatePlanningResult(raw, input) {
21278
22128
  warnings
21279
22129
  };
21280
22130
  }
21281
- function parseJsonSafe4(text64) {
22131
+ function parseJsonSafe4(text65) {
21282
22132
  try {
21283
- const trimmed = text64.trim();
22133
+ const trimmed = text65.trim();
21284
22134
  const jsonStart = trimmed.indexOf("{");
21285
22135
  const jsonEnd = trimmed.lastIndexOf("}");
21286
22136
  if (jsonStart >= 0 && jsonEnd > jsonStart) {
@@ -21350,25 +22200,25 @@ function createNativeIntelligenceProvider(configOverride) {
21350
22200
  // src/commands/pipeline.ts
21351
22201
  init_banner();
21352
22202
  function hr5(width = 72) {
21353
- return pc32.dim("\u2500".repeat(width));
22203
+ return pc34.dim("\u2500".repeat(width));
21354
22204
  }
21355
- function stripAnsi4(str) {
22205
+ function stripAnsi5(str) {
21356
22206
  return str.replace(/\x1B\[[0-9;]*m/g, "");
21357
22207
  }
21358
22208
  function box4(lines) {
21359
22209
  const padded = lines.map((l) => " " + l);
21360
- const width = Math.max(...padded.map((l) => stripAnsi4(l).length)) + 4;
21361
- const top = pc32.dim("\u250C" + "\u2500".repeat(width) + "\u2510");
21362
- const bottom = pc32.dim("\u2514" + "\u2500".repeat(width) + "\u2518");
22210
+ const width = Math.max(...padded.map((l) => stripAnsi5(l).length)) + 4;
22211
+ const top = pc34.dim("\u250C" + "\u2500".repeat(width) + "\u2510");
22212
+ const bottom = pc34.dim("\u2514" + "\u2500".repeat(width) + "\u2518");
21363
22213
  const body = padded.map((l) => {
21364
- const pad = width - stripAnsi4(l).length;
21365
- return pc32.dim("\u2502") + l + " ".repeat(pad) + pc32.dim("\u2502");
22214
+ const pad2 = width - stripAnsi5(l).length;
22215
+ return pc34.dim("\u2502") + l + " ".repeat(pad2) + pc34.dim("\u2502");
21366
22216
  });
21367
22217
  return [top, ...body, bottom].join("\n");
21368
22218
  }
21369
22219
  async function runPipelineAssembler(opts) {
21370
22220
  printPaperclipCliBanner();
21371
- p22.intro(pc32.bold("Dynamic Registry Pipeline Assembler"));
22221
+ p22.intro(pc34.bold("Dynamic Registry Pipeline Assembler"));
21372
22222
  p22.note(
21373
22223
  [
21374
22224
  "Dynamic pipeline creation flow:",
@@ -21417,7 +22267,7 @@ async function runPipelineAssembler(opts) {
21417
22267
  capabilities = result.nodes;
21418
22268
  capabilitiesSpinner.stop(`Loaded ${capabilities.length} capabilities.`);
21419
22269
  } catch (err) {
21420
- capabilitiesSpinner.stop(pc32.red("Failed to load capabilities."));
22270
+ capabilitiesSpinner.stop(pc34.red("Failed to load capabilities."));
21421
22271
  p22.log.error("Failed to load capabilities: " + err.message);
21422
22272
  return "done";
21423
22273
  }
@@ -21459,7 +22309,7 @@ async function runPipelineAssembler(opts) {
21459
22309
  options: [
21460
22310
  ...capabilities.map((c) => ({
21461
22311
  value: c.slug,
21462
- label: `${pc32.bold(c.displayName)} ${pc32.dim(c.slug)}`,
22312
+ label: `${pc34.bold(c.displayName)} ${pc34.dim(c.slug)}`,
21463
22313
  hint: `${c.family} \xB7 ${c.executionKind}`
21464
22314
  })),
21465
22315
  { value: "__back", label: "\u2190 Back" }
@@ -21508,19 +22358,19 @@ async function runPipelineAssembler(opts) {
21508
22358
  }
21509
22359
  const normalizedBindings = normalizeNodeBindings(bindings, cap);
21510
22360
  const nodeId = builder.addNode(capChoice, normalizedBindings.bindings, upstreamNodeIds);
21511
- p22.log.success(`Added node ${pc32.bold(cap.displayName)} (${pc32.dim(nodeId)})`);
22361
+ p22.log.success(`Added node ${pc34.bold(cap.displayName)} (${pc34.dim(nodeId)})`);
21512
22362
  continue;
21513
22363
  }
21514
22364
  if (action === "preview") {
21515
22365
  const pipeline = builder.build();
21516
22366
  console.log("");
21517
22367
  console.log(box4([
21518
- `${pc32.bold("Pipeline:")} ${pipeline.pipelineId}`,
21519
- `${pc32.dim("Mode:")} ${pipeline.executionMode} ${pc32.dim("Nodes:")} ${pipeline.nodes.length}`,
22368
+ `${pc34.bold("Pipeline:")} ${pipeline.pipelineId}`,
22369
+ `${pc34.dim("Mode:")} ${pipeline.executionMode} ${pc34.dim("Nodes:")} ${pipeline.nodes.length}`,
21520
22370
  "",
21521
22371
  ...pipeline.nodes.map((n, i) => {
21522
- const upstream = n.upstreamNodeIds?.length ? pc32.dim(` \u2190 ${n.upstreamNodeIds.join(", ")}`) : "";
21523
- return `${pc32.dim(String(i + 1) + ".")} ${pc32.bold(n.slug)} ${pc32.dim(n.id)}${upstream}`;
22372
+ const upstream = n.upstreamNodeIds?.length ? pc34.dim(` \u2190 ${n.upstreamNodeIds.join(", ")}`) : "";
22373
+ return `${pc34.dim(String(i + 1) + ".")} ${pc34.bold(n.slug)} ${pc34.dim(n.id)}${upstream}`;
21524
22374
  })
21525
22375
  ]));
21526
22376
  console.log("");
@@ -21535,7 +22385,7 @@ async function runPipelineAssembler(opts) {
21535
22385
  p22.log.error("Pipeline validation failed.");
21536
22386
  }
21537
22387
  for (const issue of result.issues) {
21538
- const prefix = issue.severity === "error" ? pc32.red("ERROR") : pc32.yellow("WARN");
22388
+ const prefix = issue.severity === "error" ? pc34.red("ERROR") : pc34.yellow("WARN");
21539
22389
  const nodeRef = issue.nodeId ? ` [${issue.nodeId}]` : "";
21540
22390
  console.log(` ${prefix}${nodeRef}: ${issue.message}`);
21541
22391
  }
@@ -21592,7 +22442,7 @@ async function runPipelineAssembler(opts) {
21592
22442
  throw new Error("Hosted workflow save returned no workflow id.");
21593
22443
  }
21594
22444
  p22.log.success(
21595
- `Saved to workflow registry as ${pc32.bold(workflowName)} (${pc32.dim(saveResult.workflowId)} \xB7 v${saveResult.version}).`
22445
+ `Saved to workflow registry as ${pc34.bold(workflowName)} (${pc34.dim(saveResult.workflowId)} \xB7 v${saveResult.version}).`
21596
22446
  );
21597
22447
  } catch (err) {
21598
22448
  if (err instanceof HostedEndpointUnavailableError) {
@@ -21608,7 +22458,7 @@ async function runPipelineAssembler(opts) {
21608
22458
  if (!validation.valid) {
21609
22459
  p22.log.error("Pipeline is not valid. Fix errors before executing.");
21610
22460
  for (const issue of validation.issues.filter((i) => i.severity === "error")) {
21611
- console.log(` ${pc32.red("ERROR")}: ${issue.message}`);
22461
+ console.log(` ${pc34.red("ERROR")}: ${issue.message}`);
21612
22462
  }
21613
22463
  continue;
21614
22464
  }
@@ -21638,7 +22488,7 @@ async function runPipelineAssembler(opts) {
21638
22488
  const executionClient = createHostedExecutionClient();
21639
22489
  const pipeline2 = builder.build();
21640
22490
  const pkg = await builder.package();
21641
- p22.log.info(`Executing pipeline ${pc32.bold(pipeline2.pipelineId)} (${pkg.executionRoute})...`);
22491
+ p22.log.info(`Executing pipeline ${pc34.bold(pipeline2.pipelineId)} (${pkg.executionRoute})...`);
21642
22492
  const result = await executionClient.executeWorkflow({
21643
22493
  pipelineId: pipeline2.pipelineId,
21644
22494
  threadId: pipeline2.threadId,
@@ -21651,7 +22501,7 @@ async function runPipelineAssembler(opts) {
21651
22501
  executionMode: pipeline2.executionMode,
21652
22502
  metadata: pipeline2.metadata
21653
22503
  });
21654
- p22.log.success(`Execution ${pc32.bold(result.executionId)}: ${result.status}`);
22504
+ p22.log.success(`Execution ${pc34.bold(result.executionId)}: ${result.status}`);
21655
22505
  const artifactStore = createArtifactStore();
21656
22506
  for (const artRef of result.artifacts) {
21657
22507
  const nodeResult = result.nodeResults[artRef.nodeId];
@@ -21696,7 +22546,7 @@ function renderExecutionProgress(completed, total, detail) {
21696
22546
  const percent = total <= 0 ? 0 : Math.round(safeCompleted / total * 100);
21697
22547
  const filled = Math.max(0, Math.min(width, Math.round(percent / 100 * width)));
21698
22548
  const bar = `${"=".repeat(filled)}${"-".repeat(width - filled)}`;
21699
- const line = `\r${pc32.cyan("Workflow run")} ${pc32.dim("[")}${pc32.green(bar)}${pc32.dim("]")} ${String(percent).padStart(3)}% ${pc32.dim(detail)}`;
22549
+ const line = `\r${pc34.cyan("Workflow run")} ${pc34.dim("[")}${pc34.green(bar)}${pc34.dim("]")} ${String(percent).padStart(3)}% ${pc34.dim(detail)}`;
21700
22550
  process.stdout.write(line);
21701
22551
  if (safeCompleted >= total) {
21702
22552
  process.stdout.write("\n");
@@ -21769,50 +22619,50 @@ async function executeHostedPipeline(pipeline, opts) {
21769
22619
  return;
21770
22620
  }
21771
22621
  console.log("");
21772
- console.log(pc32.bold("Pipeline Execution Result"));
22622
+ console.log(pc34.bold("Pipeline Execution Result"));
21773
22623
  console.log(hr5());
21774
- console.log(` ${pc32.dim("Execution ID:")} ${result.executionId}`);
21775
- if (result.threadId) console.log(` ${pc32.dim("Thread ID:")} ${result.threadId}`);
21776
- console.log(` ${pc32.dim("Status:")} ${result.status === "succeeded" ? pc32.green(result.status) : pc32.red(result.status)}`);
21777
- if (result.startedAt) console.log(` ${pc32.dim("Started:")} ${result.startedAt}`);
21778
- if (result.completedAt) console.log(` ${pc32.dim("Completed:")} ${result.completedAt}`);
22624
+ console.log(` ${pc34.dim("Execution ID:")} ${result.executionId}`);
22625
+ if (result.threadId) console.log(` ${pc34.dim("Thread ID:")} ${result.threadId}`);
22626
+ console.log(` ${pc34.dim("Status:")} ${result.status === "succeeded" ? pc34.green(result.status) : pc34.red(result.status)}`);
22627
+ if (result.startedAt) console.log(` ${pc34.dim("Started:")} ${result.startedAt}`);
22628
+ if (result.completedAt) console.log(` ${pc34.dim("Completed:")} ${result.completedAt}`);
21779
22629
  console.log(hr5());
21780
22630
  for (const [nodeId, nodeResult] of Object.entries(result.nodeResults)) {
21781
- const statusColor3 = nodeResult.status === "succeeded" ? pc32.green : pc32.red;
21782
- console.log(` ${statusColor3(nodeResult.status)} ${pc32.bold(nodeResult.slug)} (${pc32.dim(nodeId)})`);
22631
+ const statusColor3 = nodeResult.status === "succeeded" ? pc34.green : pc34.red;
22632
+ console.log(` ${statusColor3(nodeResult.status)} ${pc34.bold(nodeResult.slug)} (${pc34.dim(nodeId)})`);
21783
22633
  if (nodeResult.error) {
21784
- console.log(` ${pc32.red(nodeResult.error)}`);
22634
+ console.log(` ${pc34.red(nodeResult.error)}`);
21785
22635
  }
21786
22636
  }
21787
22637
  if (result.artifacts.length > 0) {
21788
22638
  console.log("");
21789
- console.log(pc32.bold(" Artifacts:"));
22639
+ console.log(pc34.bold(" Artifacts:"));
21790
22640
  for (const art of result.artifacts) {
21791
- console.log(` ${pc32.dim("\xB7")} ${art.artifactType} (${art.artifactId})`);
22641
+ console.log(` ${pc34.dim("\xB7")} ${art.artifactType} (${art.artifactId})`);
21792
22642
  }
21793
22643
  }
21794
22644
  if (result.summary) {
21795
22645
  console.log("");
21796
- console.log(pc32.bold(" Summary:"));
21797
- if (result.summary.outputText) console.log(` ${pc32.dim("\xB7")} ${result.summary.outputText}`);
21798
- if (typeof result.summary.imageCount === "number") console.log(` ${pc32.dim("\xB7")} images: ${result.summary.imageCount}`);
21799
- if (typeof result.summary.slideCount === "number") console.log(` ${pc32.dim("\xB7")} slides: ${result.summary.slideCount}`);
21800
- if (typeof result.summary.videoCount === "number") console.log(` ${pc32.dim("\xB7")} videos: ${result.summary.videoCount}`);
21801
- if (result.summary.workflowRunId) console.log(` ${pc32.dim("\xB7")} workflow_run_id: ${result.summary.workflowRunId}`);
21802
- if (result.summary.keyboardShortcutHint) console.log(` ${pc32.dim("\xB7")} ${result.summary.keyboardShortcutHint}`);
22646
+ console.log(pc34.bold(" Summary:"));
22647
+ if (result.summary.outputText) console.log(` ${pc34.dim("\xB7")} ${result.summary.outputText}`);
22648
+ if (typeof result.summary.imageCount === "number") console.log(` ${pc34.dim("\xB7")} images: ${result.summary.imageCount}`);
22649
+ if (typeof result.summary.slideCount === "number") console.log(` ${pc34.dim("\xB7")} slides: ${result.summary.slideCount}`);
22650
+ if (typeof result.summary.videoCount === "number") console.log(` ${pc34.dim("\xB7")} videos: ${result.summary.videoCount}`);
22651
+ if (result.summary.workflowRunId) console.log(` ${pc34.dim("\xB7")} workflow_run_id: ${result.summary.workflowRunId}`);
22652
+ if (result.summary.keyboardShortcutHint) console.log(` ${pc34.dim("\xB7")} ${result.summary.keyboardShortcutHint}`);
21803
22653
  }
21804
22654
  try {
21805
22655
  const credits = await fetchHostedCredits(session);
21806
22656
  if (credits) {
21807
22657
  console.log("");
21808
- console.log(pc32.bold(" Credits:"));
21809
- console.log(` ${pc32.dim("\xB7")} available: $${credits.totalAvailable.toFixed(2)}`);
21810
- console.log(` ${pc32.dim("\xB7")} used this period: $${credits.creditsUsedThisPeriod.toFixed(2)} / $${credits.creditsPerMonth.toFixed(2)}`);
22658
+ console.log(pc34.bold(" Credits:"));
22659
+ console.log(` ${pc34.dim("\xB7")} available: $${credits.totalAvailable.toFixed(2)}`);
22660
+ console.log(` ${pc34.dim("\xB7")} used this period: $${credits.creditsUsedThisPeriod.toFixed(2)} / $${credits.creditsPerMonth.toFixed(2)}`);
21811
22661
  }
21812
22662
  } catch (err) {
21813
22663
  if (err instanceof HostedEndpointUnavailableError) {
21814
22664
  console.log("");
21815
- console.log(pc32.yellow(" Credits unavailable on this hosted surface."));
22665
+ console.log(pc34.yellow(" Credits unavailable on this hosted surface."));
21816
22666
  } else {
21817
22667
  throw err;
21818
22668
  }
@@ -21870,31 +22720,31 @@ async function renderIntelligenceSummary(pipeline, capabilities, phase) {
21870
22720
  };
21871
22721
  const result = await provider.summarizeExecution(input);
21872
22722
  const lines = [
21873
- `${pc32.bold("Intelligence Summary")} ${pc32.dim(result.title)}`,
22723
+ `${pc34.bold("Intelligence Summary")} ${pc34.dim(result.title)}`,
21874
22724
  result.explanation
21875
22725
  ];
21876
22726
  if (result.runtimeModeNote) {
21877
- lines.push(`${pc32.dim("Runtime:")} ${result.runtimeModeNote}`);
22727
+ lines.push(`${pc34.dim("Runtime:")} ${result.runtimeModeNote}`);
21878
22728
  }
21879
22729
  if (result.outputExpectation) {
21880
- lines.push(`${pc32.dim("Expected:")} ${result.outputExpectation}`);
22730
+ lines.push(`${pc34.dim("Expected:")} ${result.outputExpectation}`);
21881
22731
  }
21882
22732
  if (result.missingBindingGuidance.length > 0) {
21883
- lines.push("", pc32.yellow("Missing Binding Guidance"));
22733
+ lines.push("", pc34.yellow("Missing Binding Guidance"));
21884
22734
  for (const guidance of result.missingBindingGuidance) {
21885
- lines.push(` ${pc32.dim("\xB7")} ${guidance}`);
22735
+ lines.push(` ${pc34.dim("\xB7")} ${guidance}`);
21886
22736
  }
21887
22737
  }
21888
22738
  if (result.costLatencyCautions.length > 0) {
21889
- lines.push("", pc32.yellow("Cost/Latency Notes"));
22739
+ lines.push("", pc34.yellow("Cost/Latency Notes"));
21890
22740
  for (const caution of result.costLatencyCautions) {
21891
- lines.push(` ${pc32.dim("\xB7")} ${caution}`);
22741
+ lines.push(` ${pc34.dim("\xB7")} ${caution}`);
21892
22742
  }
21893
22743
  }
21894
22744
  if (result.warnings.length > 0) {
21895
- lines.push("", pc32.yellow("Warnings"));
22745
+ lines.push("", pc34.yellow("Warnings"));
21896
22746
  for (const warning of result.warnings) {
21897
- lines.push(` ${pc32.dim("\xB7")} ${warning}`);
22747
+ lines.push(` ${pc34.dim("\xB7")} ${warning}`);
21898
22748
  }
21899
22749
  }
21900
22750
  return lines;
@@ -21919,7 +22769,7 @@ Examples:
21919
22769
  pipe.command("validate").description("Validate a pipeline from a JSON file or inline JSON").argument("<file-or-json>", "Path to pipeline JSON file or inline JSON string").option("--json", "Output raw JSON").action(async (input, opts) => {
21920
22770
  const access = getWorkflowAccess();
21921
22771
  if (access.state !== "ready") {
21922
- console.error(pc32.red(`${access.reason}.`));
22772
+ console.error(pc34.red(`${access.reason}.`));
21923
22773
  process.exitCode = 1;
21924
22774
  return;
21925
22775
  }
@@ -21939,25 +22789,25 @@ Examples:
21939
22789
  return;
21940
22790
  }
21941
22791
  if (result.valid) {
21942
- console.log(pc32.green(pc32.bold("Pipeline is valid.")));
22792
+ console.log(pc34.green(pc34.bold("Pipeline is valid.")));
21943
22793
  } else {
21944
- console.log(pc32.red(pc32.bold("Pipeline validation failed.")));
22794
+ console.log(pc34.red(pc34.bold("Pipeline validation failed.")));
21945
22795
  }
21946
22796
  for (const issue of result.issues) {
21947
- const prefix = issue.severity === "error" ? pc32.red(" ERROR") : pc32.yellow(" WARN");
22797
+ const prefix = issue.severity === "error" ? pc34.red(" ERROR") : pc34.yellow(" WARN");
21948
22798
  const nodeRef = issue.nodeId ? ` [${issue.nodeId}]` : "";
21949
22799
  console.log(`${prefix}${nodeRef}: ${issue.message}`);
21950
22800
  }
21951
22801
  if (!result.valid) process.exitCode = 1;
21952
22802
  } catch (err) {
21953
- console.error(pc32.red("Validation failed: " + err.message));
22803
+ console.error(pc34.red("Validation failed: " + err.message));
21954
22804
  process.exitCode = 1;
21955
22805
  }
21956
22806
  });
21957
22807
  pipe.command("execute").description("Execute a pipeline from a JSON file or inline JSON").argument("<file-or-json>", "Path to pipeline JSON file or inline JSON string").option("--json", "Output raw JSON").action(async (input, opts) => {
21958
22808
  const access = getWorkflowAccess();
21959
22809
  if (access.state !== "ready") {
21960
- console.error(pc32.red(`${access.reason}.`));
22810
+ console.error(pc34.red(`${access.reason}.`));
21961
22811
  process.exitCode = 1;
21962
22812
  return;
21963
22813
  }
@@ -22027,45 +22877,45 @@ Examples:
22027
22877
  return;
22028
22878
  }
22029
22879
  console.log("");
22030
- console.log(pc32.bold("Pipeline Execution Result"));
22880
+ console.log(pc34.bold("Pipeline Execution Result"));
22031
22881
  console.log(hr5());
22032
- console.log(` ${pc32.dim("Execution ID:")} ${result.executionId}`);
22033
- if (result.threadId) console.log(` ${pc32.dim("Thread ID:")} ${result.threadId}`);
22034
- console.log(` ${pc32.dim("Status:")} ${result.status === "succeeded" ? pc32.green(result.status) : pc32.red(result.status)}`);
22035
- if (result.startedAt) console.log(` ${pc32.dim("Started:")} ${result.startedAt}`);
22036
- if (result.completedAt) console.log(` ${pc32.dim("Completed:")} ${result.completedAt}`);
22882
+ console.log(` ${pc34.dim("Execution ID:")} ${result.executionId}`);
22883
+ if (result.threadId) console.log(` ${pc34.dim("Thread ID:")} ${result.threadId}`);
22884
+ console.log(` ${pc34.dim("Status:")} ${result.status === "succeeded" ? pc34.green(result.status) : pc34.red(result.status)}`);
22885
+ if (result.startedAt) console.log(` ${pc34.dim("Started:")} ${result.startedAt}`);
22886
+ if (result.completedAt) console.log(` ${pc34.dim("Completed:")} ${result.completedAt}`);
22037
22887
  console.log(hr5());
22038
22888
  for (const [nodeId, nodeResult] of Object.entries(result.nodeResults)) {
22039
- const statusColor3 = nodeResult.status === "succeeded" ? pc32.green : pc32.red;
22040
- console.log(` ${statusColor3(nodeResult.status)} ${pc32.bold(nodeResult.slug)} (${pc32.dim(nodeId)})`);
22889
+ const statusColor3 = nodeResult.status === "succeeded" ? pc34.green : pc34.red;
22890
+ console.log(` ${statusColor3(nodeResult.status)} ${pc34.bold(nodeResult.slug)} (${pc34.dim(nodeId)})`);
22041
22891
  if (nodeResult.error) {
22042
- console.log(` ${pc32.red(nodeResult.error)}`);
22892
+ console.log(` ${pc34.red(nodeResult.error)}`);
22043
22893
  }
22044
22894
  }
22045
22895
  if (result.artifacts.length > 0) {
22046
22896
  console.log("");
22047
- console.log(pc32.bold(" Artifacts:"));
22897
+ console.log(pc34.bold(" Artifacts:"));
22048
22898
  for (const art of result.artifacts) {
22049
- console.log(` ${pc32.dim("\xB7")} ${art.artifactType} (${art.artifactId})`);
22899
+ console.log(` ${pc34.dim("\xB7")} ${art.artifactType} (${art.artifactId})`);
22050
22900
  }
22051
22901
  }
22052
22902
  if (result.summary) {
22053
22903
  console.log("");
22054
- console.log(pc32.bold(" Summary:"));
22055
- if (result.summary.outputText) console.log(` ${pc32.dim("\xB7")} ${result.summary.outputText}`);
22056
- if (typeof result.summary.imageCount === "number") console.log(` ${pc32.dim("\xB7")} images: ${result.summary.imageCount}`);
22057
- if (typeof result.summary.slideCount === "number") console.log(` ${pc32.dim("\xB7")} slides: ${result.summary.slideCount}`);
22058
- if (typeof result.summary.videoCount === "number") console.log(` ${pc32.dim("\xB7")} videos: ${result.summary.videoCount}`);
22059
- if (result.summary.workflowRunId) console.log(` ${pc32.dim("\xB7")} workflow_run_id: ${result.summary.workflowRunId}`);
22060
- if (result.summary.keyboardShortcutHint) console.log(` ${pc32.dim("\xB7")} ${result.summary.keyboardShortcutHint}`);
22904
+ console.log(pc34.bold(" Summary:"));
22905
+ if (result.summary.outputText) console.log(` ${pc34.dim("\xB7")} ${result.summary.outputText}`);
22906
+ if (typeof result.summary.imageCount === "number") console.log(` ${pc34.dim("\xB7")} images: ${result.summary.imageCount}`);
22907
+ if (typeof result.summary.slideCount === "number") console.log(` ${pc34.dim("\xB7")} slides: ${result.summary.slideCount}`);
22908
+ if (typeof result.summary.videoCount === "number") console.log(` ${pc34.dim("\xB7")} videos: ${result.summary.videoCount}`);
22909
+ if (result.summary.workflowRunId) console.log(` ${pc34.dim("\xB7")} workflow_run_id: ${result.summary.workflowRunId}`);
22910
+ if (result.summary.keyboardShortcutHint) console.log(` ${pc34.dim("\xB7")} ${result.summary.keyboardShortcutHint}`);
22061
22911
  }
22062
22912
  try {
22063
22913
  const credits = await fetchHostedCredits(session);
22064
22914
  if (credits) {
22065
22915
  console.log("");
22066
- console.log(pc32.bold(" Credits:"));
22067
- console.log(` ${pc32.dim("\xB7")} available: $${credits.totalAvailable.toFixed(2)}`);
22068
- console.log(` ${pc32.dim("\xB7")} used this period: $${credits.creditsUsedThisPeriod.toFixed(2)} / $${credits.creditsPerMonth.toFixed(2)}`);
22916
+ console.log(pc34.bold(" Credits:"));
22917
+ console.log(` ${pc34.dim("\xB7")} available: $${credits.totalAvailable.toFixed(2)}`);
22918
+ console.log(` ${pc34.dim("\xB7")} used this period: $${credits.creditsUsedThisPeriod.toFixed(2)} / $${credits.creditsPerMonth.toFixed(2)}`);
22069
22919
  }
22070
22920
  } catch (err) {
22071
22921
  if (!(err instanceof HostedEndpointUnavailableError)) {
@@ -22087,24 +22937,24 @@ Examples:
22087
22937
  }
22088
22938
  console.log("");
22089
22939
  } catch (err) {
22090
- console.error(pc32.red("Execution failed: " + err.message));
22940
+ console.error(pc34.red("Execution failed: " + err.message));
22091
22941
  process.exitCode = 1;
22092
22942
  }
22093
22943
  });
22094
22944
  }
22095
22945
 
22096
22946
  // src/commands/artifact.ts
22097
- import pc33 from "picocolors";
22947
+ import pc35 from "picocolors";
22098
22948
  function hr6(width = 72) {
22099
- return pc33.dim("\u2500".repeat(width));
22949
+ return pc35.dim("\u2500".repeat(width));
22100
22950
  }
22101
22951
  var ARTIFACT_TYPE_CONFIG = {
22102
- video: { color: pc33.magenta, emoji: "\u{1F3AC}" },
22103
- image: { color: pc33.cyan, emoji: "\u{1F5BC}\uFE0F " },
22104
- slides: { color: pc33.yellow, emoji: "\u{1F4CA}" },
22105
- text: { color: pc33.green, emoji: "\u{1F4DD}" },
22106
- report: { color: pc33.blue, emoji: "\u{1F4CB}" },
22107
- pipeline: { color: pc33.red, emoji: "\u{1F517}" }
22952
+ video: { color: pc35.magenta, emoji: "\u{1F3AC}" },
22953
+ image: { color: pc35.cyan, emoji: "\u{1F5BC}\uFE0F " },
22954
+ slides: { color: pc35.yellow, emoji: "\u{1F4CA}" },
22955
+ text: { color: pc35.green, emoji: "\u{1F4DD}" },
22956
+ report: { color: pc35.blue, emoji: "\u{1F4CB}" },
22957
+ pipeline: { color: pc35.red, emoji: "\u{1F517}" }
22108
22958
  };
22109
22959
  function artifactTypeBadge(type) {
22110
22960
  const cfg = ARTIFACT_TYPE_CONFIG[type];
@@ -22112,21 +22962,21 @@ function artifactTypeBadge(type) {
22112
22962
  return cfg.color(`${cfg.emoji} ${type}`);
22113
22963
  }
22114
22964
  function statusColor(status) {
22115
- if (status === "ready") return pc33.green(status);
22116
- if (status === "generating" || status === "pending") return pc33.yellow(status);
22117
- if (status === "failed") return pc33.red(status);
22118
- if (status === "archived") return pc33.dim(status);
22965
+ if (status === "ready") return pc35.green(status);
22966
+ if (status === "generating" || status === "pending") return pc35.yellow(status);
22967
+ if (status === "failed") return pc35.red(status);
22968
+ if (status === "archived") return pc35.dim(status);
22119
22969
  return status;
22120
22970
  }
22121
22971
  function printArtifactTable(artifacts) {
22122
22972
  console.log("");
22123
22973
  console.log(
22124
- pc33.bold("Pipeline Artifacts") + pc33.dim(` ${artifacts.length} artifact${artifacts.length !== 1 ? "s" : ""}`)
22974
+ pc35.bold("Pipeline Artifacts") + pc35.dim(` ${artifacts.length} artifact${artifacts.length !== 1 ? "s" : ""}`)
22125
22975
  );
22126
22976
  console.log(hr6());
22127
22977
  if (artifacts.length === 0) {
22128
- console.log(pc33.dim(" No artifacts found."));
22129
- console.log(pc33.dim(" Run `growthub pipeline execute` to produce artifacts."));
22978
+ console.log(pc35.dim(" No artifacts found."));
22979
+ console.log(pc35.dim(" Run `growthub pipeline execute` to produce artifacts."));
22130
22980
  console.log("");
22131
22981
  return;
22132
22982
  }
@@ -22134,25 +22984,25 @@ function printArtifactTable(artifacts) {
22134
22984
  const badge2 = artifactTypeBadge(art.artifactType);
22135
22985
  const status = statusColor(art.status);
22136
22986
  console.log(
22137
- ` ${badge2} ${pc33.bold(art.id)} ${status} ${pc33.dim(art.sourceNodeSlug)} ${pc33.dim(art.executionContext)}`
22987
+ ` ${badge2} ${pc35.bold(art.id)} ${status} ${pc35.dim(art.sourceNodeSlug)} ${pc35.dim(art.executionContext)}`
22138
22988
  );
22139
22989
  if (art.pipelineId) {
22140
- console.log(` ${pc33.dim("Pipeline:")} ${art.pipelineId}`);
22990
+ console.log(` ${pc35.dim("Pipeline:")} ${art.pipelineId}`);
22141
22991
  }
22142
- console.log(` ${pc33.dim("Created:")} ${art.createdAt}`);
22992
+ console.log(` ${pc35.dim("Created:")} ${art.createdAt}`);
22143
22993
  console.log("");
22144
22994
  }
22145
22995
  console.log(hr6());
22146
- console.log(pc33.dim(" growthub artifact inspect <id> \xB7 growthub artifact list --type <type>"));
22996
+ console.log(pc35.dim(" growthub artifact inspect <id> \xB7 growthub artifact list --type <type>"));
22147
22997
  console.log("");
22148
22998
  }
22149
22999
  function printArtifactDetail(art) {
22150
23000
  console.log("");
22151
- console.log(pc33.bold("Artifact: " + art.id));
23001
+ console.log(pc35.bold("Artifact: " + art.id));
22152
23002
  console.log(hr6());
22153
23003
  const kv = (label, value) => {
22154
23004
  if (value === void 0) return;
22155
- console.log(` ${pc33.bold(label.padEnd(22))} ${value}`);
23005
+ console.log(` ${pc35.bold(label.padEnd(22))} ${value}`);
22156
23006
  };
22157
23007
  kv("Type:", artifactTypeBadge(art.artifactType));
22158
23008
  kv("Status:", statusColor(art.status));
@@ -22166,7 +23016,7 @@ function printArtifactDetail(art) {
22166
23016
  kv("Updated:", art.updatedAt);
22167
23017
  if (art.metadata && Object.keys(art.metadata).length > 0) {
22168
23018
  console.log("");
22169
- console.log(pc33.bold(" Metadata:"));
23019
+ console.log(pc35.bold(" Metadata:"));
22170
23020
  console.log(" " + JSON.stringify(art.metadata, null, 2).split("\n").join("\n "));
22171
23021
  }
22172
23022
  console.log(hr6());
@@ -22203,14 +23053,14 @@ Examples:
22203
23053
  return;
22204
23054
  }
22205
23055
  printArtifactTable(artifacts);
22206
- console.log(pc33.dim(` Store: ${store.getStorePath()} \xB7 Source: ${meta.source}`));
23056
+ console.log(pc35.dim(` Store: ${store.getStorePath()} \xB7 Source: ${meta.source}`));
22207
23057
  console.log("");
22208
23058
  });
22209
23059
  art.command("inspect").description("Inspect a specific pipeline artifact").argument("<id>", "Artifact ID (e.g. art_xxxxxxxxxxxx)").option("--json", "Output raw JSON").action((artifactId, opts) => {
22210
23060
  const store = createArtifactStore();
22211
23061
  const artifact = store.get(artifactId);
22212
23062
  if (!artifact) {
22213
- console.error(pc33.red(`Artifact not found: "${artifactId}".`) + pc33.dim(" Run `growthub artifact list` to browse."));
23063
+ console.error(pc35.red(`Artifact not found: "${artifactId}".`) + pc35.dim(" Run `growthub artifact list` to browse."));
22214
23064
  process.exitCode = 1;
22215
23065
  return;
22216
23066
  }
@@ -22226,7 +23076,7 @@ Examples:
22226
23076
  import fs31 from "node:fs";
22227
23077
  import path40 from "node:path";
22228
23078
  import * as p23 from "@clack/prompts";
22229
- import pc35 from "picocolors";
23079
+ import pc37 from "picocolors";
22230
23080
  init_session_store();
22231
23081
  init_hosted_client();
22232
23082
 
@@ -22291,11 +23141,11 @@ function createWorkflowHygieneStore() {
22291
23141
  }
22292
23142
 
22293
23143
  // src/runtime/workflow-hygiene/summaries.ts
22294
- import pc34 from "picocolors";
23144
+ import pc36 from "picocolors";
22295
23145
  function renderWorkflowLabel(label) {
22296
- if (label === "canonical") return pc34.green("canonical");
22297
- if (label === "archived") return pc34.dim("archived");
22298
- return pc34.yellow("experimental");
23146
+ if (label === "canonical") return pc36.green("canonical");
23147
+ if (label === "archived") return pc36.dim("archived");
23148
+ return pc36.yellow("experimental");
22299
23149
  }
22300
23150
  function enrichWorkflowSummaries(entries, store) {
22301
23151
  return entries.map((entry) => {
@@ -22309,14 +23159,14 @@ init_banner();
22309
23159
  init_home();
22310
23160
  var PAGE_SIZE = 10;
22311
23161
  var FAMILY_CONFIG2 = {
22312
- video: { color: pc35.magenta, label: "Video" },
22313
- image: { color: pc35.cyan, label: "Image" },
22314
- slides: { color: pc35.yellow, label: "Slides" },
22315
- text: { color: pc35.green, label: "Text" },
22316
- data: { color: pc35.blue, label: "Data" },
22317
- ops: { color: pc35.red, label: "Ops" },
22318
- research: { color: pc35.blue, label: "Research" },
22319
- vision: { color: pc35.cyan, label: "Vision" }
23162
+ video: { color: pc37.magenta, label: "Video" },
23163
+ image: { color: pc37.cyan, label: "Image" },
23164
+ slides: { color: pc37.yellow, label: "Slides" },
23165
+ text: { color: pc37.green, label: "Text" },
23166
+ data: { color: pc37.blue, label: "Data" },
23167
+ ops: { color: pc37.red, label: "Ops" },
23168
+ research: { color: pc37.blue, label: "Research" },
23169
+ vision: { color: pc37.cyan, label: "Vision" }
22320
23170
  };
22321
23171
  var FAMILY_EMOJI = {
22322
23172
  video: "\u{1F3AC}",
@@ -22333,19 +23183,19 @@ function familyLabel(family) {
22333
23183
  return cfg ? cfg.color(cfg.label) : family;
22334
23184
  }
22335
23185
  function hr7(width = 72) {
22336
- return pc35.dim("\u2500".repeat(width));
23186
+ return pc37.dim("\u2500".repeat(width));
22337
23187
  }
22338
- function stripAnsi5(str) {
23188
+ function stripAnsi6(str) {
22339
23189
  return str.replace(/\x1B\[[0-9;]*m/g, "");
22340
23190
  }
22341
23191
  function box5(lines) {
22342
23192
  const padded = lines.map((l) => " " + l);
22343
- const width = Math.max(...padded.map((l) => stripAnsi5(l).length)) + 4;
22344
- const top = pc35.dim("\u250C" + "\u2500".repeat(width) + "\u2510");
22345
- const bottom = pc35.dim("\u2514" + "\u2500".repeat(width) + "\u2518");
23193
+ const width = Math.max(...padded.map((l) => stripAnsi6(l).length)) + 4;
23194
+ const top = pc37.dim("\u250C" + "\u2500".repeat(width) + "\u2510");
23195
+ const bottom = pc37.dim("\u2514" + "\u2500".repeat(width) + "\u2518");
22346
23196
  const body = padded.map((l) => {
22347
- const pad = width - stripAnsi5(l).length;
22348
- return pc35.dim("\u2502") + l + " ".repeat(pad) + pc35.dim("\u2502");
23197
+ const pad2 = width - stripAnsi6(l).length;
23198
+ return pc37.dim("\u2502") + l + " ".repeat(pad2) + pc37.dim("\u2502");
22349
23199
  });
22350
23200
  return [top, ...body, bottom].join("\n");
22351
23201
  }
@@ -22576,7 +23426,7 @@ async function paginatedSelect(message, allOptions, opts) {
22576
23426
  const hasPrev = offset > 0;
22577
23427
  const totalPages = Math.ceil(filtered.length / PAGE_SIZE);
22578
23428
  const currentPage = Math.floor(offset / PAGE_SIZE) + 1;
22579
- const pageInfo = filtered.length > PAGE_SIZE ? pc35.dim(` (${currentPage}/${totalPages} \xB7 ${filtered.length} total)`) : "";
23429
+ const pageInfo = filtered.length > PAGE_SIZE ? pc37.dim(` (${currentPage}/${totalPages} \xB7 ${filtered.length} total)`) : "";
22580
23430
  const options = [
22581
23431
  ...page.map((o) => ({
22582
23432
  value: o.value,
@@ -22585,13 +23435,13 @@ async function paginatedSelect(message, allOptions, opts) {
22585
23435
  }))
22586
23436
  ];
22587
23437
  if (hasMore) {
22588
- options.push({ value: "__next_page", label: pc35.dim("\u2192 Next page") });
23438
+ options.push({ value: "__next_page", label: pc37.dim("\u2192 Next page") });
22589
23439
  }
22590
23440
  if (hasPrev) {
22591
- options.push({ value: "__prev_page", label: pc35.dim("\u2190 Previous page") });
23441
+ options.push({ value: "__prev_page", label: pc37.dim("\u2190 Previous page") });
22592
23442
  }
22593
23443
  if (opts?.searchEnabled) {
22594
- options.push({ value: "__search", label: pc35.dim("\u{1F50E} Search") });
23444
+ options.push({ value: "__search", label: pc37.dim("\u{1F50E} Search") });
22595
23445
  }
22596
23446
  options.push({
22597
23447
  value: opts?.backValue ?? "__back",
@@ -22639,8 +23489,8 @@ async function paginatedSelect(message, allOptions, opts) {
22639
23489
  function printTemplateCard(node) {
22640
23490
  const contract = introspectNodeContract(node);
22641
23491
  const lines = renderContractCard(contract);
22642
- lines.splice(1, 0, `${familyLabel(node.family)} ${node.enabled ? pc35.green("enabled") : pc35.red("disabled")}`);
22643
- if (node.description) lines.push("", pc35.dim(node.description));
23492
+ lines.splice(1, 0, `${familyLabel(node.family)} ${node.enabled ? pc37.green("enabled") : pc37.red("disabled")}`);
23493
+ if (node.description) lines.push("", pc37.dim(node.description));
22644
23494
  console.log("");
22645
23495
  console.log(box5(lines));
22646
23496
  console.log("");
@@ -22654,9 +23504,9 @@ function renderTemplateTree(templates) {
22654
23504
  byFamily.set(key, existing);
22655
23505
  }
22656
23506
  const families = [...byFamily.entries()].sort((a, b) => a[0].localeCompare(b[0]));
22657
- const lines = [pc35.bold("Public CMS Node Tree")];
23507
+ const lines = [pc37.bold("Public CMS Node Tree")];
22658
23508
  for (const [family, nodes] of families) {
22659
- lines.push(`${pc35.cyan("\u2022")} ${pc35.bold(family)}`);
23509
+ lines.push(`${pc37.cyan("\u2022")} ${pc37.bold(family)}`);
22660
23510
  const sorted = [...nodes].sort((a, b) => a.slug.localeCompare(b.slug));
22661
23511
  for (const [index51, node] of sorted.entries()) {
22662
23512
  const branch = index51 === sorted.length - 1 ? "\u2514\u2500" : "\u251C\u2500";
@@ -22664,12 +23514,12 @@ function renderTemplateTree(templates) {
22664
23514
  const requiredInputs = contract.inputs.filter((input) => input.required).length;
22665
23515
  const optionalInputs = contract.inputs.length - requiredInputs;
22666
23516
  lines.push(
22667
- ` ${branch} ${node.slug} ${pc35.dim(`(req:${requiredInputs} opt:${optionalInputs} out:${contract.outputTypes.length})`)}`
23517
+ ` ${branch} ${node.slug} ${pc37.dim(`(req:${requiredInputs} opt:${optionalInputs} out:${contract.outputTypes.length})`)}`
22668
23518
  );
22669
23519
  }
22670
23520
  }
22671
23521
  lines.push("");
22672
- lines.push(pc35.dim("Shortcut: growthub workflow saved --json"));
23522
+ lines.push(pc37.dim("Shortcut: growthub workflow saved --json"));
22673
23523
  return lines;
22674
23524
  }
22675
23525
  function renderWorkflowContractDiscoveryTree(nodes) {
@@ -22681,10 +23531,10 @@ function renderWorkflowContractDiscoveryTree(nodes) {
22681
23531
  byFamily.set(key, group);
22682
23532
  }
22683
23533
  const families = [...byFamily.entries()].sort((a, b) => a[0].localeCompare(b[0]));
22684
- const lines = [pc35.bold("CMS Node Contract Discovery")];
23534
+ const lines = [pc37.bold("CMS Node Contract Discovery")];
22685
23535
  for (const [family, familyNodes] of families) {
22686
23536
  const emoji = FAMILY_EMOJI[family] ?? "\u2022";
22687
- lines.push(`${emoji} ${pc35.bold(familyLabel(family))} ${pc35.dim(`(${familyNodes.length})`)}`);
23537
+ lines.push(`${emoji} ${pc37.bold(familyLabel(family))} ${pc37.dim(`(${familyNodes.length})`)}`);
22688
23538
  const sorted = [...familyNodes].sort((a, b) => a.slug.localeCompare(b.slug));
22689
23539
  for (const [index51, node] of sorted.entries()) {
22690
23540
  const branch = index51 === sorted.length - 1 ? "\u2514\u2500" : "\u251C\u2500";
@@ -22692,7 +23542,7 @@ function renderWorkflowContractDiscoveryTree(nodes) {
22692
23542
  const requiredInputs = contract.inputs.filter((input) => input.required).length;
22693
23543
  const optionalInputs = contract.inputs.length - requiredInputs;
22694
23544
  lines.push(
22695
- ` ${branch} ${node.slug} ${pc35.dim(`req:${requiredInputs} opt:${optionalInputs} bindings:${contract.requiredBindings.length} outputs:${contract.outputTypes.length}`)}`
23545
+ ` ${branch} ${node.slug} ${pc37.dim(`req:${requiredInputs} opt:${optionalInputs} bindings:${contract.requiredBindings.length} outputs:${contract.outputTypes.length}`)}`
22696
23546
  );
22697
23547
  }
22698
23548
  }
@@ -22705,7 +23555,7 @@ function buildTemplateOption(template, viewMode) {
22705
23555
  if (viewMode === "expanded") {
22706
23556
  return {
22707
23557
  value: template.slug,
22708
- label: `${template.icon} ${template.displayName} ${pc35.dim(template.slug)}`,
23558
+ label: `${template.icon} ${template.displayName} ${pc37.dim(template.slug)}`,
22709
23559
  hint: `req:${requiredInputs} opt:${optionalInputs} outputs:${contract.outputTypes.join(", ") || "none"} exec:${contract.executionStrategy}`
22710
23560
  };
22711
23561
  }
@@ -22727,11 +23577,11 @@ async function runWorkflowPicker(opts) {
22727
23577
  const hygieneStore = createWorkflowHygieneStore();
22728
23578
  const access = getWorkflowAccess();
22729
23579
  if (access.state === "unauthenticated") {
22730
- p23.intro(pc35.bold("Workflows") + pc35.dim(" (not connected)"));
23580
+ p23.intro(pc37.bold("Workflows") + pc37.dim(" (not connected)"));
22731
23581
  p23.note(
22732
23582
  [
22733
23583
  "Workflow assembly requires an authenticated Growthub session.",
22734
- "Run " + pc35.cyan("growthub auth login") + " to connect your account.",
23584
+ "Run " + pc37.cyan("growthub auth login") + " to connect your account.",
22735
23585
  "",
22736
23586
  "Once connected you can:",
22737
23587
  " - Browse CMS node contracts",
@@ -22743,7 +23593,7 @@ async function runWorkflowPicker(opts) {
22743
23593
  if (opts.allowBackToHub) return "back";
22744
23594
  return "done";
22745
23595
  }
22746
- p23.intro(pc35.bold("Workflows"));
23596
+ p23.intro(pc37.bold("Workflows"));
22747
23597
  while (true) {
22748
23598
  const refreshedAccess = getWorkflowAccess();
22749
23599
  const topChoice = await p23.select({
@@ -22751,12 +23601,12 @@ async function runWorkflowPicker(opts) {
22751
23601
  options: [
22752
23602
  {
22753
23603
  value: "contracts",
22754
- label: refreshedAccess.state === "ready" ? "0. CMS Node Contracts" : pc35.dim("0. CMS Node Contracts (locked)"),
23604
+ label: refreshedAccess.state === "ready" ? "0. CMS Node Contracts" : pc37.dim("0. CMS Node Contracts (locked)"),
22755
23605
  hint: refreshedAccess.state === "ready" ? "Discovery tree for CMS node primitives" : refreshedAccess.reason
22756
23606
  },
22757
23607
  {
22758
23608
  value: "pipelines",
22759
- label: refreshedAccess.state === "ready" ? "1. Dynamic Pipelines" : pc35.dim("1. Dynamic Pipelines (locked)"),
23609
+ label: refreshedAccess.state === "ready" ? "1. Dynamic Pipelines" : pc37.dim("1. Dynamic Pipelines (locked)"),
22760
23610
  hint: refreshedAccess.state === "ready" ? "Create new pipelines and route into Saved Workflows" : refreshedAccess.reason
22761
23611
  },
22762
23612
  {
@@ -22823,7 +23673,7 @@ async function runWorkflowPicker(opts) {
22823
23673
  const requiredInputs = contract.inputs.filter((input) => input.required).length;
22824
23674
  return {
22825
23675
  value: node.slug,
22826
- label: `${node.icon} ${node.displayName} ${pc35.dim(node.slug)}`,
23676
+ label: `${node.icon} ${node.displayName} ${pc37.dim(node.slug)}`,
22827
23677
  hint: `${node.family} \xB7 required:${requiredInputs} \xB7 bindings:${contract.requiredBindings.length} \xB7 outputs:${contract.outputTypes.length}`
22828
23678
  };
22829
23679
  });
@@ -22864,7 +23714,7 @@ async function runWorkflowPicker(opts) {
22864
23714
  }
22865
23715
  }
22866
23716
  } catch (err) {
22867
- contractsSpinner.stop(pc35.red("Failed to load CMS node contracts."));
23717
+ contractsSpinner.stop(pc37.red("Failed to load CMS node contracts."));
22868
23718
  p23.log.error("Failed to load CMS node contracts: " + err.message);
22869
23719
  }
22870
23720
  continue;
@@ -22899,14 +23749,14 @@ async function runWorkflowPicker(opts) {
22899
23749
  saved = withEffectiveWorkflowLabels(enriched, hygieneStore);
22900
23750
  savedSpinner.stop(`Loaded ${saved.length} saved workflow${saved.length === 1 ? "" : "s"}.`);
22901
23751
  } catch (err) {
22902
- savedSpinner.stop(pc35.red("Failed to load saved workflows."));
23752
+ savedSpinner.stop(pc37.red("Failed to load saved workflows."));
22903
23753
  throw err;
22904
23754
  }
22905
23755
  if (saved.length === 0) {
22906
23756
  p23.note(
22907
23757
  [
22908
23758
  "No saved workflows found.",
22909
- "Use " + pc35.cyan("growthub pipeline assemble") + " to create a new workflow pipeline."
23759
+ "Use " + pc37.cyan("growthub pipeline assemble") + " to create a new workflow pipeline."
22910
23760
  ].join("\n"),
22911
23761
  "Nothing saved"
22912
23762
  );
@@ -22914,7 +23764,7 @@ async function runWorkflowPicker(opts) {
22914
23764
  }
22915
23765
  const allOptions = saved.map((w) => ({
22916
23766
  value: w.workflowId,
22917
- label: `${w.name} ${pc35.dim(`[${renderWorkflowLabel(w.workflowLabel)}]`)} ${pc35.dim(`${w.nodeCount} node${w.nodeCount !== 1 ? "s" : ""}`)}`,
23767
+ label: `${w.name} ${pc37.dim(`[${renderWorkflowLabel(w.workflowLabel)}]`)} ${pc37.dim(`${w.nodeCount} node${w.nodeCount !== 1 ? "s" : ""}`)}`,
22918
23768
  hint: `${w.executionMode} \xB7 ${w.updatedAt?.slice(0, 10) ?? w.createdAt.slice(0, 10)}`
22919
23769
  }));
22920
23770
  const choice = await paginatedSelect("Select a saved workflow", allOptions, {
@@ -22935,7 +23785,7 @@ async function runWorkflowPicker(opts) {
22935
23785
  detail = await loadSavedWorkflowDetail(entry);
22936
23786
  detailSpinner.stop(`Loaded ${entry.name}.`);
22937
23787
  } catch (err) {
22938
- detailSpinner.stop(pc35.red(`Failed to load ${entry.name}.`));
23788
+ detailSpinner.stop(pc37.red(`Failed to load ${entry.name}.`));
22939
23789
  p23.log.error(err.message);
22940
23790
  continue;
22941
23791
  }
@@ -22943,14 +23793,14 @@ async function runWorkflowPicker(opts) {
22943
23793
  const nodes = Array.isArray(pipeline.nodes) ? pipeline.nodes : [];
22944
23794
  console.log("");
22945
23795
  console.log(box5([
22946
- `${pc35.bold("Workflow:")} ${entry.name}`,
22947
- `${pc35.dim("ID:")} ${entry.workflowId}`,
22948
- `${pc35.dim("Mode:")} hosted ${pc35.dim("Nodes:")} ${nodes.length}`,
22949
- `${pc35.dim("Label:")} ${renderWorkflowLabel(entry.workflowLabel ?? "experimental")}`,
22950
- `${pc35.dim("Created:")} ${detail.createdAt || "\u2014"}`,
23796
+ `${pc37.bold("Workflow:")} ${entry.name}`,
23797
+ `${pc37.dim("ID:")} ${entry.workflowId}`,
23798
+ `${pc37.dim("Mode:")} hosted ${pc37.dim("Nodes:")} ${nodes.length}`,
23799
+ `${pc37.dim("Label:")} ${renderWorkflowLabel(entry.workflowLabel ?? "experimental")}`,
23800
+ `${pc37.dim("Created:")} ${detail.createdAt || "\u2014"}`,
22951
23801
  "",
22952
23802
  ...nodes.map(
22953
- (n, i) => `${pc35.dim(String(i + 1) + ".")} ${pc35.bold(n.data?.slug ?? n.slug ?? n.id)} ${pc35.dim(n.id)}`
23803
+ (n, i) => `${pc37.dim(String(i + 1) + ".")} ${pc37.bold(n.data?.slug ?? n.slug ?? n.id)} ${pc37.dim(n.id)}`
22954
23804
  )
22955
23805
  ]));
22956
23806
  console.log("");
@@ -22961,7 +23811,7 @@ async function runWorkflowPicker(opts) {
22961
23811
  { value: "set_label", label: "Set workflow label" },
22962
23812
  { value: "archive", label: "Archive workflow" },
22963
23813
  { value: "unarchive", label: "Unarchive workflow" },
22964
- { value: "delete", label: pc35.red("Delete workflow") },
23814
+ { value: "delete", label: pc37.red("Delete workflow") },
22965
23815
  { value: "back_to_saved", label: "\u2190 Back to saved workflows" }
22966
23816
  ]
22967
23817
  });
@@ -23006,7 +23856,7 @@ async function runWorkflowPicker(opts) {
23006
23856
  console.log("");
23007
23857
  }
23008
23858
  await executeHostedPipeline(executablePipeline);
23009
- p23.log.success(`Saved workflow execution completed for ${pc35.bold(entry.name)}.`);
23859
+ p23.log.success(`Saved workflow execution completed for ${pc37.bold(entry.name)}.`);
23010
23860
  } catch (err) {
23011
23861
  p23.log.error("Saved workflow execution failed: " + err.message);
23012
23862
  }
@@ -23025,7 +23875,7 @@ async function runWorkflowPicker(opts) {
23025
23875
  continue;
23026
23876
  }
23027
23877
  hygieneStore.setLabel(entry.workflowId, labelChoice);
23028
- p23.log.success(`Updated label for ${pc35.bold(entry.name)} to ${renderWorkflowLabel(labelChoice)}.`);
23878
+ p23.log.success(`Updated label for ${pc37.bold(entry.name)} to ${renderWorkflowLabel(labelChoice)}.`);
23029
23879
  continue;
23030
23880
  }
23031
23881
  if (nextAction === "archive") {
@@ -23039,10 +23889,10 @@ async function runWorkflowPicker(opts) {
23039
23889
  try {
23040
23890
  await archiveSavedWorkflow(entry);
23041
23891
  hygieneStore.setLabel(entry.workflowId, "archived");
23042
- p23.log.success(`Archived ${pc35.bold(entry.name)}.`);
23892
+ p23.log.success(`Archived ${pc37.bold(entry.name)}.`);
23043
23893
  } catch {
23044
23894
  hygieneStore.setLabel(entry.workflowId, "archived");
23045
- p23.log.success(`Archived ${pc35.bold(entry.name)} (local fallback).`);
23895
+ p23.log.success(`Archived ${pc37.bold(entry.name)} (local fallback).`);
23046
23896
  }
23047
23897
  continue;
23048
23898
  }
@@ -23064,7 +23914,7 @@ async function runWorkflowPicker(opts) {
23064
23914
  }
23065
23915
  hygieneStore.setLabel(entry.workflowId, restoreChoice);
23066
23916
  p23.log.success(
23067
- `Unarchived ${pc35.bold(entry.name)} to ${renderWorkflowLabel(restoreChoice)}.`
23917
+ `Unarchived ${pc37.bold(entry.name)} to ${renderWorkflowLabel(restoreChoice)}.`
23068
23918
  );
23069
23919
  continue;
23070
23920
  }
@@ -23085,10 +23935,10 @@ async function runWorkflowPicker(opts) {
23085
23935
  }
23086
23936
  try {
23087
23937
  await deleteSavedWorkflow(entry);
23088
- p23.log.success(`Deleted ${pc35.bold(entry.name)}.`);
23938
+ p23.log.success(`Deleted ${pc37.bold(entry.name)}.`);
23089
23939
  } catch {
23090
23940
  markWorkflowDeletedLocally(entry.workflowId);
23091
- p23.log.success(`Deleted ${pc35.bold(entry.name)} (local fallback).`);
23941
+ p23.log.success(`Deleted ${pc37.bold(entry.name)} (local fallback).`);
23092
23942
  }
23093
23943
  continue;
23094
23944
  }
@@ -23205,12 +24055,12 @@ async function runWorkflowPicker(opts) {
23205
24055
  const resolver = createMachineCapabilityResolver();
23206
24056
  const binding = await resolver.resolveCapability(selected.slug);
23207
24057
  if (binding) {
23208
- const statusColor3 = binding.allowed ? pc35.green : pc35.red;
24058
+ const statusColor3 = binding.allowed ? pc37.green : pc37.red;
23209
24059
  console.log("");
23210
24060
  console.log(box5([
23211
- `${pc35.bold("Machine Binding:")} ${selected.slug}`,
23212
- `${pc35.dim("Allowed:")} ${statusColor3(String(binding.allowed))}`,
23213
- `${pc35.dim("Reason:")} ${binding.reason ?? "\u2014"}`
24061
+ `${pc37.bold("Machine Binding:")} ${selected.slug}`,
24062
+ `${pc37.dim("Allowed:")} ${statusColor3(String(binding.allowed))}`,
24063
+ `${pc37.dim("Reason:")} ${binding.reason ?? "\u2014"}`
23214
24064
  ]));
23215
24065
  console.log("");
23216
24066
  }
@@ -23245,7 +24095,7 @@ async function runWorkflowPicker(opts) {
23245
24095
  "Input normalization"
23246
24096
  );
23247
24097
  const nodeId = builder.addNode(selected.slug, normalized.bindings);
23248
- p23.log.success(`Added ${pc35.bold(selected.displayName)} (${pc35.dim(nodeId)})`);
24098
+ p23.log.success(`Added ${pc37.bold(selected.displayName)} (${pc37.dim(nodeId)})`);
23249
24099
  const next = await p23.select({
23250
24100
  message: "Pipeline has 1 node. What next?",
23251
24101
  options: [
@@ -23283,7 +24133,7 @@ async function runWorkflowPicker(opts) {
23283
24133
  throw new Error("Hosted workflow save returned no payload.");
23284
24134
  }
23285
24135
  p23.log.success(
23286
- `Hosted workflow saved as ${pc35.bold(workflowName)} (${pc35.dim(saveResult.workflowId)} \xB7 v${saveResult.version})`
24136
+ `Hosted workflow saved as ${pc37.bold(workflowName)} (${pc37.dim(saveResult.workflowId)} \xB7 v${saveResult.version})`
23287
24137
  );
23288
24138
  }
23289
24139
  break;
@@ -23333,31 +24183,31 @@ async function renderWorkflowIntelligenceSummary(pipeline, capabilities, phase)
23333
24183
  };
23334
24184
  const result = await provider.summarizeExecution(input);
23335
24185
  const lines = [
23336
- `${pc35.bold("Intelligence Summary")} ${pc35.dim(result.title)}`,
24186
+ `${pc37.bold("Intelligence Summary")} ${pc37.dim(result.title)}`,
23337
24187
  result.explanation
23338
24188
  ];
23339
24189
  if (result.runtimeModeNote) {
23340
- lines.push(`${pc35.dim("Runtime:")} ${result.runtimeModeNote}`);
24190
+ lines.push(`${pc37.dim("Runtime:")} ${result.runtimeModeNote}`);
23341
24191
  }
23342
24192
  if (result.outputExpectation) {
23343
- lines.push(`${pc35.dim("Expected:")} ${result.outputExpectation}`);
24193
+ lines.push(`${pc37.dim("Expected:")} ${result.outputExpectation}`);
23344
24194
  }
23345
24195
  if (result.missingBindingGuidance.length > 0) {
23346
- lines.push("", pc35.yellow("Missing Binding Guidance"));
24196
+ lines.push("", pc37.yellow("Missing Binding Guidance"));
23347
24197
  for (const guidance of result.missingBindingGuidance) {
23348
- lines.push(` ${pc35.dim("\xB7")} ${guidance}`);
24198
+ lines.push(` ${pc37.dim("\xB7")} ${guidance}`);
23349
24199
  }
23350
24200
  }
23351
24201
  if (result.costLatencyCautions.length > 0) {
23352
- lines.push("", pc35.yellow("Cost/Latency Notes"));
24202
+ lines.push("", pc37.yellow("Cost/Latency Notes"));
23353
24203
  for (const caution of result.costLatencyCautions) {
23354
- lines.push(` ${pc35.dim("\xB7")} ${caution}`);
24204
+ lines.push(` ${pc37.dim("\xB7")} ${caution}`);
23355
24205
  }
23356
24206
  }
23357
24207
  if (result.warnings.length > 0) {
23358
- lines.push("", pc35.yellow("Warnings"));
24208
+ lines.push("", pc37.yellow("Warnings"));
23359
24209
  for (const warning of result.warnings) {
23360
- lines.push(` ${pc35.dim("\xB7")} ${warning}`);
24210
+ lines.push(` ${pc37.dim("\xB7")} ${warning}`);
23361
24211
  }
23362
24212
  }
23363
24213
  return lines;
@@ -23380,7 +24230,7 @@ Examples:
23380
24230
  wf.command("templates").description("List CMS workflow node starter templates").option("--family <family>", "Filter by family").option("--search <term>", "Search templates").option("--view <mode>", "List view mode: condensed | expanded | tree").option("--json", "Output raw JSON").action(async (opts) => {
23381
24231
  const access = getWorkflowAccess();
23382
24232
  if (access.state !== "ready") {
23383
- console.error(pc35.red(`${access.reason}.`));
24233
+ console.error(pc37.red(`${access.reason}.`));
23384
24234
  process.exitCode = 1;
23385
24235
  return;
23386
24236
  }
@@ -23397,24 +24247,24 @@ Examples:
23397
24247
  return;
23398
24248
  }
23399
24249
  if (nodes.length === 0) {
23400
- console.error(pc35.yellow("No templates found."));
24250
+ console.error(pc37.yellow("No templates found."));
23401
24251
  process.exitCode = 1;
23402
24252
  return;
23403
24253
  }
23404
24254
  const viewMode = opts.view ?? "condensed";
23405
24255
  console.log("");
23406
24256
  console.log(
23407
- pc35.bold("Workflow Node Templates") + pc35.dim(` ${nodes.length} template${nodes.length !== 1 ? "s" : ""}`)
24257
+ pc37.bold("Workflow Node Templates") + pc37.dim(` ${nodes.length} template${nodes.length !== 1 ? "s" : ""}`)
23408
24258
  );
23409
24259
  console.log(hr7());
23410
- console.log(pc35.bold("Step 1: CMS Node Contract Validation"));
23411
- console.log(pc35.dim("Validate contract visibility before template selection."));
23412
- console.log(pc35.dim(`View mode: ${viewMode}`));
24260
+ console.log(pc37.bold("Step 1: CMS Node Contract Validation"));
24261
+ console.log(pc37.dim("Validate contract visibility before template selection."));
24262
+ console.log(pc37.dim(`View mode: ${viewMode}`));
23413
24263
  console.log("");
23414
24264
  if (viewMode === "tree") {
23415
24265
  console.log(box5(renderTemplateTree(nodes)));
23416
24266
  console.log(hr7());
23417
- console.log(pc35.dim(` Source: ${meta.source} \xB7 growthub workflow`));
24267
+ console.log(pc37.dim(` Source: ${meta.source} \xB7 growthub workflow`));
23418
24268
  console.log("");
23419
24269
  return;
23420
24270
  }
@@ -23422,24 +24272,24 @@ Examples:
23422
24272
  const contract = introspectNodeContract(node);
23423
24273
  const requiredInputs = contract.inputs.filter((input) => input.required).length;
23424
24274
  const optionalInputs = contract.inputs.length - requiredInputs;
23425
- const enabledTag = node.enabled ? pc35.green("enabled") : pc35.red("disabled");
23426
- console.log(` ${node.icon} ${pc35.bold(node.displayName)} ${pc35.dim(node.slug)} ${enabledTag}`);
24275
+ const enabledTag = node.enabled ? pc37.green("enabled") : pc37.red("disabled");
24276
+ console.log(` ${node.icon} ${pc37.bold(node.displayName)} ${pc37.dim(node.slug)} ${enabledTag}`);
23427
24277
  console.log(
23428
- ` ${pc35.dim("Contract:")} ${pc35.dim("required")}=${requiredInputs} ${pc35.dim("optional")}=${optionalInputs} ${pc35.dim("bindings")}=${contract.requiredBindings.length} ${pc35.dim("outputs")}=${contract.outputTypes.length}`
24278
+ ` ${pc37.dim("Contract:")} ${pc37.dim("required")}=${requiredInputs} ${pc37.dim("optional")}=${optionalInputs} ${pc37.dim("bindings")}=${contract.requiredBindings.length} ${pc37.dim("outputs")}=${contract.outputTypes.length}`
23429
24279
  );
23430
24280
  console.log(
23431
- ` ${pc35.dim("Execution:")} ${contract.executionStrategy} \xB7 ${contract.executionKind}`
24281
+ ` ${pc37.dim("Execution:")} ${contract.executionStrategy} \xB7 ${contract.executionKind}`
23432
24282
  );
23433
24283
  if (node.description) {
23434
- console.log(` ${pc35.dim(node.description)}`);
24284
+ console.log(` ${pc37.dim(node.description)}`);
23435
24285
  }
23436
24286
  console.log("");
23437
24287
  }
23438
24288
  console.log(hr7());
23439
- console.log(pc35.dim(` Source: ${meta.source} \xB7 growthub workflow`));
24289
+ console.log(pc37.dim(` Source: ${meta.source} \xB7 growthub workflow`));
23440
24290
  console.log("");
23441
24291
  } catch (err) {
23442
- console.error(pc35.red("Failed: " + err.message));
24292
+ console.error(pc37.red("Failed: " + err.message));
23443
24293
  process.exitCode = 1;
23444
24294
  }
23445
24295
  });
@@ -23459,34 +24309,34 @@ Examples:
23459
24309
  return;
23460
24310
  }
23461
24311
  if (visibleSaved.length === 0) {
23462
- console.log(pc35.dim("No saved workflows. Run `growthub workflow` to assemble one."));
24312
+ console.log(pc37.dim("No saved workflows. Run `growthub workflow` to assemble one."));
23463
24313
  return;
23464
24314
  }
23465
24315
  console.log("");
23466
24316
  console.log(
23467
- pc35.bold("Saved Workflows") + pc35.dim(` ${visibleSaved.length} workflow${visibleSaved.length !== 1 ? "s" : ""}`)
24317
+ pc37.bold("Saved Workflows") + pc37.dim(` ${visibleSaved.length} workflow${visibleSaved.length !== 1 ? "s" : ""}`)
23468
24318
  );
23469
24319
  if (!opts.includeArchived) {
23470
24320
  const hiddenArchivedCount = saved.length - visibleSaved.length;
23471
24321
  if (hiddenArchivedCount > 0) {
23472
- console.log(pc35.dim(` Archived hidden: ${hiddenArchivedCount} (use --include-archived to show)`));
24322
+ console.log(pc37.dim(` Archived hidden: ${hiddenArchivedCount} (use --include-archived to show)`));
23473
24323
  }
23474
24324
  }
23475
24325
  console.log(hr7());
23476
24326
  for (const w of visibleSaved) {
23477
24327
  console.log(
23478
- ` ${pc35.bold(w.name)} ` + pc35.dim(`[${renderWorkflowLabel(w.workflowLabel)}] `) + pc35.dim(`${w.nodeCount} node${w.nodeCount !== 1 ? "s" : ""} \xB7 ${w.executionMode} \xB7 ${w.updatedAt?.slice(0, 10) ?? w.createdAt.slice(0, 10)}`)
24328
+ ` ${pc37.bold(w.name)} ` + pc37.dim(`[${renderWorkflowLabel(w.workflowLabel)}] `) + pc37.dim(`${w.nodeCount} node${w.nodeCount !== 1 ? "s" : ""} \xB7 ${w.executionMode} \xB7 ${w.updatedAt?.slice(0, 10) ?? w.createdAt.slice(0, 10)}`)
23479
24329
  );
23480
24330
  }
23481
24331
  console.log("");
23482
- console.log(pc35.dim(` Source: ${visibleSaved[0]?.source === "hosted" ? "hosted workflow registry" : resolveSavedWorkflowsDir()}`));
24332
+ console.log(pc37.dim(` Source: ${visibleSaved[0]?.source === "hosted" ? "hosted workflow registry" : resolveSavedWorkflowsDir()}`));
23483
24333
  console.log("");
23484
24334
  });
23485
24335
  }
23486
24336
 
23487
24337
  // src/commands/open-agents.ts
23488
24338
  import * as p24 from "@clack/prompts";
23489
- import pc36 from "picocolors";
24339
+ import pc38 from "picocolors";
23490
24340
 
23491
24341
  // src/runtime/agent-harness/auth-store.ts
23492
24342
  init_home();
@@ -23819,49 +24669,49 @@ function validateAuthMode(value) {
23819
24669
  // src/commands/open-agents.ts
23820
24670
  init_banner();
23821
24671
  function statusColor2(status) {
23822
- if (status === "running") return pc36.green(status);
23823
- if (status === "completed") return pc36.cyan(status);
23824
- if (status === "failed" || status === "cancelled") return pc36.red(status);
23825
- if (status === "waiting" || status === "idle") return pc36.yellow(status);
23826
- return pc36.dim(status);
24672
+ if (status === "running") return pc38.green(status);
24673
+ if (status === "completed") return pc38.cyan(status);
24674
+ if (status === "failed" || status === "cancelled") return pc38.red(status);
24675
+ if (status === "waiting" || status === "idle") return pc38.yellow(status);
24676
+ return pc38.dim(status);
23827
24677
  }
23828
24678
  function sandboxBadge(state) {
23829
- if (state === "running") return pc36.green("running");
23830
- if (state === "hibernating") return pc36.yellow("hibernating");
23831
- if (state === "stopped") return pc36.dim("stopped");
23832
- if (state === "error") return pc36.red("error");
23833
- return pc36.dim(state);
24679
+ if (state === "running") return pc38.green("running");
24680
+ if (state === "hibernating") return pc38.yellow("hibernating");
24681
+ if (state === "stopped") return pc38.dim("stopped");
24682
+ if (state === "error") return pc38.red("error");
24683
+ return pc38.dim(state);
23834
24684
  }
23835
24685
  function hr8(width = 72) {
23836
- return pc36.dim("\u2500".repeat(width));
24686
+ return pc38.dim("\u2500".repeat(width));
23837
24687
  }
23838
- function stripAnsi6(str) {
24688
+ function stripAnsi7(str) {
23839
24689
  return str.replace(/\x1B\[[0-9;]*m/g, "");
23840
24690
  }
23841
24691
  function box6(lines) {
23842
24692
  const padded = lines.map((l) => " " + l);
23843
- const width = Math.max(...padded.map((l) => stripAnsi6(l).length)) + 4;
23844
- const top = pc36.dim("\u250C" + "\u2500".repeat(width) + "\u2510");
23845
- const bottom = pc36.dim("\u2514" + "\u2500".repeat(width) + "\u2518");
24693
+ const width = Math.max(...padded.map((l) => stripAnsi7(l).length)) + 4;
24694
+ const top = pc38.dim("\u250C" + "\u2500".repeat(width) + "\u2510");
24695
+ const bottom = pc38.dim("\u2514" + "\u2500".repeat(width) + "\u2518");
23846
24696
  const body = padded.map((l) => {
23847
- const pad = width - stripAnsi6(l).length;
23848
- return pc36.dim("\u2502") + l + " ".repeat(pad) + pc36.dim("\u2502");
24697
+ const pad2 = width - stripAnsi7(l).length;
24698
+ return pc38.dim("\u2502") + l + " ".repeat(pad2) + pc38.dim("\u2502");
23849
24699
  });
23850
24700
  return [top, ...body, bottom].join("\n");
23851
24701
  }
23852
24702
  function printSessionCard(session) {
23853
24703
  const lines = [
23854
- `${pc36.bold("Session")} ${pc36.dim(session.sessionId)}`,
23855
- `${pc36.dim("Status:")} ${statusColor2(session.status)}`,
23856
- `${pc36.dim("Sandbox:")} ${sandboxBadge(session.sandboxState)}`,
23857
- `${pc36.dim("Events:")} ${session.eventCount}`,
23858
- `${pc36.dim("Created:")} ${session.createdAt}`
24704
+ `${pc38.bold("Session")} ${pc38.dim(session.sessionId)}`,
24705
+ `${pc38.dim("Status:")} ${statusColor2(session.status)}`,
24706
+ `${pc38.dim("Sandbox:")} ${sandboxBadge(session.sandboxState)}`,
24707
+ `${pc38.dim("Events:")} ${session.eventCount}`,
24708
+ `${pc38.dim("Created:")} ${session.createdAt}`
23859
24709
  ];
23860
- if (session.repoUrl) lines.push(`${pc36.dim("Repo:")} ${session.repoUrl}`);
23861
- if (session.branch) lines.push(`${pc36.dim("Branch:")} ${session.branch}`);
24710
+ if (session.repoUrl) lines.push(`${pc38.dim("Repo:")} ${session.repoUrl}`);
24711
+ if (session.branch) lines.push(`${pc38.dim("Branch:")} ${session.branch}`);
23862
24712
  if (session.prompt) {
23863
24713
  const truncated = session.prompt.length > 80 ? session.prompt.slice(0, 77) + "..." : session.prompt;
23864
- lines.push(`${pc36.dim("Prompt:")} ${truncated}`);
24714
+ lines.push(`${pc38.dim("Prompt:")} ${truncated}`);
23865
24715
  }
23866
24716
  console.log("");
23867
24717
  console.log(box6(lines));
@@ -23888,12 +24738,12 @@ var EVENT_EMOJI = {
23888
24738
  };
23889
24739
  function printEvent(event) {
23890
24740
  const emoji = EVENT_EMOJI[event.type] ?? "\xB7";
23891
- const ts = pc36.dim(event.timestamp.split("T")[1]?.slice(0, 8) ?? "");
24741
+ const ts = pc38.dim(event.timestamp.split("T")[1]?.slice(0, 8) ?? "");
23892
24742
  console.log(` ${emoji} ${ts} ${event.detail}`);
23893
24743
  }
23894
24744
  async function runOpenAgentsHub(opts) {
23895
24745
  printPaperclipCliBanner();
23896
- p24.intro(pc36.bold("Open Agents"));
24746
+ p24.intro(pc38.bold("Open Agents"));
23897
24747
  while (true) {
23898
24748
  const config = readOpenAgentsConfig();
23899
24749
  const action = await p24.select({
@@ -24060,7 +24910,7 @@ async function runSessionListFlow(config) {
24060
24910
  options: [
24061
24911
  ...sessions.map((s) => ({
24062
24912
  value: s.sessionId,
24063
- label: `${statusColor2(s.status)} ${pc36.dim(s.sessionId.slice(0, 12))}`,
24913
+ label: `${statusColor2(s.status)} ${pc38.dim(s.sessionId.slice(0, 12))}`,
24064
24914
  hint: s.prompt ? s.prompt.slice(0, 50) : void 0
24065
24915
  })),
24066
24916
  { value: "__back", label: "\u2190 Back" }
@@ -24085,7 +24935,7 @@ async function runSessionListFlow(config) {
24085
24935
  p24.note("No events recorded yet.", "Empty");
24086
24936
  } else {
24087
24937
  console.log("");
24088
- console.log(pc36.bold("Recent Events") + pc36.dim(` (${events.length})`));
24938
+ console.log(pc38.bold("Recent Events") + pc38.dim(` (${events.length})`));
24089
24939
  console.log(hr8());
24090
24940
  for (const event of events.slice(-20)) {
24091
24941
  printEvent(event);
@@ -24151,7 +25001,7 @@ async function runResumeSessionFlow(config) {
24151
25001
  printSessionCard(session);
24152
25002
  const events = await pollSessionEvents(config, session.sessionId);
24153
25003
  if (events.length > 0) {
24154
- console.log(pc36.bold("Latest Events") + pc36.dim(` (${events.length})`));
25004
+ console.log(pc38.bold("Latest Events") + pc38.dim(` (${events.length})`));
24155
25005
  console.log(hr8());
24156
25006
  for (const event of events.slice(-20)) {
24157
25007
  printEvent(event);
@@ -24198,7 +25048,7 @@ Examples:
24198
25048
  if (opts.json) {
24199
25049
  console.log(JSON.stringify(updated, null, 2));
24200
25050
  } else {
24201
- console.log(pc36.green("Configuration updated."));
25051
+ console.log(pc38.green("Configuration updated."));
24202
25052
  }
24203
25053
  return;
24204
25054
  }
@@ -24207,15 +25057,15 @@ Examples:
24207
25057
  return;
24208
25058
  }
24209
25059
  console.log("");
24210
- console.log(pc36.bold("Open Agents Configuration"));
25060
+ console.log(pc38.bold("Open Agents Configuration"));
24211
25061
  console.log(hr8());
24212
- console.log(` ${pc36.dim("Backend:")} ${config.backendType}`);
24213
- console.log(` ${pc36.dim("Auth Mode:")} ${config.authMode ?? "none"}`);
24214
- console.log(` ${pc36.dim("Endpoint:")} ${config.endpoint}`);
24215
- console.log(` ${pc36.dim("API Key:")} ${config.apiKey ? maskSecret(config.apiKey) : pc36.dim("(none)")}`);
24216
- console.log(` ${pc36.dim("Repo:")} ${config.defaultRepo ?? pc36.dim("(none)")}`);
24217
- console.log(` ${pc36.dim("Branch:")} ${config.defaultBranch ?? pc36.dim("(none)")}`);
24218
- console.log(` ${pc36.dim("Timeout:")} ${config.timeoutMs ?? 3e4}ms`);
25062
+ console.log(` ${pc38.dim("Backend:")} ${config.backendType}`);
25063
+ console.log(` ${pc38.dim("Auth Mode:")} ${config.authMode ?? "none"}`);
25064
+ console.log(` ${pc38.dim("Endpoint:")} ${config.endpoint}`);
25065
+ console.log(` ${pc38.dim("API Key:")} ${config.apiKey ? maskSecret(config.apiKey) : pc38.dim("(none)")}`);
25066
+ console.log(` ${pc38.dim("Repo:")} ${config.defaultRepo ?? pc38.dim("(none)")}`);
25067
+ console.log(` ${pc38.dim("Branch:")} ${config.defaultBranch ?? pc38.dim("(none)")}`);
25068
+ console.log(` ${pc38.dim("Timeout:")} ${config.timeoutMs ?? 3e4}ms`);
24219
25069
  console.log(hr8());
24220
25070
  console.log("");
24221
25071
  });
@@ -24228,12 +25078,12 @@ Examples:
24228
25078
  }
24229
25079
  if (health.available) {
24230
25080
  console.log(
24231
- pc36.green("\u2713") + ` Backend reachable at ${config.endpoint} (${health.latencyMs}ms)` + (health.version ? ` version: ${health.version}` : "")
25081
+ pc38.green("\u2713") + ` Backend reachable at ${config.endpoint} (${health.latencyMs}ms)` + (health.version ? ` version: ${health.version}` : "")
24232
25082
  );
24233
25083
  } else {
24234
- console.log(pc36.red("\u2717") + ` Backend unavailable at ${config.endpoint} (${health.latencyMs}ms)`);
25084
+ console.log(pc38.red("\u2717") + ` Backend unavailable at ${config.endpoint} (${health.latencyMs}ms)`);
24235
25085
  if (health.error) {
24236
- console.log(pc36.dim(` ${health.error}`));
25086
+ console.log(pc38.dim(` ${health.error}`));
24237
25087
  }
24238
25088
  process.exitCode = 1;
24239
25089
  }
@@ -24247,22 +25097,22 @@ Examples:
24247
25097
  return;
24248
25098
  }
24249
25099
  if (sessions.length === 0) {
24250
- console.log(pc36.yellow("No sessions found.") + pc36.dim(" Run `growthub open-agents create` to start one."));
25100
+ console.log(pc38.yellow("No sessions found.") + pc38.dim(" Run `growthub open-agents create` to start one."));
24251
25101
  return;
24252
25102
  }
24253
25103
  console.log("");
24254
- console.log(pc36.bold("Agent Sessions") + pc36.dim(` (${sessions.length})`));
25104
+ console.log(pc38.bold("Agent Sessions") + pc38.dim(` (${sessions.length})`));
24255
25105
  console.log(hr8());
24256
25106
  for (const session of sessions) {
24257
- const truncatedPrompt = session.prompt ? pc36.dim(session.prompt.slice(0, 50)) : "";
25107
+ const truncatedPrompt = session.prompt ? pc38.dim(session.prompt.slice(0, 50)) : "";
24258
25108
  console.log(
24259
- ` ${statusColor2(session.status)} ${pc36.dim(session.sessionId.slice(0, 12))} ${sandboxBadge(session.sandboxState)} ${truncatedPrompt}`
25109
+ ` ${statusColor2(session.status)} ${pc38.dim(session.sessionId.slice(0, 12))} ${sandboxBadge(session.sandboxState)} ${truncatedPrompt}`
24260
25110
  );
24261
25111
  }
24262
25112
  console.log(hr8());
24263
25113
  console.log("");
24264
25114
  } catch (err) {
24265
- console.error(pc36.red("Failed to list sessions: " + err.message));
25115
+ console.error(pc38.red("Failed to list sessions: " + err.message));
24266
25116
  process.exitCode = 1;
24267
25117
  }
24268
25118
  });
@@ -24284,7 +25134,7 @@ Examples:
24284
25134
  }
24285
25135
  printSessionCard(session);
24286
25136
  } catch (err) {
24287
- console.error(pc36.red("Failed to create session: " + err.message));
25137
+ console.error(pc38.red("Failed to create session: " + err.message));
24288
25138
  process.exitCode = 1;
24289
25139
  }
24290
25140
  });
@@ -24302,7 +25152,7 @@ Examples:
24302
25152
  }
24303
25153
  printSessionCard(session);
24304
25154
  } catch (err) {
24305
- console.error(pc36.red("Failed to create session: " + err.message));
25155
+ console.error(pc38.red("Failed to create session: " + err.message));
24306
25156
  process.exitCode = 1;
24307
25157
  }
24308
25158
  });
@@ -24317,7 +25167,7 @@ Examples:
24317
25167
  printSessionCard(session);
24318
25168
  const events = await pollSessionEvents(config, session.sessionId);
24319
25169
  if (events.length > 0) {
24320
- console.log(pc36.bold("Latest Events") + pc36.dim(` (${events.length})`));
25170
+ console.log(pc38.bold("Latest Events") + pc38.dim(` (${events.length})`));
24321
25171
  console.log(hr8());
24322
25172
  for (const event of events.slice(-20)) {
24323
25173
  printEvent(event);
@@ -24326,7 +25176,7 @@ Examples:
24326
25176
  console.log("");
24327
25177
  }
24328
25178
  } catch (err) {
24329
- console.error(pc36.red("Failed to resume session: " + err.message));
25179
+ console.error(pc38.red("Failed to resume session: " + err.message));
24330
25180
  process.exitCode = 1;
24331
25181
  }
24332
25182
  });
@@ -24341,7 +25191,7 @@ Examples:
24341
25191
  printSessionCard(session);
24342
25192
  const events = await pollSessionEvents(config, session.sessionId);
24343
25193
  if (events.length > 0) {
24344
- console.log(pc36.bold("Latest Events") + pc36.dim(` (${events.length})`));
25194
+ console.log(pc38.bold("Latest Events") + pc38.dim(` (${events.length})`));
24345
25195
  console.log(hr8());
24346
25196
  for (const event of events.slice(-20)) {
24347
25197
  printEvent(event);
@@ -24350,7 +25200,7 @@ Examples:
24350
25200
  console.log("");
24351
25201
  }
24352
25202
  } catch (err) {
24353
- console.error(pc36.red("Failed to chat/resume session: " + err.message));
25203
+ console.error(pc38.red("Failed to chat/resume session: " + err.message));
24354
25204
  process.exitCode = 1;
24355
25205
  }
24356
25206
  });
@@ -24358,7 +25208,7 @@ Examples:
24358
25208
 
24359
25209
  // src/commands/qwen-code.ts
24360
25210
  import * as p25 from "@clack/prompts";
24361
- import pc37 from "picocolors";
25211
+ import pc39 from "picocolors";
24362
25212
 
24363
25213
  // src/runtime/qwen-code/index.ts
24364
25214
  init_home();
@@ -24653,7 +25503,7 @@ async function runQwenCodeHub(opts) {
24653
25503
  while (true) {
24654
25504
  const config = readQwenCodeConfig();
24655
25505
  const health = checkHealth(config.binaryPath, config.env);
24656
- const statusHint = health.status === "available" ? pc37.green("ready") : health.status === "degraded" ? pc37.yellow("degraded") : pc37.red("unavailable");
25506
+ const statusHint = health.status === "available" ? pc39.green("ready") : health.status === "degraded" ? pc39.yellow("degraded") : pc39.red("unavailable");
24657
25507
  const action = await p25.select({
24658
25508
  message: `Qwen Code CLI (${statusHint})`,
24659
25509
  options: [
@@ -24877,7 +25727,7 @@ init_github();
24877
25727
  // src/commands/integrations.ts
24878
25728
  init_bridge();
24879
25729
  import * as p27 from "@clack/prompts";
24880
- import pc39 from "picocolors";
25730
+ import pc41 from "picocolors";
24881
25731
  async function integrationsStatus(opts = {}) {
24882
25732
  const status = await describeIntegrationBridge();
24883
25733
  if (opts.json) {
@@ -24888,7 +25738,7 @@ async function integrationsStatus(opts = {}) {
24888
25738
  p27.log.warn(status.notice ?? "Not logged into Growthub.");
24889
25739
  return;
24890
25740
  }
24891
- p27.log.message(`Growthub: ${pc39.green("connected")} as ${status.growthubLogin ?? "?"}`);
25741
+ p27.log.message(`Growthub: ${pc41.green("connected")} as ${status.growthubLogin ?? "?"}`);
24892
25742
  if (!status.bridgeAvailable) {
24893
25743
  p27.log.info(status.notice ?? "Hosted integrations endpoint not available.");
24894
25744
  return;
@@ -24898,9 +25748,9 @@ async function integrationsStatus(opts = {}) {
24898
25748
  return;
24899
25749
  }
24900
25750
  for (const i of status.integrations) {
24901
- const ready = i.ready ? pc39.green("ready") : pc39.yellow("reauth needed");
25751
+ const ready = i.ready ? pc41.green("ready") : pc41.yellow("reauth needed");
24902
25752
  p27.log.message(
24903
- ` \u2022 ${pc39.cyan(i.provider)} ${ready} handle=${i.handle ?? "?"} scopes=[${(i.scopes ?? []).join(", ")}]`
25753
+ ` \u2022 ${pc41.cyan(i.provider)} ${ready} handle=${i.handle ?? "?"} scopes=[${(i.scopes ?? []).join(", ")}]`
24904
25754
  );
24905
25755
  }
24906
25756
  }
@@ -24915,7 +25765,7 @@ async function integrationsList(opts = {}) {
24915
25765
  return;
24916
25766
  }
24917
25767
  for (const i of integrations) {
24918
- p27.log.message(`${pc39.cyan(i.provider)} ${i.handle ?? ""} (ready=${i.ready})`);
25768
+ p27.log.message(`${pc41.cyan(i.provider)} ${i.handle ?? ""} (ready=${i.ready})`);
24919
25769
  }
24920
25770
  }
24921
25771
  async function integrationsProbe(opts) {
@@ -24938,7 +25788,7 @@ async function integrationsProbe(opts) {
24938
25788
  return;
24939
25789
  }
24940
25790
  p27.log.success(
24941
- `Resolved ${pc39.cyan(opts.provider)} credential via ${cred.source} handle=${cred.handle ?? "?"} scopes=[${(cred.scopes ?? []).join(", ")}]`
25791
+ `Resolved ${pc41.cyan(opts.provider)} credential via ${cred.source} handle=${cred.handle ?? "?"} scopes=[${(cred.scopes ?? []).join(", ")}]`
24942
25792
  );
24943
25793
  }
24944
25794
  function registerIntegrationsCommands(program2) {
@@ -24956,7 +25806,7 @@ function registerIntegrationsCommands(program2) {
24956
25806
 
24957
25807
  // src/commands/status.ts
24958
25808
  import * as p28 from "@clack/prompts";
24959
- import pc40 from "picocolors";
25809
+ import pc42 from "picocolors";
24960
25810
 
24961
25811
  // src/status/probes.ts
24962
25812
  import { spawnSync as spawnSync3 } from "node:child_process";
@@ -25389,25 +26239,25 @@ async function runStatuspageReport(opts = {}) {
25389
26239
  function levelGlyph(level) {
25390
26240
  switch (level) {
25391
26241
  case "operational":
25392
- return pc40.green("\u25CF");
26242
+ return pc42.green("\u25CF");
25393
26243
  case "degraded":
25394
- return pc40.yellow("\u25CF");
26244
+ return pc42.yellow("\u25CF");
25395
26245
  case "outage":
25396
- return pc40.red("\u25CF");
26246
+ return pc42.red("\u25CF");
25397
26247
  default:
25398
- return pc40.dim("\u25CB");
26248
+ return pc42.dim("\u25CB");
25399
26249
  }
25400
26250
  }
25401
26251
  function overallBanner(report) {
25402
26252
  switch (report.overallLevel) {
25403
26253
  case "operational":
25404
- return pc40.green("\u2713 All systems operational");
26254
+ return pc42.green("\u2713 All systems operational");
25405
26255
  case "degraded":
25406
- return pc40.yellow("\u26A0 Degraded \u2014 non-critical issues detected");
26256
+ return pc42.yellow("\u26A0 Degraded \u2014 non-critical issues detected");
25407
26257
  case "outage":
25408
- return pc40.red("\u2717 Outage \u2014 at least one critical component is down");
26258
+ return pc42.red("\u2717 Outage \u2014 at least one critical component is down");
25409
26259
  default:
25410
- return pc40.dim("? Status indeterminate");
26260
+ return pc42.dim("? Status indeterminate");
25411
26261
  }
25412
26262
  }
25413
26263
  function renderHuman(report) {
@@ -25417,14 +26267,14 @@ function renderHuman(report) {
25417
26267
  bucket.push(c);
25418
26268
  byCategory.set(c.category, bucket);
25419
26269
  }
25420
- p28.log.message(`${overallBanner(report)} ${pc40.dim(`(${report.summary})`)}`);
26270
+ p28.log.message(`${overallBanner(report)} ${pc42.dim(`(${report.summary})`)}`);
25421
26271
  for (const [category, list] of byCategory) {
25422
- p28.log.message(pc40.cyan(`
26272
+ p28.log.message(pc42.cyan(`
25423
26273
  ${category}`));
25424
26274
  for (const c of list) {
25425
- const crit = c.critical ? pc40.red("!") : pc40.dim("\xB7");
25426
- const lat = c.latencyMs !== void 0 ? pc40.dim(` ${c.latencyMs}ms`) : "";
25427
- const sa = c.superAdminOnly ? pc40.magenta(" [super-admin]") : "";
26275
+ const crit = c.critical ? pc42.red("!") : pc42.dim("\xB7");
26276
+ const lat = c.latencyMs !== void 0 ? pc42.dim(` ${c.latencyMs}ms`) : "";
26277
+ const sa = c.superAdminOnly ? pc42.magenta(" [super-admin]") : "";
25428
26278
  p28.log.message(` ${levelGlyph(c.level)} ${crit} ${c.label.padEnd(30)} ${c.summary}${lat}${sa}`);
25429
26279
  }
25430
26280
  }
@@ -25452,7 +26302,7 @@ function registerStatusCommands(program2) {
25452
26302
 
25453
26303
  // src/commands/starter.ts
25454
26304
  import * as p29 from "@clack/prompts";
25455
- import pc41 from "picocolors";
26305
+ import pc43 from "picocolors";
25456
26306
 
25457
26307
  // src/starter/init.ts
25458
26308
  init_service();
@@ -25552,14 +26402,14 @@ async function runStarterInit(opts) {
25552
26402
  return;
25553
26403
  }
25554
26404
  p29.outro(
25555
- `Workspace scaffolded at ${pc41.cyan(result.forkPath)}
26405
+ `Workspace scaffolded at ${pc43.cyan(result.forkPath)}
25556
26406
  kitId: ${result.kitId}
25557
- forkId: ${pc41.cyan(result.forkId)}
26407
+ forkId: ${pc43.cyan(result.forkId)}
25558
26408
  baseVersion: ${result.baseVersion}
25559
26409
  policyMode: remoteSyncMode=${result.policyMode}` + (result.remote ? `
25560
- remote: ${pc41.cyan(result.remote.htmlUrl)}` : "") + `
26410
+ remote: ${pc43.cyan(result.remote.htmlUrl)}` : "") + `
25561
26411
 
25562
- Next: ${pc41.dim(`growthub kit fork status ${result.forkId}`)}`
26412
+ Next: ${pc43.dim(`growthub kit fork status ${result.forkId}`)}`
25563
26413
  );
25564
26414
  } catch (err) {
25565
26415
  const msg = err instanceof Error ? err.message : String(err);
@@ -25590,7 +26440,7 @@ function registerStarterCommands(program2) {
25590
26440
 
25591
26441
  // src/commands/fleet.ts
25592
26442
  import * as p30 from "@clack/prompts";
25593
- import pc42 from "picocolors";
26443
+ import pc44 from "picocolors";
25594
26444
 
25595
26445
  // src/fleet/summary.ts
25596
26446
  import fs37 from "node:fs";
@@ -25915,20 +26765,20 @@ function buildAgentHealPlanDocument(reg, opts = {}) {
25915
26765
  function healthGlyph(level) {
25916
26766
  switch (level) {
25917
26767
  case "clean":
25918
- return pc42.green("\u25CF");
26768
+ return pc44.green("\u25CF");
25919
26769
  case "drift-minor":
25920
- return pc42.cyan("\u25CF");
26770
+ return pc44.cyan("\u25CF");
25921
26771
  case "drift-major":
25922
- return pc42.yellow("\u25CF");
26772
+ return pc44.yellow("\u25CF");
25923
26773
  case "awaiting-confirmation":
25924
- return pc42.magenta("\u25D0");
26774
+ return pc44.magenta("\u25D0");
25925
26775
  case "error":
25926
- return pc42.red("\u25CF");
26776
+ return pc44.red("\u25CF");
25927
26777
  default:
25928
- return pc42.dim("\u25CB");
26778
+ return pc44.dim("\u25CB");
25929
26779
  }
25930
26780
  }
25931
- function truncate3(s, n) {
26781
+ function truncate4(s, n) {
25932
26782
  if (!s) return "";
25933
26783
  return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
25934
26784
  }
@@ -25939,7 +26789,7 @@ async function fleetView(opts) {
25939
26789
  return;
25940
26790
  }
25941
26791
  p30.log.message(
25942
- `Fleet: ${pc42.cyan(String(fleet.totalForks))} fork(s) | remote=${fleet.forksWithRemote} awaiting=${fleet.forksAwaitingConfirmation} pending-approvals=${fleet.pendingApprovalCount}`
26792
+ `Fleet: ${pc44.cyan(String(fleet.totalForks))} fork(s) | remote=${fleet.forksWithRemote} awaiting=${fleet.forksAwaitingConfirmation} pending-approvals=${fleet.pendingApprovalCount}`
25943
26793
  );
25944
26794
  p30.log.message(
25945
26795
  ` Health \u2192 clean=${fleet.byHealth.clean} drift-minor=${fleet.byHealth["drift-minor"]} drift-major=${fleet.byHealth["drift-major"]} awaiting=${fleet.byHealth["awaiting-confirmation"]} error=${fleet.byHealth.error} unknown=${fleet.byHealth.unknown}`
@@ -25951,15 +26801,15 @@ async function fleetView(opts) {
25951
26801
  for (const f of fleet.forks) renderForkRow(f);
25952
26802
  }
25953
26803
  function renderForkRow(f) {
25954
- const label = truncate3(f.label ?? f.forkId, 28).padEnd(28);
25955
- const kit = truncate3(f.kitId, 34).padEnd(34);
26804
+ const label = truncate4(f.label ?? f.forkId, 28).padEnd(28);
26805
+ const kit = truncate4(f.kitId, 34).padEnd(34);
25956
26806
  const base = f.baseVersion.padEnd(8);
25957
26807
  const upstream = (f.upstreamVersion ?? "?").padEnd(8);
25958
26808
  const driftCounts = `files=${f.fileDriftCount} pkgs=${f.packageDriftCount}`;
25959
- const pending = f.pendingConfirmationJobs > 0 ? pc42.magenta(` awaits=${f.pendingConfirmationJobs}`) : "";
25960
- const remote = f.remote ? pc42.dim(` ${f.remote.owner}/${f.remote.repo}`) : "";
26809
+ const pending = f.pendingConfirmationJobs > 0 ? pc44.magenta(` awaits=${f.pendingConfirmationJobs}`) : "";
26810
+ const remote = f.remote ? pc44.dim(` ${f.remote.owner}/${f.remote.repo}`) : "";
25961
26811
  p30.log.message(
25962
- ` ${healthGlyph(f.health)} ${label} ${pc42.dim(kit)} ${base} \u2192 ${upstream} ${pc42.dim(driftCounts)}${pending}${remote}`
26812
+ ` ${healthGlyph(f.health)} ${label} ${pc44.dim(kit)} ${base} \u2192 ${upstream} ${pc44.dim(driftCounts)}${pending}${remote}`
25963
26813
  );
25964
26814
  }
25965
26815
  async function fleetDrift(opts) {
@@ -25974,7 +26824,7 @@ async function fleetDrift(opts) {
25974
26824
  return;
25975
26825
  }
25976
26826
  p30.log.message(
25977
- `Fleet drift: ${pc42.cyan(String(withDrift.length))} of ${fleet.totalForks} fork(s) have drift.`
26827
+ `Fleet drift: ${pc44.cyan(String(withDrift.length))} of ${fleet.totalForks} fork(s) have drift.`
25978
26828
  );
25979
26829
  p30.log.message(
25980
26830
  ` By severity \u2192 none=${fleet.bySeverity.none} info=${fleet.bySeverity.info} warning=${fleet.bySeverity.warning} critical=${fleet.bySeverity.critical}`
@@ -25994,7 +26844,7 @@ async function fleetDriftSummary(opts) {
25994
26844
  console.log(JSON.stringify({ summary, narrative }, null, 2));
25995
26845
  return;
25996
26846
  }
25997
- p30.log.message(pc42.cyan(`Drift summary \u2014 ${reg.forkId} (${summary.fromVersion} \u2192 ${summary.toVersion})`));
26847
+ p30.log.message(pc44.cyan(`Drift summary \u2014 ${reg.forkId} (${summary.fromVersion} \u2192 ${summary.toVersion})`));
25998
26848
  for (const line of narrative) p30.log.message(` ${line}`);
25999
26849
  const sections = [
26000
26850
  ["safe additions", summary.buckets.safeAdditions],
@@ -26007,13 +26857,13 @@ async function fleetDriftSummary(opts) {
26007
26857
  ];
26008
26858
  for (const [label, items] of sections) {
26009
26859
  if (items.length === 0) continue;
26010
- p30.log.message(pc42.dim(` \u2014 ${label} (${items.length}) \u2014`));
26011
- for (const item of items) p30.log.message(` \xB7 ${item.path} ${pc42.dim(item.note)}`);
26860
+ p30.log.message(pc44.dim(` \u2014 ${label} (${items.length}) \u2014`));
26861
+ for (const item of items) p30.log.message(` \xB7 ${item.path} ${pc44.dim(item.note)}`);
26012
26862
  }
26013
26863
  if (summary.buckets.packageAdditions.length || summary.buckets.packageUpgrades.length) {
26014
- p30.log.message(pc42.dim(` \u2014 dependency drift \u2014`));
26864
+ p30.log.message(pc44.dim(` \u2014 dependency drift \u2014`));
26015
26865
  for (const d of summary.buckets.packageAdditions) {
26016
- p30.log.message(` + ${d.packageName}@${d.toVersion} ${pc42.dim("(added upstream)")}`);
26866
+ p30.log.message(` + ${d.packageName}@${d.toVersion} ${pc44.dim("(added upstream)")}`);
26017
26867
  }
26018
26868
  for (const d of summary.buckets.packageUpgrades) {
26019
26869
  p30.log.message(` \u2191 ${d.packageName} ${d.fromVersion ?? "?"} \u2192 ${d.toVersion}`);
@@ -26039,14 +26889,14 @@ async function fleetPolicy(opts) {
26039
26889
  console.log(JSON.stringify({ count: rows.length, rows }, null, 2));
26040
26890
  return;
26041
26891
  }
26042
- p30.log.message(pc42.cyan(`Fleet policy matrix (${rows.length} fork(s))`));
26892
+ p30.log.message(pc44.cyan(`Fleet policy matrix (${rows.length} fork(s))`));
26043
26893
  for (const r of rows) {
26044
- const label = truncate3(r.label ?? r.forkId, 28).padEnd(28);
26894
+ const label = truncate4(r.label ?? r.forkId, 28).padEnd(28);
26045
26895
  const aa = r.autoApprove.padEnd(9);
26046
26896
  const ad = r.autoApproveDepUpdates.padEnd(9);
26047
26897
  const rs = r.remoteSyncMode.padEnd(6);
26048
26898
  const ut = String(r.untouchableCount).padStart(3);
26049
- const remote = r.hasRemote ? pc42.green("+") : pc42.dim("\xB7");
26899
+ const remote = r.hasRemote ? pc44.green("+") : pc44.dim("\xB7");
26050
26900
  p30.log.message(
26051
26901
  ` ${label} autoApprove=${aa} deps=${ad} remote=${rs} untouchable=${ut} ${remote}`
26052
26902
  );
@@ -26062,19 +26912,19 @@ async function fleetApprovals(opts) {
26062
26912
  p30.log.success("Approval queue is empty.");
26063
26913
  return;
26064
26914
  }
26065
- p30.log.message(pc42.cyan(`Approval queue: ${queue.length} job(s) awaiting confirmation`));
26915
+ p30.log.message(pc44.cyan(`Approval queue: ${queue.length} job(s) awaiting confirmation`));
26066
26916
  for (const entry of queue) {
26067
26917
  p30.log.message(
26068
- ` \xB7 ${pc42.cyan(entry.jobId)} fork=${entry.forkLabel ?? entry.forkId} created=${entry.createdAt.slice(0, 19)}`
26918
+ ` \xB7 ${pc44.cyan(entry.jobId)} fork=${entry.forkLabel ?? entry.forkId} created=${entry.createdAt.slice(0, 19)}`
26069
26919
  );
26070
26920
  for (const path47 of entry.pendingPaths.slice(0, 6)) {
26071
- p30.log.message(` ${pc42.dim("awaits")} ${path47}`);
26921
+ p30.log.message(` ${pc44.dim("awaits")} ${path47}`);
26072
26922
  }
26073
26923
  if (entry.pendingPaths.length > 6) {
26074
- p30.log.message(` ${pc42.dim(`\u2026 +${entry.pendingPaths.length - 6} more`)}`);
26924
+ p30.log.message(` ${pc44.dim(`\u2026 +${entry.pendingPaths.length - 6} more`)}`);
26075
26925
  }
26076
26926
  p30.log.message(
26077
- ` ${pc42.dim("resume:")} growthub kit fork confirm --job-id ${entry.jobId}`
26927
+ ` ${pc44.dim("resume:")} growthub kit fork confirm --job-id ${entry.jobId}`
26078
26928
  );
26079
26929
  }
26080
26930
  }
@@ -26086,20 +26936,20 @@ async function fleetAgentPlan(opts) {
26086
26936
  console.log(JSON.stringify(doc, null, 2));
26087
26937
  return;
26088
26938
  }
26089
- p30.log.message(pc42.cyan(`Agent heal plan \u2014 ${reg.forkId}`));
26939
+ p30.log.message(pc44.cyan(`Agent heal plan \u2014 ${reg.forkId}`));
26090
26940
  p30.log.message(` ${doc.summary}`);
26091
26941
  for (const line of doc.narrative) p30.log.message(` ${line}`);
26092
26942
  if (doc.awaitsConfirmation.length > 0) {
26093
- p30.log.message(pc42.magenta(` Awaiting confirmation on:`));
26943
+ p30.log.message(pc44.magenta(` Awaiting confirmation on:`));
26094
26944
  for (const p210 of doc.awaitsConfirmation) p30.log.message(` \xB7 ${p210}`);
26095
26945
  p30.log.message(
26096
- pc42.dim(
26946
+ pc44.dim(
26097
26947
  ` Next: growthub kit fork heal ${reg.forkId} (will park in awaiting_confirmation until resumed)`
26098
26948
  )
26099
26949
  );
26100
26950
  } else if (doc.plan.actions.length > 0) {
26101
26951
  p30.log.message(
26102
- pc42.dim(` Next: growthub kit fork heal ${reg.forkId} (${doc.plan.actions.length} safe action(s) ready)`)
26952
+ pc44.dim(` Next: growthub kit fork heal ${reg.forkId} (${doc.plan.actions.length} safe action(s) ready)`)
26103
26953
  );
26104
26954
  }
26105
26955
  }
@@ -26641,7 +27491,7 @@ async function runDiscoveryHub(opts) {
26641
27491
  },
26642
27492
  {
26643
27493
  value: "workflows",
26644
- label: workflowAccess.state === "ready" ? "\u{1F517} Workflows" : "\u{1F517} Workflows" + pc43.dim(" (locked)"),
27494
+ label: workflowAccess.state === "ready" ? "\u{1F517} Workflows" : "\u{1F517} Workflows" + pc45.dim(" (locked)"),
26645
27495
  hint: workflowAccess.state === "ready" ? "CMS contracts, dynamic pipelines, and saved workflows" : workflowAccess.reason
26646
27496
  },
26647
27497
  {