@ghostystudio/cli 0.68.0 → 0.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -114,6 +114,10 @@ Every command has its own help with examples: `ghosty <command> --help` or `ghos
114
114
 
115
115
  Exit codes: `0` ok · `1` API error · `2` usage error · `3` not signed in.
116
116
 
117
+ ### Changes in 0.69.0
118
+
119
+ - `factory runs why` puts an unmet plan criterion on top (`approved_unmet_criterion`): approved without the preview a criterion asked for, merged without preview, smoke failed on the merged commit, or a CI criterion approved with CI `none`. Each one is listed with the criterion's text and the evidence (`acceptance[]` in `--json`). A saved analysis is redone if the run had events after it.
120
+
117
121
  ### Changes in 0.68.0
118
122
 
119
123
  - New `spaces members ls|add|rm <workspace> [email]`: a workspace's people without the Members screen (owner, admin or staff). `--role admin` lets them invite and remove; `--until 2026-10-28` or `--until 14d` gives a temporary seat that is removed automatically — for reviewer accounts (Meta, Google, Apple).
@@ -169,7 +173,7 @@ Exit codes: `0` ok · `1` API error · `2` usage error · `3` not signed in.
169
173
 
170
174
  ### Changes in 0.56.0
171
175
 
172
- - `factory runs why <run> [--refresh]`: why a run got stuck or failed — category, impact, the critical step with its evidence and what to change next time (a healthy run doesn't call the model).
176
+ - `factory runs why <run> [--refresh]`: why a run got stuck or failed — category, impact, the critical step with its evidence and what to change next time (a healthy run doesn't call the model). It first checks the approved plan's criteria against the verdict: a criterion "in the preview" approved without the preview ready comes out on top as `approved_unmet_criterion`.
173
177
  - `factory runs show --timing` lists stuck patterns (a command open 8+ min, the same command repeated, errors in a row, going back and forth, apt install in a box); `runs stats` counts runs with stuck alerts.
174
178
 
175
179
  ### Changes in 0.55.0
package/dist/index.js CHANGED
@@ -8478,7 +8478,7 @@ async function postLong(path, body, timeoutMs = 9e5) {
8478
8478
  const req = httpsRequest(`${base}${path}`, {
8479
8479
  method: "POST",
8480
8480
  timeout: timeoutMs,
8481
- headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.68.0"}`, "content-type": "application/json", "content-length": Buffer.byteLength(data) }
8481
+ headers: { authorization: `Bearer ${token}`, "user-agent": `ghosty-cli/${"0.69.0"}`, "content-type": "application/json", "content-length": Buffer.byteLength(data) }
8482
8482
  }, (res) => {
8483
8483
  let buf = "";
8484
8484
  res.on("data", (c) => buf += c);
@@ -8520,7 +8520,7 @@ async function request(path, opts = {}, retried = false) {
8520
8520
  method: opts.method ?? (opts.body !== void 0 || opts.raw !== void 0 ? "POST" : "GET"),
8521
8521
  headers: {
8522
8522
  authorization: `Bearer ${token}`,
8523
- "user-agent": `ghosty-cli/${"0.68.0"}`,
8523
+ "user-agent": `ghosty-cli/${"0.69.0"}`,
8524
8524
  "accept-language": lang(),
8525
8525
  ...opts.body !== void 0 ? { "content-type": "application/json" } : {},
8526
8526
  ...opts.headers
@@ -10492,7 +10492,7 @@ async function call(path, v, init = {}) {
10492
10492
  "x-ghosty-ts": ts,
10493
10493
  "x-ghosty-sig": sig,
10494
10494
  "content-type": "application/json",
10495
- "user-agent": `ghosty-cli/${"0.68.0"}`
10495
+ "user-agent": `ghosty-cli/${"0.69.0"}`
10496
10496
  },
10497
10497
  body: method === "GET" ? void 0 : raw
10498
10498
  });
@@ -13135,7 +13135,7 @@ var HELPS_ES = {
13135
13135
  "Qui\xE9n es @plan o @build: ghosty agents ls --handle plan --workspace SLUG.",
13136
13136
  "stats: pedidos, % mezclados, mediana de minutos hasta el PR y hasta el merge, vueltas @check\u2192@build y CI rojo por pedido, y costo por pedido y por PR mezclado. El costo incluye el primer turno de @plan en el hilo, antes de que naciera el pedido.",
13137
13137
  "--timing lee la transcripci\xF3n de cada rol: los motores sin una (ACP) salen con minutos y costo, pero sin comandos. Tambi\xE9n lista los atascos: un comando abierto 8+ min, el mismo comando 4 veces, el mismo error 3 veces, ir y venir entre dos acciones, o apt install dentro de una caja.",
13138
- "why: si el pedido no fue sano (atascos, @build de m\xE1s de 30 min, vueltas, CI rojo, escalado), una categor\xEDa (missing_service, unresolved_build_or_tests, fixed_strategy\u2026), el paso cr\xEDtico con su evidencia y qu\xE9 cambiar la pr\xF3xima vez. Un pedido sano no llama al modelo. Cuando un pedido cierra sin ser sano, el room recibe este resumen en su hilo.",
13138
+ "why: si el pedido no fue sano (atascos, @build de m\xE1s de 30 min, vueltas, CI rojo, escalado), una categor\xEDa (missing_service, unresolved_build_or_tests, fixed_strategy\u2026), el paso cr\xEDtico con su evidencia y qu\xE9 cambiar la pr\xF3xima vez. Primero cruza los criterios del plan aprobado con la evidencia: aprobado sin la preview que ped\xEDa un criterio, mezclado sin preview, smoke rojo sobre el commit mezclado o criterio de CI con CI none \u2192 approved_unmet_criterion, arriba de cualquier atasco. Un pedido sano no llama al modelo. Cuando un pedido cierra sin ser sano, el room recibe este resumen en su hilo.",
13139
13139
  "Mientras un rol trabaja, si se atora el room recibe un \u23F3 en el hilo y al rol se le dice qu\xE9 revisar; desde la segunda vez en el mismo pedido, quien lo pidi\xF3 recibe un push."
13140
13140
  ]
13141
13141
  }
@@ -13980,7 +13980,7 @@ HELPS.factory = {
13980
13980
  ["--yes", "rename: skip the confirmation (required without a terminal)"]
13981
13981
  ],
13982
13982
  examples: ["ghosty factory runs ls --workspace business --room mailmask", "ghosty factory runs show 15 --workspace business", "ghosty factory runs show 13 --timing --workspace mercadito-verde", "ghosty factory runs why 13 --workspace mercadito-verde", "ghosty factory runs stats --since 7d --workspace mercadito-verde", 'ghosty factory runs rename 15 "Docs del CLI al d\xEDa" --workspace business --dry-run'],
13983
- notes: ["Reading needs membership in the workspace; rename needs owner, admin or Ghosty staff, and is logged (factory.run_rename). The room's card picks the new title up on its next refresh.", "Who is @plan or @build: ghosty agents ls --handle plan --workspace SLUG.", "stats: runs, % merged, median minutes to PR and to merge, @check\u2192@build loops and red CI per run, and cost per run and per merged PR. The cost counts @plan's first turn in the thread, before the run existed.", "--timing reads each role's transcript: engines without one (ACP) show minutes and cost but no commands. It also lists stuck patterns: a command open 8+ min, the same command 4 times, the same error 3 times, going back and forth, or apt install inside a box.", "why: if the run wasn't healthy (stuck patterns, @build over 30 min, loops, red CI, escalated), a category (missing_service, unresolved_build_or_tests, fixed_strategy\u2026), the critical step with its evidence and what to change next time. A healthy run doesn't call the model. When a run closes unhealthy, the room gets this summary in its thread.", "While a role works, if it gets stuck the room gets a \u23F3 message in the thread and the role is told what to check; from the second time in the same run, whoever asked gets a push."],
13983
+ notes: ["Reading needs membership in the workspace; rename needs owner, admin or Ghosty staff, and is logged (factory.run_rename). The room's card picks the new title up on its next refresh.", "Who is @plan or @build: ghosty agents ls --handle plan --workspace SLUG.", "stats: runs, % merged, median minutes to PR and to merge, @check\u2192@build loops and red CI per run, and cost per run and per merged PR. The cost counts @plan's first turn in the thread, before the run existed.", "--timing reads each role's transcript: engines without one (ACP) show minutes and cost but no commands. It also lists stuck patterns: a command open 8+ min, the same command 4 times, the same error 3 times, going back and forth, or apt install inside a box.", "why: if the run wasn't healthy (stuck patterns, @build over 30 min, loops, red CI, escalated), a category (missing_service, unresolved_build_or_tests, fixed_strategy\u2026), the critical step with its evidence and what to change next time. First it checks the approved plan's criteria against the evidence: approved without the preview a criterion asked for, merged without preview, smoke failed on the merged commit, or a CI criterion with CI none \u2192 approved_unmet_criterion, above any stuck pattern. A healthy run doesn't call the model. When a run closes unhealthy, the room gets this summary in its thread.", "While a role works, if it gets stuck the room gets a \u23F3 message in the thread and the role is told what to check; from the second time in the same run, whoever asked gets a push."],
13984
13984
  learn: `${REF}#fabrica`
13985
13985
  };
13986
13986
  function helpText(cmd) {
@@ -14703,6 +14703,8 @@ ${dim(`${t("Detail", "Detalle")}: ghosty factory runs show <run> --workspace ${r
14703
14703
  const impact = { high: t("high", "alto"), medium: t("medium", "medio"), low: t("low", "bajo") }[w.impact] ?? w.impact;
14704
14704
  return [
14705
14705
  `${bold(`#${w.runId}`)} ${red(w.category)} ${dim(`\xB7 ${t("impact", "impacto")} ${impact} \xB7 ${w.source === "model" ? w.model ?? "model" : t("rules", "reglas")} \xB7 ${short2(w.createdAt)}`)}`,
14706
+ ...w.acceptance?.length ? [bold(red(t("Unmet criterion, approved anyway", "Criterio incumplido y aprobado"))), ...w.acceptance.map((g) => ` ${g.at ? hhmm(g.at) : "\u2014"} ${red(g.rule)} \xAB${g.criterion}\xBB
14707
+ ${dim(g.evidence)}`), ""] : [],
14706
14708
  w.summary,
14707
14709
  dim(`${t("signals", "se\xF1ales")}: ${w.reasons.join("; ")}`),
14708
14710
  ...w.criticalStep ? ["", bold(t("Critical step", "Paso cr\xEDtico")), ` ${w.criticalStep.at ? hhmm(w.criticalStep.at) : "\u2014"} @${w.criticalStep.role ?? "?"} ${dim(w.criticalStep.command ?? "")}`, ` ${w.criticalStep.evidence}`] : [],
@@ -15712,7 +15714,7 @@ async function main() {
15712
15714
  const tokens = splitTokens(pos, v);
15713
15715
  globals.token = tokens.session;
15714
15716
  globals.profile = v.profile;
15715
- if (v.version) return out({ version: "0.68.0" }, () => "0.68.0");
15717
+ if (v.version) return out({ version: "0.69.0" }, () => "0.69.0");
15716
15718
  for (const n of normalizeArgs(pos, v)) if (!globals.json) info(dim(n));
15717
15719
  const context = (await readConfig()).workspace;
15718
15720
  if (!explicitToken()?.startsWith("gat_")) {
@@ -15889,7 +15891,7 @@ async function main() {
15889
15891
  throw unknown(cmd, cmd, COMMANDS, "ghosty --help");
15890
15892
  }
15891
15893
  }
15892
- var notice = updateNotice("0.68.0").catch(() => null);
15894
+ var notice = updateNotice("0.69.0").catch(() => null);
15893
15895
  main().then(
15894
15896
  async () => {
15895
15897
  const n = await notice;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghostystudio/cli",
3
- "version": "0.68.0",
3
+ "version": "0.69.0",
4
4
  "description": "Official Ghosty Studio CLI — configure, test and chat with your agents from the terminal. Built for humans and coding agents.",
5
5
  "type": "module",
6
6
  "bin": {