@sleds/cli 0.1.42 → 0.1.44

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/sleds.mjs +977 -430
  2. package/package.json +1 -1
package/dist/sleds.mjs CHANGED
@@ -21,6 +21,9 @@ var p = (input, output, cacheWrite, cacheWrite1h, cacheRead) => ({ input, output
21
21
  }), OPENAI_PRICES, byLength = (t) => Object.keys(t).sort((a, b) => b.length - a.length), ANTHROPIC_KEYS, OPENAI_KEYS;
22
22
  var init_pricing = __esm(() => {
23
23
  ANTHROPIC_PRICES = {
24
+ "claude-opus-5-5": p(4, 20, 5, 8, 0.2),
25
+ "claude-sonnet-5-5": p(2, 10, 2.5, 4, 0.1),
26
+ "claude-haiku-5-5": p(0.1, 0.5, 0.125, 0.2, 0.01),
24
27
  "claude-fable-5-1": p(10, 50, 12.5, 20, 0.25),
25
28
  "claude-mythos-5-1": p(10, 50, 12.5, 20, 0.25),
26
29
  "claude-fable-5": p(10, 50, 12.5, 20, 1),
@@ -794,10 +797,10 @@ var init_verbs = __esm(() => {
794
797
  {
795
798
  id: "update",
796
799
  group: "meter",
797
- want: "Change an item — its title, why, done, description, due day, what it sits under, or what it touches",
798
- mcp: "update {project, ask?, why?, done?, smallest?, touches?, demand?, description?, due?, parent?, repos?, sensitivity?}",
800
+ want: "Change an item — its title, why, done, worth, description, due day, what it sits under, or what it touches",
801
+ mcp: "update {project, ask?, why?, done?, smallest?, touches?, demand?, worth?, carry?, description?, due?, parent?, repos?, sensitivity?}",
799
802
  app: "Work › the item › click a field",
800
- how: "The filer, an approver or an admin changes an item from chat or by clicking the field in the app; every change says who and through what (via Claude · Cowork, via ChatGPT, in the app) and the record keeps before and after. A change to the ask, done or smallest marks the band stale with a Re-size at hand — never re-sized silently. A mirrored ticket is the tracker's word and is not changed here."
803
+ how: "The filer, an approver or an admin changes an item from chat or by clicking the field in the app; every change says who and through what (via Claude · Cowork, via ChatGPT, in the app) and the record keeps before and after. A change to the ask, done or smallest marks the band stale with a Re-size at hand — never re-sized silently. Worth is the person's word in their words ('high · Acme renewal', '$5k–20k'; null clears it); on an epic, `carry: true` puts it on each child that has none, each child's record signed the same way. A mirrored ticket is the tracker's word and is not changed here."
801
804
  },
802
805
  {
803
806
  id: "archive",
@@ -1083,6 +1086,112 @@ var init_verbs = __esm(() => {
1083
1086
  ];
1084
1087
  });
1085
1088
 
1089
+ // ../../packages/shared/src/intake/forms.ts
1090
+ function norm(label) {
1091
+ return label.replace(/[*_`~]/g, "").replace(/\(s\)/gi, "s").replace(/[:?]+\s*$/, "").replace(/,\s*including\b.*$/i, "").replace(/\s+/g, " ").trim().toLowerCase();
1092
+ }
1093
+ function plain(s) {
1094
+ return s.replace(/[*_`~]+/g, "").replace(/\s+/g, " ").trim();
1095
+ }
1096
+ function titleOf(s, max = 80) {
1097
+ const t = plain(s);
1098
+ const first = /^(.+?[.!?])(\s|$)/.exec(t)?.[1] ?? t;
1099
+ if (first.length <= max)
1100
+ return first;
1101
+ const cut = first.slice(0, max);
1102
+ const sp = cut.lastIndexOf(" ");
1103
+ return `${(sp > max / 2 ? cut.slice(0, sp) : cut).replace(/[,;:\s]+$/, "")}…`;
1104
+ }
1105
+ function readForm(text) {
1106
+ const lines = text.split(/\r?\n/);
1107
+ for (const def of FORMS) {
1108
+ const found = [];
1109
+ let cur = null;
1110
+ let known = 0;
1111
+ for (const raw of lines) {
1112
+ const line = raw.trim();
1113
+ if (!line)
1114
+ continue;
1115
+ const bold = /^\*[^*]{2,80}\*:?$/.test(line);
1116
+ const whole = line.length <= 80 ? slotOf(def, line) : null;
1117
+ const inline = /^\**([^:*]{2,60}?)\**\s*:\s*(.+)$/.exec(line);
1118
+ const slotInline = inline ? slotOf(def, inline[1] ?? "") : null;
1119
+ if (whole && (bold || !inline)) {
1120
+ cur = { label: plain(norm(line)), slot: whole, value: [] };
1121
+ found.push(cur);
1122
+ known++;
1123
+ } else if (slotInline && inline) {
1124
+ cur = { label: plain(norm(inline[1] ?? "")), slot: slotInline, value: [inline[2] ?? ""] };
1125
+ found.push(cur);
1126
+ known++;
1127
+ } else if (bold && cur) {
1128
+ cur = { label: plain(line.replace(/:$/, "")), slot: null, value: [] };
1129
+ found.push(cur);
1130
+ } else if (cur)
1131
+ cur.value.push(line);
1132
+ }
1133
+ if (known < def.min)
1134
+ continue;
1135
+ const val = (f) => plain(f.value.join(" "));
1136
+ const one = (slot) => found.find((f) => f.slot === slot && val(f));
1137
+ const ask = one("ask");
1138
+ const users = one("users");
1139
+ const sid = one("sid");
1140
+ const loc = one("location");
1141
+ const clients = one("clients");
1142
+ const rev = one("revenue");
1143
+ const n = clients ? val(clients) : "";
1144
+ const clientsText = n ? /^\d+$/.test(n) ? `${n} client${n === "1" ? "" : "s"} affected` : `clients affected: ${n}` : "";
1145
+ const r = rev ? val(rev) : "";
1146
+ const revenue = YES.test(r) ? true : NO.test(r) ? false : undefined;
1147
+ const revText = revenue === true ? "Impacting revenue" : revenue === false ? "No revenue impact" : "";
1148
+ const unknown = found.filter((f) => f.slot === null && val(f)).map((f) => `${f.label}: ${val(f)}`);
1149
+ const who = [
1150
+ users ? `Users: ${val(users)}` : "",
1151
+ sid ? `SID: ${val(sid)}` : "",
1152
+ loc ? `Location ${val(loc)}` : "",
1153
+ ...unknown
1154
+ ].filter(Boolean);
1155
+ const touches = who.join(" · ");
1156
+ const demand = [clientsText, revText].filter(Boolean).join(" · ");
1157
+ const details = [...who, clientsText, revText].filter(Boolean).join(" · ");
1158
+ return {
1159
+ form: def.name,
1160
+ ...ask ? { ask: val(ask) } : {},
1161
+ ...details ? { details } : {},
1162
+ ...touches ? { touches } : {},
1163
+ ...demand ? { demand } : {},
1164
+ ...revenue !== undefined ? { revenue } : {}
1165
+ };
1166
+ }
1167
+ return null;
1168
+ }
1169
+ var FORMS, YES, NO, slotOf = (def, label) => {
1170
+ const n = norm(label);
1171
+ for (const [re, slot] of def.labels)
1172
+ if (re.test(n))
1173
+ return slot;
1174
+ return null;
1175
+ };
1176
+ var init_forms = __esm(() => {
1177
+ FORMS = [
1178
+ {
1179
+ name: "Create Tech Support Ticket",
1180
+ labels: [
1181
+ [/^users? experiencing\b/, "users"],
1182
+ [/^sids?\b/, "sid"],
1183
+ [/^location ids?\b/, "location"],
1184
+ [/^issue description\b/, "ask"],
1185
+ [/^(?:number of )?clients? affected\b|^number of clients\b/, "clients"],
1186
+ [/\bimpacting revenue\b|\brevenue impact\b/, "revenue"]
1187
+ ],
1188
+ min: 3
1189
+ }
1190
+ ];
1191
+ YES = /^(yes|y|yep|true|definitely|it is)\b/i;
1192
+ NO = /^(no|n|nope|false|not)\b/i;
1193
+ });
1194
+
1086
1195
  // ../../packages/shared/src/intake/brief.ts
1087
1196
  function labelOf(line) {
1088
1197
  const h = /^#{1,6}\s+(.+?)\s*#*\s*$/.exec(line);
@@ -1155,8 +1264,12 @@ function worthFromAnswer(answer) {
1155
1264
  function draftBrief(input) {
1156
1265
  const text = (input.text ?? "").trim();
1157
1266
  const a = input.answers ?? {};
1158
- const { preamble, byKey } = sections(text);
1159
- const askText = a.ask?.trim() || askFrom(text, preamble);
1267
+ const form = readForm(text);
1268
+ const parsed = sections(text);
1269
+ const preamble = parsed.preamble;
1270
+ const byKey = form ? { touches: form.touches, demand: form.demand } : parsed.byKey;
1271
+ const fromText = form?.ask ? form.ask : askFrom(text, preamble);
1272
+ const askText = a.ask?.trim() || (fromText ? titleOf(fromText) : undefined);
1160
1273
  if (!askText)
1161
1274
  return null;
1162
1275
  const ask = a.ask?.trim() ? { text: clip(a.ask, MAX_ASK), from: "filer" } : { text: clip(askText, MAX_ASK), from: "artifact" };
@@ -1288,12 +1401,13 @@ var MAX_FIELD = 280, MAX_ASK = 120, MAX_SOURCES = 12, QUESTIONS, REQUIRED_TO_FIL
1288
1401
  }, fromWord = (f) => f.from === "filer" ? "from you" : f.from === "product" ? "from the product map" : "from what you sent";
1289
1402
  var init_brief = __esm(() => {
1290
1403
  init_worth();
1404
+ init_forms();
1291
1405
  QUESTIONS = {
1292
- why: "Who is it for, and why now?",
1293
- done: "What does done look like, in your words?",
1294
- smallest: "What is the smallest version still worth doing?",
1295
- worth: "What is it worth to the business — a customer, a number, or high / medium / low?",
1296
- touches: "What does it touch — which product areas or systems, and where in the product would it live?",
1406
+ why: "Who is this for, and why does it matter now?",
1407
+ done: "How will we know it's done?",
1408
+ smallest: "What's the smallest version that would still help?",
1409
+ worth: "How important is this: high, medium, or low? If a specific customer is waiting on it, tell me who.",
1410
+ touches: "Which part of the product is this about?",
1297
1411
  demand: "How many people have asked for this, or how often does it come up?"
1298
1412
  };
1299
1413
  REQUIRED_TO_FILE = ["why", "done"];
@@ -1554,7 +1668,8 @@ function intakePlan(g) {
1554
1668
  card: g.card ? [...g.card] : base.card,
1555
1669
  limits: [...g.limits ?? []],
1556
1670
  followed: [...g.followed ?? []],
1557
- text: g.text ?? ""
1671
+ text: g.text ?? "",
1672
+ ...g.references ? { references: g.references } : {}
1558
1673
  };
1559
1674
  }
1560
1675
  function planOpen(b, plan, extra = {}) {
@@ -1586,11 +1701,14 @@ var init_intake = __esm(() => {
1586
1701
  ORDER = ["why", "done", "smallest", "worth", "touches", "demand"];
1587
1702
  DEFAULT_CARD = CARD_FIELDS.filter((f) => f !== "product map details");
1588
1703
  FIELD_WORDS = [
1589
- ["why", /\bwho is it for\b|\bwhy now\b|\bwho (?:hits|needs|asked)\b|\bwhy\b/i],
1590
- ["done", /\bdone\b|\blook like\b|\bsuccess\b|\bacceptance\b/i],
1704
+ ["why", /\bwho is (?:it|this) for\b|\bwhy now\b|\bwho (?:hits|needs|asked)\b|\bwhy\b/i],
1705
+ ["done", /\bdone\b|\blook like\b|\bsuccess\b|\bacceptance\b|\bis fixed\b|\bit'?s fixed\b/i],
1591
1706
  ["smallest", /\bsmallest\b|\bminimum\b|\bmvp\b|\bsmaller version\b/i],
1592
- ["worth", /\bworth\b|\bvalue to\b|\bthe business\b|\brevenue\b/i],
1593
- ["touches", /\btouch(?:es)?\b|\bwhich (?:product|system|area)s?\b|\bwhere in the product\b/i],
1707
+ ["worth", /\bworth\b|\bvalue to\b|\bthe business\b|\brevenue\b|\bhow important\b/i],
1708
+ [
1709
+ "touches",
1710
+ /\btouch(?:es)?\b|\bwhich (?:product|system|area)s?\b|\bwhere in the product\b|\bwhich part of the product\b/i
1711
+ ],
1594
1712
  ["demand", /\bhow many\b|\bhow often\b|\bcome up\b|\basked for this\b/i]
1595
1713
  ];
1596
1714
  });
@@ -1769,7 +1887,7 @@ function buildRoute(drafts, opts = {}) {
1769
1887
  problems.push({ level: "error", text: "a route needs at least one node" });
1770
1888
  if (drafts.length > MAX_NODES)
1771
1889
  problems.push({ level: "error", text: `a route holds at most ${MAX_NODES} nodes` });
1772
- const given = drafts.map((d) => d.key ? norm(d.key) : "");
1890
+ const given = drafts.map((d) => d.key ? norm2(d.key) : "");
1773
1891
  const fresh = mintKeys(given.filter((k) => !k).length, given.filter((k) => k));
1774
1892
  let f = 0;
1775
1893
  const keys = given.map((k) => k || fresh[f++]);
@@ -1784,7 +1902,7 @@ function buildRoute(drafts, opts = {}) {
1784
1902
  const title = stripControl(d.title.replace(/\s+/g, " ")).trim().slice(0, 160);
1785
1903
  if (!title)
1786
1904
  problems.push({ level: "error", node: key, text: `node ${key} has no title` });
1787
- const blockedBy = [...new Set((d.blockedBy ?? []).map(norm).filter(Boolean))];
1905
+ const blockedBy = [...new Set((d.blockedBy ?? []).map(norm2).filter(Boolean))];
1788
1906
  for (const b of blockedBy) {
1789
1907
  if (b === key)
1790
1908
  problems.push({ level: "error", node: key, text: `node ${key} blocks itself` });
@@ -1961,7 +2079,7 @@ ${state}`)}, fillcolor="${fill}", color="${border}"${style}];`);
1961
2079
  `)}
1962
2080
  `;
1963
2081
  }
1964
- var ROUTE_APPROACH_MAX = 2000, PLAN_APPROACH_MAX = 1200, PLAN_LIST_MAX = 8, PLAN_LINE_MAX = 240, CONTROL, MAX_NODES = 24, DEPTH_WARN = 4, norm = (s) => s.trim().toUpperCase(), AREA_ROOTS, NOT_AREAS, sameRepo = (a, b) => a.length === 0 || b.length === 0 || a.some((r) => b.includes(r)), DOT_COLORS, ROUTE_DRAFT_RULE = "Draft the route: PR-sized nodes, file-disjoint where they run in parallel, each with a title, the files or areas it touches, the repo, and the nodes it waits on (by key: A, B, C…). Prefer wide waves over chains deeper than four. Make the tough calls once, so each node's session follows them: an `approach` paragraph for the whole route, and on each node a `plan` — its approach, what it `provides` that later nodes rely on (names, shapes, files), what it `expects` from the nodes it waits on, and the `doneChecks` that say it landed. Show the graph and the plans as text and ask for a yes; file nothing before it. Then `route {q, approach, nodes: [{key, title, touches, repos, blockedBy, plan: {approach, provides, expects, doneChecks}}], confirm: true}`.";
2082
+ var ROUTE_APPROACH_MAX = 2000, PLAN_APPROACH_MAX = 1200, PLAN_LIST_MAX = 8, PLAN_LINE_MAX = 240, CONTROL, MAX_NODES = 24, DEPTH_WARN = 4, norm2 = (s) => s.trim().toUpperCase(), AREA_ROOTS, NOT_AREAS, sameRepo = (a, b) => a.length === 0 || b.length === 0 || a.some((r) => b.includes(r)), DOT_COLORS, ROUTE_DRAFT_RULE = "Draft the route: PR-sized nodes, file-disjoint where they run in parallel, each with a title, the files or areas it touches, the repo, and the nodes it waits on (by key: A, B, C…). Prefer wide waves over chains deeper than four. Make the tough calls once, so each node's session follows them: an `approach` paragraph for the whole route, and on each node a `plan` — its approach, what it `provides` that later nodes rely on (names, shapes, files), what it `expects` from the nodes it waits on, and the `doneChecks` that say it landed. Show the graph and the plans as text and ask for a yes; file nothing before it. Then `route {q, approach, nodes: [{key, title, touches, repos, blockedBy, plan: {approach, provides, expects, doneChecks}}], confirm: true}`.";
1965
2083
  var init_route = __esm(() => {
1966
2084
  CONTROL = /[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g;
1967
2085
  AREA_ROOTS = new Set(["apps", "packages", "services", "libs", "crates", "modules"]);
@@ -3073,6 +3191,13 @@ async function updateTool(ctx, args) {
3073
3191
  patch.repos = args.repos.split(/[,\s]+/).filter(Boolean);
3074
3192
  if (Array.isArray(args.relations))
3075
3193
  patch.relations = args.relations.filter(isObject4).map((r) => ({ key: str5(r.key)?.trim() ?? "", how: str5(r.how) ?? "relates" })).filter((r) => r.key && /^(blockedBy|blocks|relates|duplicates)$/.test(r.how));
3194
+ if (args.worth === null)
3195
+ patch.worth = null;
3196
+ else if (typeof args.worth === "string" && args.worth.trim()) {
3197
+ patch.worth = args.worth.trim();
3198
+ if (args.carry === true)
3199
+ patch.carry = true;
3200
+ }
3076
3201
  if (args.sensitivity === null)
3077
3202
  patch.sensitivity = null;
3078
3203
  else if (typeof args.sensitivity === "string" && /^(public|internal|restricted)$/.test(args.sensitivity)) {
@@ -3082,7 +3207,7 @@ async function updateTool(ctx, args) {
3082
3207
  }
3083
3208
  if (Object.keys(patch).length === 0)
3084
3209
  return {
3085
- text: "Nothing to change. Pass the fields that change: ask, why, done, smallest, touches, demand, description, due, parent, repos, relations.",
3210
+ text: "Nothing to change. Pass the fields that change: ask, why, done, smallest, touches, demand, worth, description, due, parent, repos, relations.",
3086
3211
  isError: true
3087
3212
  };
3088
3213
  const res = await postSaying(ctx, "/proxy/item/update", { project, ...patch }, "Could not update the item.");
@@ -3090,13 +3215,27 @@ async function updateTool(ctx, args) {
3090
3215
  return res.fail;
3091
3216
  const changed = Array.isArray(res.json.changed) ? res.json.changed.filter((x) => typeof x === "string") : [];
3092
3217
  const key = str5(res.json.key) ?? project;
3218
+ const carried = carriedLine(res.json.carried);
3093
3219
  if (changed.length === 0)
3094
- return { text: `${key}: nothing differed from what is on the item.` };
3220
+ return { text: `${key}: nothing differed from what is on the item.${carried}` };
3095
3221
  const stale = res.json.sizeStale === true;
3096
3222
  return {
3097
- text: `${key} updated: ${changed.join(", ")}.${stale ? " The band was sized before this change — say so, and offer to re-size (estimate with the same source)." : ""}`
3223
+ text: `${key} updated: ${changed.join(", ")}.${carried}${stale ? " The band was sized before this change — say so, and offer to re-size (estimate with the same source)." : ""}`
3098
3224
  };
3099
3225
  }
3226
+ function carriedLine(c) {
3227
+ if (!isObject4(c))
3228
+ return "";
3229
+ const set = Array.isArray(c.set) ? c.set.filter((x) => typeof x === "string") : [];
3230
+ const valued = num3(c.valued) ?? 0;
3231
+ const skipped = num3(c.skipped) ?? 0;
3232
+ const parts = [
3233
+ set.length ? `worth set on ${set.length} ${set.length === 1 ? "child" : "children"} (${set.join(", ")})` : "no child took it",
3234
+ ...valued ? [`${valued} already had a worth and kept it`] : [],
3235
+ ...skipped ? [`${skipped} you may not change (a mirror, or not yours) — left as they were`] : []
3236
+ ];
3237
+ return ` ${parts.join("; ").replace(/^./, (ch) => ch.toUpperCase())}.`;
3238
+ }
3100
3239
  async function archiveTool(ctx, args) {
3101
3240
  if (!ctx.client)
3102
3241
  return NOT_SET_UP;
@@ -4773,7 +4912,7 @@ var init_server = __esm(() => {
4773
4912
  },
4774
4913
  {
4775
4914
  name: "update",
4776
- description: "Change an item on the sled — its title (`ask`), why, done, smallest, touches, demand, its description (markdown: the prose the brief does not hold), its due day, which item it sits under, the repo(s) it lands in, or its sensitivity (public · internal · restricted). Pass the item's key and only the fields that change. The filer, an approver or an admin may; a mirrored ticket cannot be changed here. A change to the ask, done or smallest marks the band stale — say so, and offer to re-size. Everything you write is signed as coming through you.",
4915
+ description: "Change an item on the sled — its title (`ask`), why, done, smallest, touches, demand, its worth, its description (markdown: the prose the brief does not hold), its due day, which item it sits under, the repo(s) it lands in, or its sensitivity (public · internal · restricted). Pass the item's key and only the fields that change. Worth is the person's word — never guess it; on an epic, `carry: true` puts it on the children that have none. The filer, an approver or an admin may; a mirrored ticket cannot be changed here. A change to the ask, done or smallest marks the band stale — say so, and offer to re-size. Everything you write is signed as coming through you.",
4777
4916
  inputSchema: {
4778
4917
  type: "object",
4779
4918
  properties: {
@@ -4784,6 +4923,14 @@ var init_server = __esm(() => {
4784
4923
  smallest: { type: "string" },
4785
4924
  touches: { type: "string" },
4786
4925
  demand: { type: "string" },
4926
+ worth: {
4927
+ type: ["string", "null"],
4928
+ description: "What the person said it is worth: a level (low · medium · high · critical), dollars, a customer — e.g. 'high · Acme renewal', '$5k–20k'. Null clears it."
4929
+ },
4930
+ carry: {
4931
+ type: "boolean",
4932
+ description: "With worth: put it on this item's children that have no worth yet, each on its own record. A child with a worth keeps it."
4933
+ },
4787
4934
  description: {
4788
4935
  type: "string",
4789
4936
  description: "Markdown. Links and images inline. Empty clears it."
@@ -5242,9 +5389,33 @@ var init_outcome = __esm(() => {
5242
5389
  });
5243
5390
 
5244
5391
  // ../../packages/shared/src/slack/mention.ts
5392
+ var MENTION_HELP;
5245
5393
  var init_mention = __esm(() => {
5246
5394
  init_intake();
5247
5395
  init_brief();
5396
+ MENTION_HELP = [
5397
+ "Here's what I can do:",
5398
+ "• *@SLEDS file this*: turn the message above into a request for engineering",
5399
+ "• *@SLEDS status*: see where something stands",
5400
+ "You can also ask me to *watch* or *mute* a thread, or *run QW-123*."
5401
+ ].join(`
5402
+ `);
5403
+ });
5404
+
5405
+ // ../../packages/shared/src/slack/copy.ts
5406
+ var init_copy = __esm(() => {
5407
+ init_intake();
5408
+ init_forms();
5409
+ init_mention();
5410
+ init_mention();
5411
+ });
5412
+
5413
+ // ../../packages/shared/src/slack/agent.ts
5414
+ var init_agent = __esm(() => {
5415
+ init_intake();
5416
+ init_brief();
5417
+ init_copy();
5418
+ init_mention();
5248
5419
  });
5249
5420
 
5250
5421
  // ../../packages/shared/src/item/productHits.ts
@@ -5546,6 +5717,72 @@ var init_fieldMap = __esm(() => {
5546
5717
  var SEPT_30 = "/whats-new/2026-09-30", WHATS_NEW;
5547
5718
  var init_whatsNew = __esm(() => {
5548
5719
  WHATS_NEW = [
5720
+ {
5721
+ date: "2026-10-22",
5722
+ title: "Policy is an org setting",
5723
+ lede: "There is one policy for the whole org, so it now lives under Settings beside Platform keys and AI Guidance, instead of on each workspace's rail where it read as a workspace's own. Nothing in it changed; old links redirect.",
5724
+ sections: [
5725
+ {
5726
+ title: "Where it went",
5727
+ where: "Settings › Policy",
5728
+ body: "Open your profile menu › Settings, then Policy. The page is the same: every rule as one sentence, saved as a new version. The rail's Plan group keeps Seats."
5729
+ }
5730
+ ],
5731
+ also: [
5732
+ {
5733
+ label: "Next",
5734
+ text: "Each workspace's Jira projects get their own pages for fields and statuses, and the org's Jira page keeps only the connection, the webhook and what SLEDS may write."
5735
+ }
5736
+ ]
5737
+ },
5738
+ {
5739
+ date: "2026-10-21",
5740
+ title: "The Slack thread is the item's discussion",
5741
+ lede: "An item filed from a Slack thread keeps that thread. What people say there is on the item, what is said on the item goes back there, every move is one line in the thread, and everyone who has spoken hears what happens next.",
5742
+ sections: [
5743
+ {
5744
+ title: "Replies are comments; moves are lines",
5745
+ where: "Slack, after Filed as",
5746
+ body: "After Filed as, a reply in the thread is a comment on the item, as that person, marked from Slack. Approve, defer, take, land and archive each post one line in the thread with a link to the item. The item's Details has Slack, which opens the thread."
5747
+ },
5748
+ {
5749
+ title: "Comments go out",
5750
+ where: "The item › Discussion",
5751
+ body: "A comment written on the item is posted in its thread as the person who wrote it, and to Jira when the comments switch is on. The line under the composer says where it will go. SLEDS's own strips stay on SLEDS."
5752
+ },
5753
+ {
5754
+ title: "Watchers",
5755
+ where: "The item › Discussion, and @SLEDS in the thread",
5756
+ body: "Whoever filed it, holds it, or has spoken on it hears each move — once, never their own. Watch on the Discussion adds you; Unwatch stops it. In a thread, @SLEDS watch QW-123 ties an item to that thread, @SLEDS status answers with the item's status, and @SLEDS ask: … puts a question to the filer."
5757
+ },
5758
+ {
5759
+ title: "Forms are read as fields",
5760
+ where: "Slack, filing from a workflow post",
5761
+ body: "A support ticket form posted by a Slack workflow is read field by field: the issue description is the title, the users and IDs go on one details line, and the count of clients and the revenue answer to demand. SLEDS then asks only what the form did not say."
5762
+ },
5763
+ {
5764
+ title: "Replies you can read",
5765
+ where: "Slack, filing from a thread",
5766
+ body: `One summary message per thread, kept up to date as you answer, with the title in plain words and the form's other fields on one line. Answer several questions at once, one per line, or say which one you're answering: "done means the sync works", "high priority". Say "send it to Core" to change the team before filing. A yes with something missing asks for just that one thing.`
5767
+ },
5768
+ {
5769
+ title: "A model can write the replies",
5770
+ where: "Policy › Intake",
5771
+ body: "Turn on Slack intake replies written by a model, Claude Haiku 5.5 by default, and it answers in the thread the way the channel's AI Guidance says: what it understood, a workaround when there is one, and the questions that matter for this kind of issue. It spends your own Anthropic key from Platform keys, up to a daily cap you set. Filing still waits for a yes, and it never sets the priority."
5772
+ },
5773
+ {
5774
+ title: "Which workspace, picked",
5775
+ where: "Slack, filing",
5776
+ body: "A channel tied to a workspace files there. With several workspaces and none tied to the channel, SLEDS asks which team: reply with the number or the name. The Jira key is never typed — the Filed as reply shows it."
5777
+ }
5778
+ ],
5779
+ also: [
5780
+ {
5781
+ label: "Fixed",
5782
+ text: "An ask filed from Slack now creates its Jira ticket in the workspace it was filed on, and a stated priority sets the ticket's priority. A form posted by a Slack workflow is now read field by field."
5783
+ }
5784
+ ]
5785
+ },
5549
5786
  {
5550
5787
  date: "2026-10-20",
5551
5788
  title: "Intake: the gate gets its own page",
@@ -6178,6 +6415,9 @@ var init_pack2 = __esm(() => {
6178
6415
  init_prHeader();
6179
6416
  });
6180
6417
 
6418
+ // ../../packages/shared/src/deploys/deploys.ts
6419
+ var init_deploys = () => {};
6420
+
6181
6421
  // ../../packages/shared/src/newrelic/newrelic.ts
6182
6422
  var init_newrelic = () => {};
6183
6423
 
@@ -6575,7 +6815,7 @@ function nodePrompt(o) {
6575
6815
  `- Work on branch \`${o.branch}\` from the latest \`origin/${base}\` (create it if this checkout is not on it). One branch, one PR.`,
6576
6816
  `- Open the PR against \`${base}\` with \`gh pr create${visual ? " --draft" : ""}\`${o.prTitle ? ` and title it exactly \`${o.prTitle}\` (the repo's CI checks it)` : ""}. Its body carries \`SLEDS-Node: ${claim.node}\` on the line under \`SLEDS-Source:\` when the pack names a source.`,
6577
6817
  ...claim.pack.includes(PR_HEADER_OPEN) ? [
6578
- `- The PR body starts with the pack's PR header block (\`${PR_HEADER_OPEN}\` … \`${PR_HEADER_CLOSE}\`, in its part 5), above everything else and as given; when you edit the body later, keep it on top.`
6818
+ `- The PR body starts with the pack's PR header block (\`${PR_HEADER_OPEN}\` … \`${PR_HEADER_CLOSE}\`, in its part 5), above everything else. The pack wrote it before your work existed: when you make a mock (a screenshot or an artifact) or write a doc, put its link on that part's line in place of \`None\` — not only lower in the body (SL-1746). When you edit the body later, keep it on top.`
6579
6819
  ] : [],
6580
6820
  "- Run the repo's own gate before you push. Never merge: a person (or the musher, when the attachment says so) does.",
6581
6821
  "- Stay inside this node's scope. Work another node needs goes in the PR description, not in this branch.",
@@ -7019,6 +7259,9 @@ var init_effort = __esm(() => {
7019
7259
  EFFORTS = ["low", "medium", "high", "xhigh", "max"];
7020
7260
  });
7021
7261
 
7262
+ // ../../packages/shared/src/workspaceLook.ts
7263
+ var init_workspaceLook = () => {};
7264
+
7022
7265
  // src/settings.ts
7023
7266
  import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
7024
7267
  import { dirname, join, resolve as resolve2 } from "node:path";
@@ -7553,6 +7796,7 @@ var init_src = __esm(() => {
7553
7796
  init_guides();
7554
7797
  init_verbs();
7555
7798
  init_brief();
7799
+ init_forms();
7556
7800
  init_related();
7557
7801
  init_rank();
7558
7802
  init_markdown2();
@@ -7562,6 +7806,8 @@ var init_src = __esm(() => {
7562
7806
  init_profile2();
7563
7807
  init_outcome();
7564
7808
  init_mention();
7809
+ init_agent();
7810
+ init_copy();
7565
7811
  init_productHits();
7566
7812
  init_model();
7567
7813
  init_parse();
@@ -7576,6 +7822,7 @@ var init_src = __esm(() => {
7576
7822
  init_cheatSheet();
7577
7823
  init_pack2();
7578
7824
  init_flags();
7825
+ init_deploys();
7579
7826
  init_sentry();
7580
7827
  init_newrelic();
7581
7828
  init_musher();
@@ -7586,6 +7833,7 @@ var init_src = __esm(() => {
7586
7833
  init_otlp();
7587
7834
  init_session();
7588
7835
  init_effort();
7836
+ init_workspaceLook();
7589
7837
  });
7590
7838
 
7591
7839
  // src/engine/json.ts
@@ -8253,6 +8501,7 @@ init_cowork();
8253
8501
  init_guides();
8254
8502
  init_verbs();
8255
8503
  init_brief();
8504
+ init_forms();
8256
8505
  init_related();
8257
8506
  init_rank();
8258
8507
  init_markdown2();
@@ -8262,6 +8511,8 @@ init_due();
8262
8511
  init_profile2();
8263
8512
  init_outcome();
8264
8513
  init_mention();
8514
+ init_agent();
8515
+ init_copy();
8265
8516
  init_productHits();
8266
8517
  init_model();
8267
8518
  init_parse();
@@ -8276,6 +8527,7 @@ init_whatsNew();
8276
8527
  init_cheatSheet();
8277
8528
  init_pack2();
8278
8529
  init_flags();
8530
+ init_deploys();
8279
8531
  init_sentry();
8280
8532
  init_newrelic();
8281
8533
  init_musher();
@@ -8286,6 +8538,7 @@ init_engine();
8286
8538
  init_otlp();
8287
8539
  init_session();
8288
8540
  init_effort();
8541
+ init_workspaceLook();
8289
8542
 
8290
8543
  // src/agentMcp.ts
8291
8544
  import { execFileSync } from "node:child_process";
@@ -9232,12 +9485,13 @@ var scanTranscriptForCredits = (path, prior) => {
9232
9485
  return { hit: false, next: prior && prior.path === path ? prior : { path, offset: 0 } };
9233
9486
  }
9234
9487
  };
9235
- var seatWindowBody = (w) => ({
9488
+ var seatWindowBody = (w, account) => ({
9236
9489
  capturedAt: w.capturedAt,
9237
9490
  source: "claude",
9238
9491
  ...w.fiveHour ? { fiveHour: w.fiveHour } : {},
9239
9492
  ...w.sevenDay ? { sevenDay: w.sevenDay } : {},
9240
- ...w.spendLimit ? { spendLimit: w.spendLimit } : {}
9493
+ ...w.spendLimit ? { spendLimit: w.spendLimit } : {},
9494
+ ...account ? { account } : {}
9241
9495
  });
9242
9496
  var postJson = async (o, path, body) => {
9243
9497
  const fetchFn = o.fetchFn ?? fetch;
@@ -9253,7 +9507,7 @@ var postJson = async (o, path, body) => {
9253
9507
  return false;
9254
9508
  }
9255
9509
  };
9256
- var postSeatWindow = (o, w) => postJson(o, "/proxy/seat", seatWindowBody(w));
9510
+ var postSeatWindow = (o, w, account) => postJson(o, "/proxy/seat", seatWindowBody(w, account));
9257
9511
  var postSeatWall = (o, input) => postJson(o, "/proxy/seat-wall", { source: "claude", ...input });
9258
9512
  var SEAT_WALL_LINE = "Seat limit hit. sleds on --until-reset to continue on the platform key, or sleds defer to resume here at the reset.";
9259
9513
  var SEAT_WALL_LINE_NO_KEY = "Seat limit hit. sleds defer resumes this session on this Mac at the reset; /sled 5 to hand off — this org has no platform key to switch to.";
@@ -9444,16 +9698,16 @@ init_src();
9444
9698
  import { execFileSync as execFileSync3, spawnSync as spawnSync5 } from "node:child_process";
9445
9699
  import { randomBytes } from "node:crypto";
9446
9700
  import {
9447
- existsSync as existsSync16,
9448
- lstatSync,
9701
+ existsSync as existsSync17,
9702
+ lstatSync as lstatSync2,
9449
9703
  mkdtempSync,
9450
- readFileSync as readFileSync16,
9451
- readlinkSync,
9704
+ readFileSync as readFileSync17,
9705
+ readlinkSync as readlinkSync2,
9452
9706
  rmSync as rmSync8,
9453
9707
  writeFileSync as writeFileSync17
9454
9708
  } from "node:fs";
9455
9709
  import { tmpdir } from "node:os";
9456
- import { join as join19, resolve as resolve8 } from "node:path";
9710
+ import { join as join20, resolve as resolve9 } from "node:path";
9457
9711
 
9458
9712
  // src/agentMcp.ts
9459
9713
  import { execFileSync as execFileSync2 } from "node:child_process";
@@ -9850,7 +10104,7 @@ function resolveRepoPath(o) {
9850
10104
  const want = o.repos.length ? o.repos.join(", ") : "this node";
9851
10105
  const dir = names[0] ? ` (the folder that holds ${names[0]})` : "";
9852
10106
  return {
9853
- error: `No repo for ${want}: this engine runs in ${o.cwd}, which is not a git checkout. Set Repos dir in Settings${dir}, or start the engine with --repo.`
10107
+ error: `No repo for ${want}: this engine runs in ${o.cwd}, which is not a git checkout. Set Repos folders in Settings › Running work${dir}, or start the engine with --repo.`
9854
10108
  };
9855
10109
  }
9856
10110
  for (const name of names) {
@@ -10375,7 +10629,7 @@ function cmuxRunner(exec, deps = {}) {
10375
10629
  throw new Error(`cmux send-key ${h.id} failed: ${failed(r)}`);
10376
10630
  },
10377
10631
  stop(h) {
10378
- cmux(["close-workspace", "--workspace", h.id]);
10632
+ closeWorkspace(h.id);
10379
10633
  if (!h.group)
10380
10634
  return;
10381
10635
  const l = cmux(LIST_GROUPS);
@@ -10415,6 +10669,215 @@ function cmuxRunner(exec, deps = {}) {
10415
10669
  };
10416
10670
  }
10417
10671
 
10672
+ // src/runners/orca.ts
10673
+ import { existsSync as existsSync12, lstatSync, readlinkSync, writeFileSync as writeFileSync11 } from "node:fs";
10674
+ import { join as join14, resolve as resolve7 } from "node:path";
10675
+ var obj = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
10676
+ var str8 = (v) => typeof v === "string" && v.length > 0 ? v : null;
10677
+ var parseOrcaJson = (stdout) => {
10678
+ try {
10679
+ return obj(JSON.parse(stdout));
10680
+ } catch {
10681
+ return null;
10682
+ }
10683
+ };
10684
+ var orcaError = (env) => {
10685
+ if (!env || env.ok !== false)
10686
+ return null;
10687
+ const e = obj(env.error);
10688
+ const message = str8(e?.message) ?? "Orca refused the call";
10689
+ const code = str8(e?.code);
10690
+ return code ? `${message} (${code})` : message;
10691
+ };
10692
+ var parseOrcaWorktree = (env) => {
10693
+ const result = obj(env.result) ?? {};
10694
+ return str8(obj(result.worktree)?.path) ?? str8(result.worktreePath) ?? str8(result.path);
10695
+ };
10696
+ var parseOrcaBranch = (env) => {
10697
+ const wt = obj(obj(env.result)?.worktree);
10698
+ const branch = str8(wt?.branch)?.replace(/^refs\/heads\//, "");
10699
+ const head = str8(wt?.head);
10700
+ return branch && head ? { branch, head } : null;
10701
+ };
10702
+ var parseOrcaTerminal = (env) => {
10703
+ const result = obj(env.result) ?? {};
10704
+ return str8(obj(result.terminal)?.handle) ?? str8(result.handle) ?? str8(result.terminalHandle) ?? null;
10705
+ };
10706
+ var orcaLauncher = (o) => `#!/bin/sh
10707
+ # sleds engine: ${o.name}
10708
+ exec ${agentShellCommand(o)}
10709
+ `;
10710
+ var orcaCommand = (launcher) => `sh ${shq2(launcher)}; exit`;
10711
+ var GONE = /exit|clos|gone|dead|stopp|kill/i;
10712
+ var orcaTerminalLive = (status, stdout) => {
10713
+ const env = parseOrcaJson(stdout);
10714
+ if (str8(obj(env?.error)?.code) === "runtime_unavailable")
10715
+ return true;
10716
+ if (status !== 0 || !env || env.ok === false)
10717
+ return false;
10718
+ const t = obj(obj(env.result)?.terminal) ?? obj(env.result) ?? {};
10719
+ if (typeof t.status === "string" && GONE.test(t.status))
10720
+ return false;
10721
+ if (t.exited === true || t.alive === false)
10722
+ return false;
10723
+ if (typeof t.exitCode === "number")
10724
+ return false;
10725
+ if (obj(t.exitCause))
10726
+ return false;
10727
+ if (t.orphaned === true && t.writable === false)
10728
+ return false;
10729
+ return true;
10730
+ };
10731
+ var realFs = { lstat: lstatSync, readlink: readlinkSync, exists: existsSync12 };
10732
+ var ORCA_LINK_FIX = "reinstall Orca's shell command from Orca (it links `orca` onto your PATH)";
10733
+ function danglingOrca(path, fs) {
10734
+ for (const dir of path.split(":").filter(Boolean)) {
10735
+ const link = join14(dir, "orca");
10736
+ try {
10737
+ if (!fs.lstat(link).isSymbolicLink())
10738
+ return null;
10739
+ const target = resolve7(dir, fs.readlink(link));
10740
+ if (!fs.exists(target))
10741
+ return { link, target };
10742
+ return null;
10743
+ } catch {}
10744
+ }
10745
+ return null;
10746
+ }
10747
+ function orcaPreflight(exec, path, fs = realFs) {
10748
+ let r;
10749
+ try {
10750
+ r = exec("orca", ["--version"], { env: { PATH: path } });
10751
+ } catch (e) {
10752
+ r = { status: 127, stdout: "", stderr: e instanceof Error ? e.message : String(e) };
10753
+ }
10754
+ if (r.status === 0) {
10755
+ return { ok: true, version: r.stdout.trim().split(`
10756
+ `)[0]?.trim() || "orca" };
10757
+ }
10758
+ const dangling = danglingOrca(path, fs);
10759
+ if (dangling) {
10760
+ return {
10761
+ ok: false,
10762
+ why: `${dangling.link} links to ${dangling.target}, which is gone`,
10763
+ fix: ORCA_LINK_FIX
10764
+ };
10765
+ }
10766
+ if (!path.split(":").includes("/usr/bin")) {
10767
+ return { ok: false, why: "the engine's PATH has no /usr/bin", fix: "sleds engine install" };
10768
+ }
10769
+ if (r.status === 127) {
10770
+ return { ok: false, why: "not installed (no `orca` on the PATH)", fix: ORCA_LINK_FIX };
10771
+ }
10772
+ const said = `${r.stderr}
10773
+ ${r.stdout}`.split(`
10774
+ `).map((l) => l.trim()).find(Boolean);
10775
+ return {
10776
+ ok: false,
10777
+ why: `\`orca --version\` failed: ${said ?? `exit ${r.status}`}`,
10778
+ fix: "reinstall Orca, or its shell command from Orca"
10779
+ };
10780
+ }
10781
+ var launcherPath2 = (promptFile) => `${promptFile.replace(/\.md$/, "")}.orca.sh`;
10782
+ function orcaRunner(exec, deps = {}) {
10783
+ const writeFile = deps.writeFile ?? ((p, t) => writeFileSync11(p, t, { mode: 384 }));
10784
+ const orca = (args, what) => {
10785
+ const r = exec("orca", args);
10786
+ const env = parseOrcaJson(r.stdout);
10787
+ const refused = orcaError(env);
10788
+ if (refused)
10789
+ throw new Error(`${what}: ${refused}`);
10790
+ if (r.status !== 0 || !env) {
10791
+ throw new Error(`${what} failed: ${r.stderr.trim() || r.stdout.trim() || `exit ${r.status}`}`);
10792
+ }
10793
+ return env;
10794
+ };
10795
+ return {
10796
+ name: "orca",
10797
+ makesWorktree: true,
10798
+ readsSession: true,
10799
+ start(o) {
10800
+ const created = orca([
10801
+ "worktree",
10802
+ "create",
10803
+ "--repo",
10804
+ `path:${o.repoPath}`,
10805
+ "--name",
10806
+ o.name,
10807
+ "--base-branch",
10808
+ `origin/${o.base ?? "main"}`,
10809
+ "--no-parent",
10810
+ "--json"
10811
+ ], `orca worktree create ${o.name}`);
10812
+ const cwd = parseOrcaWorktree(created);
10813
+ if (!cwd) {
10814
+ throw new Error(`orca worktree create ${o.name} returned no worktree path; the agent was not started`);
10815
+ }
10816
+ const launcher = launcherPath2(o.promptFile);
10817
+ writeFile(launcher, orcaLauncher(o));
10818
+ const shown = orca([
10819
+ "terminal",
10820
+ "create",
10821
+ "--worktree",
10822
+ `path:${cwd}`,
10823
+ "--title",
10824
+ o.name,
10825
+ "--command",
10826
+ orcaCommand(launcher),
10827
+ "--json"
10828
+ ], `orca terminal create ${o.name} (worktree ${cwd})`);
10829
+ const terminal = parseOrcaTerminal(shown);
10830
+ if (!terminal) {
10831
+ throw new Error(`orca terminal create ${o.name} started in ${cwd} but returned no terminal handle`);
10832
+ }
10833
+ const own = parseOrcaBranch(created);
10834
+ const h = { runner: "orca", id: terminal, cwd, ...own ? { own } : {} };
10835
+ return h;
10836
+ },
10837
+ status(h) {
10838
+ const r = exec("orca", ["terminal", "show", "--terminal", h.id, "--json"]);
10839
+ return orcaTerminalLive(r.status, r.stdout) ? "running" : "exited";
10840
+ },
10841
+ read(h) {
10842
+ const r = exec("orca", ["terminal", "read", "--terminal", h.id, "--limit", "200"]);
10843
+ return r.status === 0 ? r.stdout : "";
10844
+ },
10845
+ send(h, text) {
10846
+ const r = exec("orca", ["terminal", "send", "--terminal", h.id, "--text", text, "--enter"]);
10847
+ if (r.status !== 0) {
10848
+ throw new Error(`orca terminal send ${h.id} failed: ${r.stderr.trim() || `exit ${r.status}`}`);
10849
+ }
10850
+ },
10851
+ stop(h) {
10852
+ exec("orca", ["terminal", "close", "--terminal", h.id]);
10853
+ },
10854
+ watchHint(h) {
10855
+ return `orca terminal show --terminal ${h.id}`;
10856
+ },
10857
+ probe() {
10858
+ try {
10859
+ const p = orcaPreflight(exec, process.env.PATH ?? "", deps.fs);
10860
+ return p.ok ? null : `orca: ${p.why} — ${p.fix}`;
10861
+ } catch {
10862
+ return "orca: not installed";
10863
+ }
10864
+ },
10865
+ removeWorktree(h, repoPath) {
10866
+ orca(["worktree", "rm", "--worktree", `path:${h.cwd}`, "--json"], `orca worktree rm ${h.cwd}`);
10867
+ if (!h.own)
10868
+ return;
10869
+ const ref = `refs/heads/${h.own.branch}`;
10870
+ const r = exec("git", ["-C", repoPath, "update-ref", "-d", ref, h.own.head]);
10871
+ if (r.status === 0)
10872
+ return;
10873
+ const still = exec("git", ["-C", repoPath, "rev-parse", "--verify", "--quiet", ref]);
10874
+ if (still.status !== 0)
10875
+ return;
10876
+ return `kept Orca's branch ${h.own.branch}: ${r.stderr.trim() || `exit ${r.status}`}`;
10877
+ }
10878
+ };
10879
+ }
10880
+
10418
10881
  // src/commands/doctor.ts
10419
10882
  init_settings();
10420
10883
 
@@ -10432,7 +10895,7 @@ import {
10432
10895
  writeFileSync as writeFileSync13
10433
10896
  } from "node:fs";
10434
10897
  import { hostname as hostname2 } from "node:os";
10435
- import { join as join15, resolve as resolve7 } from "node:path";
10898
+ import { join as join16, resolve as resolve8 } from "node:path";
10436
10899
 
10437
10900
  // src/engine/beat.ts
10438
10901
  var BEAT_EVERY_MS = 60000;
@@ -10444,7 +10907,7 @@ function beatBody(state, flags, host = {}, cap = {}) {
10444
10907
  name: flags.name,
10445
10908
  os: host.os ?? process.platform,
10446
10909
  runner: flags.runner,
10447
- version: host.version ?? "0.1.42" ?? "dev",
10910
+ version: host.version ?? "0.1.44" ?? "dev",
10448
10911
  running: live.length,
10449
10912
  items: live.slice(0, BEAT_ITEMS).map((r) => `${r.item}/${r.node}`),
10450
10913
  ...cap.atOnce !== undefined ? { atOnce: cap.atOnce } : {},
@@ -10463,10 +10926,13 @@ function beatBody(state, flags, host = {}, cap = {}) {
10463
10926
  }
10464
10927
  async function postBeat(client, body) {
10465
10928
  try {
10466
- const r = await client.post("/proxy/engine/beat", { ...body });
10467
- return r?.ok === true;
10929
+ const r = await client.postFull("/proxy/engine/beat", { ...body });
10930
+ if (r?.status === 200 && r.json?.ok === true)
10931
+ return { ok: true };
10932
+ const error = r?.json?.error;
10933
+ return r?.status === 409 && typeof error === "string" ? { ok: false, refused: error } : { ok: false };
10468
10934
  } catch {
10469
- return false;
10935
+ return { ok: false };
10470
10936
  }
10471
10937
  }
10472
10938
  function beater(client, now, everyMs = BEAT_EVERY_MS) {
@@ -11234,7 +11700,7 @@ function jiraFromEnv(epic, gate, env = process.env) {
11234
11700
  init_src();
11235
11701
 
11236
11702
  // src/commands/permissionEvent.ts
11237
- import { chmodSync as chmodSync3, mkdirSync as mkdirSync10, readFileSync as readFileSync10, renameSync as renameSync6, rmSync as rmSync3, writeFileSync as writeFileSync11 } from "node:fs";
11703
+ import { chmodSync as chmodSync3, mkdirSync as mkdirSync10, readFileSync as readFileSync10, renameSync as renameSync6, rmSync as rmSync3, writeFileSync as writeFileSync12 } from "node:fs";
11238
11704
 
11239
11705
  // src/commands/seatEvent.ts
11240
11706
  init_config();
@@ -11254,6 +11720,11 @@ var notificationType = (text) => {
11254
11720
 
11255
11721
  // src/commands/permissionEvent.ts
11256
11722
  var isObject12 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
11723
+ var NOT_A_TOOL = new Set(["askuserquestion", "exitplanmode", "enterplanmode"]);
11724
+ var isToolPermission = (message) => {
11725
+ const tool = /permission to use\s+(.+?)\.?\s*$/i.exec(message)?.[1];
11726
+ return !tool || !NOT_A_TOOL.has(tool.replace(/[\s_-]/g, "").toLowerCase());
11727
+ };
11257
11728
  var readPermissionMark = (file) => {
11258
11729
  try {
11259
11730
  const raw = JSON.parse(readFileSync10(file, "utf8"));
@@ -11708,11 +12179,12 @@ function sledsSource(client, o) {
11708
12179
  async function draft(row, item, why) {
11709
12180
  const project = str6(row.project) ?? item;
11710
12181
  const pending = isObject8(row.route) && isObject8(row.route.redraft) ? row.route.redraft : null;
12182
+ const runner = typeof o.runner === "function" ? o.runner() : o.runner;
11711
12183
  const r = await client.postFull("/proxy/route", {
11712
12184
  project,
11713
12185
  draft: "take",
11714
12186
  engine: o.engine,
11715
- ...o.runner ? { runner: o.runner } : {},
12187
+ ...runner ? { runner } : {},
11716
12188
  ...o.leaseMin !== undefined ? { leaseMin: o.leaseMin } : {}
11717
12189
  });
11718
12190
  if (!r || r.status >= 300 || !r.json || r.json.ok === false) {
@@ -12136,7 +12608,36 @@ var DIALOG_ASKS = /^Do you want to .+\?$/;
12136
12608
  var DIALOG_OPTION = /^(❯\s*)?(\d)\.\s+(.+)$/;
12137
12609
  var DIALOG_FOOTER = /^(?:esc to |tab to |enter to |ctrl\+)/i;
12138
12610
  var unbox = (line) => line.trimEnd().replace(/^\s*[│┃║]\s?/, "").replace(/\s*[│┃║]$/, "");
12611
+ var PICKER_CHIP = /^[☐☒✔✓□■]\s+\S/;
12612
+ var PICKER_OPTION = /^(?:Type something\.?|Chat about this|Submit answers?)$/i;
12613
+ var PICKER_FOOTER = /\benter to select\b|\bto navigate\b/i;
12614
+ var PICKER_ASKS = /^(?:Would you like to proceed\?|Ready to code\?)$/;
12615
+ var PICKER_REACH = 40;
12616
+ function choicePicker(screen) {
12617
+ const lines = screen.split(`
12618
+ `).map((l) => unbox(l).trim());
12619
+ let c = -1;
12620
+ for (let i = lines.length - 1;i >= 0; i--)
12621
+ if (/^❯\s*\d\.\s/.test(lines[i])) {
12622
+ c = i;
12623
+ break;
12624
+ }
12625
+ if (c < 0)
12626
+ return false;
12627
+ let from = c;
12628
+ while (from > 0 && c - from < PICKER_REACH && !/^⏺/.test(lines[from - 1]))
12629
+ from--;
12630
+ for (let i = from;i < lines.length; i++) {
12631
+ const t = lines[i];
12632
+ const choice = DIALOG_OPTION.exec(t)?.[3]?.trim() ?? "";
12633
+ if (PICKER_CHIP.test(t) || PICKER_ASKS.test(t) || PICKER_OPTION.test(choice) || i > c && PICKER_FOOTER.test(t))
12634
+ return true;
12635
+ }
12636
+ return false;
12637
+ }
12139
12638
  function permissionDialog(screen) {
12639
+ if (choicePicker(screen))
12640
+ return null;
12140
12641
  const raw = screen.split(`
12141
12642
  `);
12142
12643
  const lines = raw.map(unbox);
@@ -12211,10 +12712,10 @@ function providerFailure(screen) {
12211
12712
 
12212
12713
  // src/engine/worktree.ts
12213
12714
  init_src();
12214
- import { appendFileSync, existsSync as existsSync12, mkdirSync as mkdirSync11 } from "node:fs";
12215
- import { dirname as dirname11, isAbsolute, join as join14 } from "node:path";
12715
+ import { appendFileSync, existsSync as existsSync13, mkdirSync as mkdirSync11 } from "node:fs";
12716
+ import { dirname as dirname11, isAbsolute, join as join15 } from "node:path";
12216
12717
  function worktreePath(repoPath, name) {
12217
- return join14(repoPath, ".worktrees", name);
12718
+ return join15(repoPath, ".worktrees", name);
12218
12719
  }
12219
12720
  var fail = (what, r) => new Error(`${what} failed: ${(r.stderr || r.stdout).trim() || `exit ${r.status}`}`);
12220
12721
  function defaultBranch(exec, repoPath) {
@@ -12235,7 +12736,7 @@ function defaultBranch(exec, repoPath) {
12235
12736
  return "main";
12236
12737
  }
12237
12738
  var realWorktreeFs = {
12238
- exists: existsSync12,
12739
+ exists: existsSync13,
12239
12740
  append: (p, text) => {
12240
12741
  mkdirSync11(dirname11(p), { recursive: true });
12241
12742
  appendFileSync(p, text);
@@ -12249,7 +12750,7 @@ function ensureIgnored(exec, repoPath, fs = realWorktreeFs) {
12249
12750
  if (common.status !== 0)
12250
12751
  return;
12251
12752
  const dir = common.stdout.trim();
12252
- const exclude = join14(isAbsolute(dir) ? dir : join14(repoPath, dir), "info", "exclude");
12753
+ const exclude = join15(isAbsolute(dir) ? dir : join15(repoPath, dir), "info", "exclude");
12253
12754
  fs.append(exclude, `
12254
12755
  # sleds engine: one worktree per route node
12255
12756
  .worktrees/
@@ -12261,7 +12762,7 @@ function ensureWorktree(exec, repoPath, branch, path, base = "main", fs = realWo
12261
12762
  return path;
12262
12763
  }
12263
12764
  function makeWorktree(exec, repoPath, branch, path, base, fs, log) {
12264
- if (fs.exists(join14(path, ".git"))) {
12765
+ if (fs.exists(join15(path, ".git"))) {
12265
12766
  fastForwardUntouched(exec, path, base, log);
12266
12767
  return path;
12267
12768
  }
@@ -12334,13 +12835,13 @@ function installArgv(command) {
12334
12835
  return argv;
12335
12836
  }
12336
12837
  function lockfileInstall(path, exists) {
12337
- if (exists(join14(path, "pnpm-lock.yaml")))
12838
+ if (exists(join15(path, "pnpm-lock.yaml")))
12338
12839
  return ["pnpm", "install", "--frozen-lockfile"];
12339
- if (exists(join14(path, "bun.lock")) || exists(join14(path, "bun.lockb")))
12840
+ if (exists(join15(path, "bun.lock")) || exists(join15(path, "bun.lockb")))
12340
12841
  return ["bun", "install", "--frozen-lockfile"];
12341
- if (exists(join14(path, "yarn.lock")))
12842
+ if (exists(join15(path, "yarn.lock")))
12342
12843
  return ["yarn", "install", "--frozen-lockfile"];
12343
- if (exists(join14(path, "package-lock.json")))
12844
+ if (exists(join15(path, "package-lock.json")))
12344
12845
  return ["npm", "ci"];
12345
12846
  return null;
12346
12847
  }
@@ -12365,7 +12866,7 @@ function packInstallOf(pack, repo) {
12365
12866
  return first;
12366
12867
  }
12367
12868
  function ensureInstalled(exec, path, fs, o = {}) {
12368
- if (!fs.exists(join14(path, "package.json")) || fs.exists(join14(path, "node_modules")))
12869
+ if (!fs.exists(join15(path, "package.json")) || fs.exists(join15(path, "node_modules")))
12369
12870
  return null;
12370
12871
  const argv = installArgv(o.command) ?? lockfileInstall(path, fs.exists);
12371
12872
  if (!argv)
@@ -12380,7 +12881,7 @@ function ensureInstalled(exec, path, fs, o = {}) {
12380
12881
  return { argv, ok };
12381
12882
  }
12382
12883
  function ensureDetachedWorktree(exec, repoPath, path, base = "main", fs = realWorktreeFs) {
12383
- if (fs.exists(join14(path, ".git")))
12884
+ if (fs.exists(join15(path, ".git")))
12384
12885
  return path;
12385
12886
  ensureIgnored(exec, repoPath, fs);
12386
12887
  const f = exec("git", ["-C", repoPath, "fetch", "origin", base]);
@@ -12527,6 +13028,8 @@ async function tick(deps) {
12527
13028
  deps.startBackoff = d.startBackoff;
12528
13029
  deps.providerHold = d.providerHold;
12529
13030
  deps.atOnce = d.atOnce;
13031
+ deps.runner = d.runner;
13032
+ deps.runnerRefused = d.runnerRefused;
12530
13033
  }
12531
13034
  removeEndedMcpConfigs(deps, made);
12532
13035
  }
@@ -12569,6 +13072,7 @@ async function tickOnce(d) {
12569
13072
  const changes = [];
12570
13073
  const decided = [];
12571
13074
  const save = () => d.writeState(state);
13075
+ await rereadRunner(d);
12572
13076
  probeRunner(d);
12573
13077
  if (d.startBackoff && --d.startBackoff.checks <= 0)
12574
13078
  d.startBackoff = undefined;
@@ -13151,7 +13655,11 @@ async function settlePermission(d, runner, run, shown) {
13151
13655
  run.permission = undefined;
13152
13656
  return false;
13153
13657
  }
13154
- const mark = markFile ? readPermissionMark(markFile) : null;
13658
+ let mark = markFile ? readPermissionMark(markFile) : null;
13659
+ if (mark && markFile && (!isToolPermission(mark.message) || runner.readsSession && choicePicker(shown))) {
13660
+ clearPermissionMark(markFile);
13661
+ mark = null;
13662
+ }
13155
13663
  if (!dialog && !mark)
13156
13664
  return false;
13157
13665
  if (!dialog && runner.readsSession && !run.seenTicks)
@@ -13350,6 +13858,29 @@ async function rereadAtOnce(d) {
13350
13858
  d.atOnce = next;
13351
13859
  d.log(`at once now ${next}, from your engine profile`);
13352
13860
  }
13861
+ async function rereadRunner(d) {
13862
+ if (!d.rereadRunner)
13863
+ return;
13864
+ let next = null;
13865
+ try {
13866
+ next = await d.rereadRunner(profileOf2(d));
13867
+ } catch {}
13868
+ if (next === null)
13869
+ return;
13870
+ if (typeof next === "string") {
13871
+ if (d.runnerRefused !== next)
13872
+ d.log(next);
13873
+ d.runnerRefused = next;
13874
+ return;
13875
+ }
13876
+ d.runnerRefused = undefined;
13877
+ if (next === d.runner)
13878
+ return;
13879
+ const was = d.runner.name;
13880
+ d.runner = next;
13881
+ d.runnerHold = undefined;
13882
+ d.log(`runner now ${next.name}, from your engine profile — new sessions start on it; running ones stay on ${was}`);
13883
+ }
13353
13884
  async function rereadMachine(w, d) {
13354
13885
  if (!w.reread)
13355
13886
  return;
@@ -14894,8 +15425,8 @@ function commandRunner(template, deps = {}) {
14894
15425
 
14895
15426
  // src/runners/conductor.ts
14896
15427
  import { readFileSync as readFileSync11 } from "node:fs";
14897
- var obj = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
14898
- var str8 = (v) => typeof v === "string" && v.length > 0 ? v : null;
15428
+ var obj2 = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
15429
+ var str9 = (v) => typeof v === "string" && v.length > 0 ? v : null;
14899
15430
  var CONDUCTOR_API = "https://api.conductor.build";
14900
15431
  var CLAUDE_MODELS = new Set([
14901
15432
  "fable-5-1",
@@ -14952,7 +15483,7 @@ var splitCurl = (stdout) => {
14952
15483
  const code = Number(stdout.slice(cut + 1).trim()) || 0;
14953
15484
  let body = null;
14954
15485
  try {
14955
- body = obj(JSON.parse(text));
15486
+ body = obj2(JSON.parse(text));
14956
15487
  } catch {
14957
15488
  body = null;
14958
15489
  }
@@ -14967,7 +15498,7 @@ var messageText = (content, depth = 0) => {
14967
15498
  return content.map((c) => messageText(c, depth + 1)).filter(Boolean).join(`
14968
15499
  `);
14969
15500
  }
14970
- const o = obj(content);
15501
+ const o = obj2(content);
14971
15502
  if (!o)
14972
15503
  return String(content);
14973
15504
  for (const k of ["text", "content", "message", "result"]) {
@@ -14975,12 +15506,12 @@ var messageText = (content, depth = 0) => {
14975
15506
  if (t)
14976
15507
  return t;
14977
15508
  }
14978
- return str8(o.type) ? `(${o.type}${str8(o.name) ? ` ${o.name}` : ""})` : "";
15509
+ return str9(o.type) ? `(${o.type}${str9(o.name) ? ` ${o.name}` : ""})` : "";
14979
15510
  };
14980
15511
  var renderTranscript = (messages, keep = 40, clip = 2000) => messages.slice(-keep).map((m) => {
14981
15512
  const t = messageText(m.content).trim();
14982
15513
  const body = t.length > clip ? `${t.slice(0, clip)}…` : t;
14983
- return body ? `[${str8(m.type) ?? "message"}] ${body}` : "";
15514
+ return body ? `[${str9(m.type) ?? "message"}] ${body}` : "";
14984
15515
  }).filter(Boolean).join(`
14985
15516
 
14986
15517
  `);
@@ -15010,7 +15541,7 @@ function conductorRunner(exec, deps = {}) {
15010
15541
  }
15011
15542
  const res = splitCurl(r.stdout);
15012
15543
  if (res.code < 200 || res.code >= 300 || !res.body) {
15013
- const why = str8(res.body?.userMessage) ?? str8(res.body?.message) ?? (res.text.trim().slice(0, 300) || "no body");
15544
+ const why = str9(res.body?.userMessage) ?? str9(res.body?.message) ?? (res.text.trim().slice(0, 300) || "no body");
15014
15545
  throw new Error(`conductor ${method} ${path}: HTTP ${res.code}: ${why}`);
15015
15546
  }
15016
15547
  return res.body;
@@ -15040,15 +15571,15 @@ function conductorRunner(exec, deps = {}) {
15040
15571
  ...effort ? { effort } : {},
15041
15572
  message: prompt
15042
15573
  });
15043
- const workspace = str8(created.workspaceId);
15044
- const session = str8(created.sessionId);
15574
+ const workspace = str9(created.workspaceId);
15575
+ const session = str9(created.sessionId);
15045
15576
  if (!workspace || !session) {
15046
15577
  throw new Error(`conductor: workspace create for ${o.name} returned no workspace or session id`);
15047
15578
  }
15048
- if (!obj(created.initialMessage)) {
15579
+ if (!obj2(created.initialMessage)) {
15049
15580
  api("POST", `/v0/sessions/${session}/messages`, { message: prompt });
15050
15581
  }
15051
- const link = str8(created.deepLink);
15582
+ const link = str9(created.deepLink);
15052
15583
  return {
15053
15584
  runner: "conductor",
15054
15585
  id: `${workspace}/${session}`,
@@ -15070,8 +15601,8 @@ function conductorRunner(exec, deps = {}) {
15070
15601
  let line = "";
15071
15602
  try {
15072
15603
  const s = api("GET", `/v0/sessions/${session}/status`);
15073
- state = str8(s.status) ?? "unknown";
15074
- const err = str8(s.lastError) ?? str8(s.errorMessage);
15604
+ state = str9(s.status) ?? "unknown";
15605
+ const err = str9(s.lastError) ?? str9(s.errorMessage);
15075
15606
  line = state === "working" ? `conductor session: working (checked ${new Date(now()).toISOString()})` : `conductor session: ${state}${err ? ` — ${err}` : ""}`;
15076
15607
  } catch (e) {
15077
15608
  line = `conductor session: status unread (${e instanceof Error ? e.message : String(e)})`;
@@ -15183,8 +15714,8 @@ function headlessRunner(deps = {}) {
15183
15714
  // src/runners/managed.ts
15184
15715
  init_src();
15185
15716
  import { readFileSync as readFileSync12 } from "node:fs";
15186
- var obj2 = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
15187
- var str9 = (v) => typeof v === "string" && v.length > 0 ? v : null;
15717
+ var obj3 = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
15718
+ var str10 = (v) => typeof v === "string" && v.length > 0 ? v : null;
15188
15719
  var ANTHROPIC_API = "https://api.anthropic.com";
15189
15720
  var MANAGED_BETA = "managed-agents-2026-04-01";
15190
15721
  var DEFAULT_BUDGET_USD = 25;
@@ -15259,7 +15790,7 @@ var lastIdle = (events) => {
15259
15790
  return null;
15260
15791
  };
15261
15792
  var pendingAsks = (events, idle) => {
15262
- const ids = obj2(idle?.stop_reason)?.event_ids;
15793
+ const ids = obj3(idle?.stop_reason)?.event_ids;
15263
15794
  if (!Array.isArray(ids))
15264
15795
  return [];
15265
15796
  const want = new Set(ids.filter((x) => typeof x === "string"));
@@ -15280,7 +15811,7 @@ var eventMessages = (events) => {
15280
15811
  case "agent.custom_tool_use":
15281
15812
  out.push({
15282
15813
  type: "tool",
15283
- content: `(${str9(e.name) ?? "tool"}${e.evaluated_permission === "ask" ? " — waiting on a yes" : ""})`
15814
+ content: `(${str10(e.name) ?? "tool"}${e.evaluated_permission === "ask" ? " — waiting on a yes" : ""})`
15284
15815
  });
15285
15816
  break;
15286
15817
  case "session.error":
@@ -15291,9 +15822,9 @@ var eventMessages = (events) => {
15291
15822
  return out;
15292
15823
  };
15293
15824
  var statusLine2 = (session, events, now) => {
15294
- const status = str9(session.status) ?? "unknown";
15295
- const spent = usd4(obj2(obj2(session.usage)?.list_cost)?.amount);
15296
- const cap = usd4(obj2(obj2(session.budget)?.max_list_cost)?.amount);
15825
+ const status = str10(session.status) ?? "unknown";
15826
+ const spent = usd4(obj3(obj3(session.usage)?.list_cost)?.amount);
15827
+ const cap = usd4(obj3(obj3(session.budget)?.max_list_cost)?.amount);
15297
15828
  const money = spent ? ` · ${spent}${cap ? ` of ${cap}` : ""}` : "";
15298
15829
  if (status === "running" || status === "rescheduling") {
15299
15830
  return `managed session: ${status} (checked ${new Date(now).toISOString()})${money}`;
@@ -15301,10 +15832,10 @@ var statusLine2 = (session, events, now) => {
15301
15832
  if (status !== "idle")
15302
15833
  return `managed session: ${status}${money}`;
15303
15834
  const idle = lastIdle(events);
15304
- const why = str9(obj2(idle?.stop_reason)?.type);
15835
+ const why = str10(obj3(idle?.stop_reason)?.type);
15305
15836
  switch (why) {
15306
15837
  case "requires_action": {
15307
- const tools = pendingAsks(events, idle).map((e) => str9(e.name) ?? "a tool").join(", ");
15838
+ const tools = pendingAsks(events, idle).map((e) => str10(e.name) ?? "a tool").join(", ");
15308
15839
  return `managed session: idle — waiting on a yes for ${tools || "a tool call"} (answer yes to allow, anything else denies)${money}`;
15309
15840
  }
15310
15841
  case "budget_reached":
@@ -15315,7 +15846,7 @@ var statusLine2 = (session, events, now) => {
15315
15846
  return `managed session: idle — its turn ended${money}`;
15316
15847
  }
15317
15848
  };
15318
- var YES = /^\s*(?:y|yes|allow|ok|okay|go|go ahead|approve[d]?)\b/i;
15849
+ var YES2 = /^\s*(?:y|yes|allow|ok|okay|go|go ahead|approve[d]?)\b/i;
15319
15850
  function managedRunner(exec, deps = {}) {
15320
15851
  const env = deps.env ?? process.env;
15321
15852
  const readFile = deps.readFile ?? ((p) => readFileSync12(p, "utf8"));
@@ -15338,7 +15869,7 @@ function managedRunner(exec, deps = {}) {
15338
15869
  }
15339
15870
  const res = splitCurl(r.stdout);
15340
15871
  if (res.code < 200 || res.code >= 300 || !res.body) {
15341
- const why = str9(obj2(res.body?.error)?.message) ?? str9(res.body?.message) ?? (res.text.trim().slice(0, 300) || "no body");
15872
+ const why = str10(obj3(res.body?.error)?.message) ?? str10(res.body?.message) ?? (res.text.trim().slice(0, 300) || "no body");
15342
15873
  throw new Error(`managed ${method} ${path}: HTTP ${res.code}: ${why}`);
15343
15874
  }
15344
15875
  return res.body;
@@ -15350,7 +15881,7 @@ function managedRunner(exec, deps = {}) {
15350
15881
  const got = api("GET", `/v1/sessions/${id}/events?limit=1000${page ? `&page=${encodeURIComponent(page)}` : ""}`);
15351
15882
  const data = Array.isArray(got.data) ? got.data : [];
15352
15883
  out.push(...data);
15353
- page = str9(got.next_page);
15884
+ page = str10(got.next_page);
15354
15885
  if (!page || data.length === 0)
15355
15886
  break;
15356
15887
  }
@@ -15413,7 +15944,7 @@ function managedRunner(exec, deps = {}) {
15413
15944
  }
15414
15945
  ]
15415
15946
  });
15416
- const id = str9(created.id);
15947
+ const id = str10(created.id);
15417
15948
  if (!id)
15418
15949
  throw new Error(`managed: session create for ${o.name} returned no id`);
15419
15950
  return { runner: "managed", id, cwd: o.repoPath, log: consoleUrl(id) };
@@ -15438,9 +15969,9 @@ ${renderTranscript(eventMessages(all))}`;
15438
15969
  const session = api("GET", `/v1/sessions/${h.id}`);
15439
15970
  const all = session.status === "idle" ? events(h.id) : [];
15440
15971
  const idle = lastIdle(all);
15441
- const asks = str9(obj2(idle?.stop_reason)?.type) === "requires_action" ? pendingAsks(all, idle) : [];
15972
+ const asks = str10(obj3(idle?.stop_reason)?.type) === "requires_action" ? pendingAsks(all, idle) : [];
15442
15973
  if (asks.length) {
15443
- const allow = YES.test(text);
15974
+ const allow = YES2.test(text);
15444
15975
  api("POST", `/v1/sessions/${h.id}/events`, {
15445
15976
  events: asks.map((e) => ({
15446
15977
  type: "user.tool_confirmation",
@@ -15487,156 +16018,6 @@ ${renderTranscript(eventMessages(all))}`;
15487
16018
  };
15488
16019
  }
15489
16020
 
15490
- // src/runners/orca.ts
15491
- import { writeFileSync as writeFileSync12 } from "node:fs";
15492
- var obj3 = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
15493
- var str10 = (v) => typeof v === "string" && v.length > 0 ? v : null;
15494
- var parseOrcaJson = (stdout) => {
15495
- try {
15496
- return obj3(JSON.parse(stdout));
15497
- } catch {
15498
- return null;
15499
- }
15500
- };
15501
- var orcaError = (env) => {
15502
- if (!env || env.ok !== false)
15503
- return null;
15504
- const e = obj3(env.error);
15505
- const message = str10(e?.message) ?? "Orca refused the call";
15506
- const code = str10(e?.code);
15507
- return code ? `${message} (${code})` : message;
15508
- };
15509
- var parseOrcaWorktree = (env) => {
15510
- const result = obj3(env.result) ?? {};
15511
- return str10(obj3(result.worktree)?.path) ?? str10(result.worktreePath) ?? str10(result.path);
15512
- };
15513
- var parseOrcaBranch = (env) => {
15514
- const wt = obj3(obj3(env.result)?.worktree);
15515
- const branch = str10(wt?.branch)?.replace(/^refs\/heads\//, "");
15516
- const head = str10(wt?.head);
15517
- return branch && head ? { branch, head } : null;
15518
- };
15519
- var parseOrcaTerminal = (env) => {
15520
- const result = obj3(env.result) ?? {};
15521
- return str10(obj3(result.terminal)?.handle) ?? str10(result.handle) ?? str10(result.terminalHandle) ?? null;
15522
- };
15523
- var orcaLauncher = (o) => `#!/bin/sh
15524
- # sleds engine: ${o.name}
15525
- exec ${agentShellCommand(o)}
15526
- `;
15527
- var orcaCommand = (launcher) => `sh ${shq2(launcher)}; exit`;
15528
- var GONE = /exit|clos|gone|dead|stopp|kill/i;
15529
- var orcaTerminalLive = (status, stdout) => {
15530
- const env = parseOrcaJson(stdout);
15531
- if (str10(obj3(env?.error)?.code) === "runtime_unavailable")
15532
- return true;
15533
- if (status !== 0 || !env || env.ok === false)
15534
- return false;
15535
- const t = obj3(obj3(env.result)?.terminal) ?? obj3(env.result) ?? {};
15536
- if (typeof t.status === "string" && GONE.test(t.status))
15537
- return false;
15538
- if (t.exited === true || t.alive === false)
15539
- return false;
15540
- if (typeof t.exitCode === "number")
15541
- return false;
15542
- if (obj3(t.exitCause))
15543
- return false;
15544
- if (t.orphaned === true && t.writable === false)
15545
- return false;
15546
- return true;
15547
- };
15548
- var launcherPath2 = (promptFile) => `${promptFile.replace(/\.md$/, "")}.orca.sh`;
15549
- function orcaRunner(exec, deps = {}) {
15550
- const writeFile = deps.writeFile ?? ((p, t) => writeFileSync12(p, t, { mode: 384 }));
15551
- const orca = (args, what) => {
15552
- const r = exec("orca", args);
15553
- const env = parseOrcaJson(r.stdout);
15554
- const refused = orcaError(env);
15555
- if (refused)
15556
- throw new Error(`${what}: ${refused}`);
15557
- if (r.status !== 0 || !env) {
15558
- throw new Error(`${what} failed: ${r.stderr.trim() || r.stdout.trim() || `exit ${r.status}`}`);
15559
- }
15560
- return env;
15561
- };
15562
- return {
15563
- name: "orca",
15564
- makesWorktree: true,
15565
- readsSession: true,
15566
- start(o) {
15567
- const created = orca([
15568
- "worktree",
15569
- "create",
15570
- "--repo",
15571
- `path:${o.repoPath}`,
15572
- "--name",
15573
- o.name,
15574
- "--base-branch",
15575
- `origin/${o.base ?? "main"}`,
15576
- "--no-parent",
15577
- "--json"
15578
- ], `orca worktree create ${o.name}`);
15579
- const cwd = parseOrcaWorktree(created);
15580
- if (!cwd) {
15581
- throw new Error(`orca worktree create ${o.name} returned no worktree path; the agent was not started`);
15582
- }
15583
- const launcher = launcherPath2(o.promptFile);
15584
- writeFile(launcher, orcaLauncher(o));
15585
- const shown = orca([
15586
- "terminal",
15587
- "create",
15588
- "--worktree",
15589
- `path:${cwd}`,
15590
- "--title",
15591
- o.name,
15592
- "--command",
15593
- orcaCommand(launcher),
15594
- "--json"
15595
- ], `orca terminal create ${o.name} (worktree ${cwd})`);
15596
- const terminal = parseOrcaTerminal(shown);
15597
- if (!terminal) {
15598
- throw new Error(`orca terminal create ${o.name} started in ${cwd} but returned no terminal handle`);
15599
- }
15600
- const own = parseOrcaBranch(created);
15601
- const h = { runner: "orca", id: terminal, cwd, ...own ? { own } : {} };
15602
- return h;
15603
- },
15604
- status(h) {
15605
- const r = exec("orca", ["terminal", "show", "--terminal", h.id, "--json"]);
15606
- return orcaTerminalLive(r.status, r.stdout) ? "running" : "exited";
15607
- },
15608
- read(h) {
15609
- const r = exec("orca", ["terminal", "read", "--terminal", h.id, "--limit", "200"]);
15610
- return r.status === 0 ? r.stdout : "";
15611
- },
15612
- send(h, text) {
15613
- const r = exec("orca", ["terminal", "send", "--terminal", h.id, "--text", text, "--enter"]);
15614
- if (r.status !== 0) {
15615
- throw new Error(`orca terminal send ${h.id} failed: ${r.stderr.trim() || `exit ${r.status}`}`);
15616
- }
15617
- },
15618
- stop(h) {
15619
- exec("orca", ["terminal", "close", "--terminal", h.id]);
15620
- },
15621
- watchHint(h) {
15622
- return `orca terminal show --terminal ${h.id}`;
15623
- },
15624
- removeWorktree(h, repoPath) {
15625
- orca(["worktree", "rm", "--worktree", `path:${h.cwd}`, "--json"], `orca worktree rm ${h.cwd}`);
15626
- if (!h.own)
15627
- return;
15628
- const ref = `refs/heads/${h.own.branch}`;
15629
- const r = exec("git", ["-C", repoPath, "update-ref", "-d", ref, h.own.head]);
15630
- if (r.status === 0)
15631
- return;
15632
- const still = exec("git", ["-C", repoPath, "rev-parse", "--verify", "--quiet", ref]);
15633
- if (still.status !== 0)
15634
- return;
15635
- return `kept Orca's branch ${h.own.branch}: ${r.stderr.trim() || `exit ${r.status}`}`;
15636
- }
15637
- };
15638
- }
15639
-
15640
16021
  // src/runners/tmux.ts
15641
16022
  var tmuxSession = (name) => `=${name}`;
15642
16023
  var tmuxPane = (name) => `=${name}:`;
@@ -15997,7 +16378,7 @@ function flagsFromProfile(flags, given, profile, home) {
15997
16378
  }
15998
16379
  }
15999
16380
  if (profile.reposDir && !has("repos-dir") && !has("repo")) {
16000
- out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ? join15(home, d.slice(1)) : d).join(":");
16381
+ out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ? join16(home, d.slice(1)) : d).join(":");
16001
16382
  used.push(`repos ${profile.reposDir}`);
16002
16383
  }
16003
16384
  if (profile.mcpStrict !== undefined && !has("strict-mcp") && !has("no-strict-mcp")) {
@@ -16127,12 +16508,12 @@ function memberMcpConfigs(o, cwd) {
16127
16508
  });
16128
16509
  const claudeDir = (o.env ?? process.env).CLAUDE_CONFIG_DIR;
16129
16510
  return [
16130
- read(claudeDir ? join15(claudeDir, ".claude.json") : join15(o.home, ".claude.json")),
16131
- ...cwd ? [read(join15(cwd, ".mcp.json"))] : []
16511
+ read(claudeDir ? join16(claudeDir, ".claude.json") : join16(o.home, ".claude.json")),
16512
+ ...cwd ? [read(join16(cwd, ".mcp.json"))] : []
16132
16513
  ];
16133
16514
  }
16134
16515
  function engineStateDir(o, org, seat) {
16135
- return seatStateDir(orgStateDir(o.stateDir ?? join15(configDir(o.home, o.env ?? process.env), "engine"), org), seat);
16516
+ return seatStateDir(orgStateDir(o.stateDir ?? join16(configDir(o.home, o.env ?? process.env), "engine"), org), seat);
16136
16517
  }
16137
16518
  function engineSeat(o, org) {
16138
16519
  try {
@@ -16159,11 +16540,11 @@ function engineDeps(o, flags, source, runner, stateName) {
16159
16540
  const stateDir = engineStateDir(o, flags.org, flags.seat);
16160
16541
  const file = statePath(stateDir, stateName);
16161
16542
  const mcpOrg = flags.org && engineOrg(o, flags.org).seated ? flags.org : undefined;
16162
- const repo = flags.repo ? resolve7(cwd, flags.repo) : undefined;
16163
- const reposDirs = splitReposDirs(flags.reposDir).map((d) => resolve7(cwd, d));
16543
+ const repo = flags.repo ? resolve8(cwd, flags.repo) : undefined;
16544
+ const reposDirs = splitReposDirs(flags.reposDir).map((d) => resolve8(cwd, d));
16164
16545
  const { branch, prTitle } = flags;
16165
- const hooksDir = join15(stateDir, "hooks");
16166
- const permissionMark = (name) => join15(hooksDir, `${name}.permission.json`);
16546
+ const hooksDir = join16(stateDir, "hooks");
16547
+ const permissionMark = (name) => join16(hooksDir, `${name}.permission.json`);
16167
16548
  const withHook = (name, settings) => applyPermissionHook(settings, [...o.sledsArgv ?? ["sleds"], "permission-event", "--mark", permissionMark(name)].map(shq2).join(" "));
16168
16549
  return {
16169
16550
  source,
@@ -16188,9 +16569,9 @@ function engineDeps(o, flags, source, runner, stateName) {
16188
16569
  sandbox: true,
16189
16570
  writeSandboxSettings: o.writeSandboxSettings ?? ((name, cwd) => {
16190
16571
  const gitCommonDir = gitCommonDirOf(exec, cwd);
16191
- const dir = join15(stateDir, "sandbox");
16572
+ const dir = join16(stateDir, "sandbox");
16192
16573
  mkdirSync12(dir, { recursive: true, mode: 448 });
16193
- const p = join15(dir, `${name}.json`);
16574
+ const p = join16(dir, `${name}.json`);
16194
16575
  const walls = engineSandboxSettings(o.home, o.env ?? process.env, gitCommonDir, [
16195
16576
  ...SANDBOX_DEFAULT_ALLOW,
16196
16577
  ...flags.sandboxAllow ?? []
@@ -16204,7 +16585,7 @@ function engineDeps(o, flags, source, runner, stateName) {
16204
16585
  } : {},
16205
16586
  writeHookSettings: (name) => {
16206
16587
  mkdirSync12(hooksDir, { recursive: true, mode: 448 });
16207
- const p = join15(hooksDir, `${name}.json`);
16588
+ const p = join16(hooksDir, `${name}.json`);
16208
16589
  writeFileSync13(p, `${JSON.stringify(withHook(name, {}), null, 2)}
16209
16590
  `, { mode: 384 });
16210
16591
  chmodSync4(p, 384);
@@ -16231,9 +16612,9 @@ function engineDeps(o, flags, source, runner, stateName) {
16231
16612
  exists
16232
16613
  }),
16233
16614
  writeMcpConfig: o.writeMcpConfig ?? ((name, runToken, worktree) => {
16234
- const dir = join15(stateDir, "mcp");
16615
+ const dir = join16(stateDir, "mcp");
16235
16616
  mkdirSync12(dir, { recursive: true, mode: 448 });
16236
- const p = join15(dir, `${name}.json`);
16617
+ const p = join16(dir, `${name}.json`);
16237
16618
  let others = {};
16238
16619
  if (flags.strictMcp && flags.mcpAllow?.length) {
16239
16620
  const r = mcpPassThrough(flags.mcpAllow, memberMcpConfigs(o, worktree));
@@ -16249,9 +16630,9 @@ function engineDeps(o, flags, source, runner, stateName) {
16249
16630
  }),
16250
16631
  removeMcpConfig: o.removeMcpConfig ?? ((p) => rmSync4(p, { force: true })),
16251
16632
  writePrompt: o.writePrompt ?? ((name, text) => {
16252
- const dir = join15(stateDir, "prompts");
16633
+ const dir = join16(stateDir, "prompts");
16253
16634
  mkdirSync12(dir, { recursive: true, mode: 448 });
16254
- const p = join15(dir, `${name}.md`);
16635
+ const p = join16(dir, `${name}.md`);
16255
16636
  writeFileSync13(p, text, { mode: 384 });
16256
16637
  return p;
16257
16638
  }),
@@ -16278,8 +16659,8 @@ function engineDeps(o, flags, source, runner, stateName) {
16278
16659
  }
16279
16660
  function sandboxDenyRead(home, env) {
16280
16661
  return {
16281
- dirs: [...new Set([configDir(home, env), join15(home, ".config", "sleds")])],
16282
- files: [...new Set([tokenPath(home, env), join15(home, ".sleds-token")])]
16662
+ dirs: [...new Set([configDir(home, env), join16(home, ".config", "sleds")])],
16663
+ files: [...new Set([tokenPath(home, env), join16(home, ".sleds-token")])]
16283
16664
  };
16284
16665
  }
16285
16666
  function engineSandboxSettings(home, env, gitCommonDir, allow) {
@@ -16294,7 +16675,7 @@ function gitCommonDirOf(exec, cwd) {
16294
16675
  const dir = r.status === 0 ? r.stdout.trim() : "";
16295
16676
  if (!dir)
16296
16677
  throw new Error(`git has no common dir for ${cwd}, so the sandbox has nowhere to commit`);
16297
- return resolve7(cwd, dir);
16678
+ return resolve8(cwd, dir);
16298
16679
  }
16299
16680
  function pinOrg2(configJson, org) {
16300
16681
  if (!org)
@@ -16336,13 +16717,14 @@ async function driveEngine(o, flags, deps, until = {}) {
16336
16717
  runner: deps.runner.name,
16337
16718
  atOnce: flags.atOnce,
16338
16719
  interval: flags.interval,
16339
- cliVersion: "0.1.42"
16720
+ cliVersion: "0.1.44"
16340
16721
  };
16341
16722
  const beat = (checkedAt) => {
16342
16723
  const m = deps.machine;
16343
16724
  try {
16344
16725
  writeLock(lockFile, checkedAt === undefined ? lock : {
16345
16726
  ...lock,
16727
+ runner: deps.runner.name,
16346
16728
  atOnce: deps.atOnce,
16347
16729
  checkedAt,
16348
16730
  nextCheckAt: checkedAt + flags.interval * 1000,
@@ -16647,9 +17029,8 @@ async function enginePauseCmd(o) {
16647
17029
 
16648
17030
  // src/commands/engineInstall.ts
16649
17031
  init_config();
16650
- init_state();
16651
17032
  import {
16652
- existsSync as existsSync14,
17033
+ existsSync as existsSync15,
16653
17034
  mkdirSync as mkdirSync14,
16654
17035
  readFileSync as readFileSync14,
16655
17036
  readdirSync as readdirSync2,
@@ -16658,12 +17039,13 @@ import {
16658
17039
  writeFileSync as writeFileSync15
16659
17040
  } from "node:fs";
16660
17041
  import { hostname as hostname3 } from "node:os";
16661
- import { basename as basename4, dirname as dirname12, isAbsolute as isAbsolute2, join as join18 } from "node:path";
17042
+ import { basename as basename4, dirname as dirname12, isAbsolute as isAbsolute2, join as join19 } from "node:path";
17043
+ init_state();
16662
17044
 
16663
17045
  // src/schedule.ts
16664
17046
  import { spawnSync as spawnSync4 } from "node:child_process";
16665
- import { existsSync as existsSync13, mkdirSync as mkdirSync13, rmSync as rmSync5, writeFileSync as writeFileSync14 } from "node:fs";
16666
- import { join as join16 } from "node:path";
17047
+ import { existsSync as existsSync14, mkdirSync as mkdirSync13, rmSync as rmSync5, writeFileSync as writeFileSync14 } from "node:fs";
17048
+ import { join as join17 } from "node:path";
16667
17049
  var REVERT_LABEL = "ai.sleds.revert";
16668
17050
  var defaultExec2 = (cmd, args) => {
16669
17051
  const r = spawnSync4(cmd, [...args], { stdio: ["ignore", "ignore", "pipe"], encoding: "utf8" });
@@ -16671,7 +17053,7 @@ var defaultExec2 = (cmd, args) => {
16671
17053
  return { ok: false, stderr: r.error.message };
16672
17054
  return { ok: r.status === 0, stderr: r.stderr ?? "" };
16673
17055
  };
16674
- var plistPath = (home) => join16(home, "Library", "LaunchAgents", `${REVERT_LABEL}.plist`);
17056
+ var plistPath = (home) => join17(home, "Library", "LaunchAgents", `${REVERT_LABEL}.plist`);
16675
17057
  var xmlEscape2 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
16676
17058
  var buildLaunchdPlist = (sledsArgv, deadline) => {
16677
17059
  const args = [...sledsArgv, "off"].map((a) => ` <string>${xmlEscape2(a)}</string>`).join(`
@@ -16710,7 +17092,7 @@ var scheduleRevert = (d, deadlineMs) => {
16710
17092
  if (d.platform === "darwin") {
16711
17093
  const p = plistPath(d.home);
16712
17094
  try {
16713
- mkdirSync13(join16(d.home, "Library", "LaunchAgents"), { recursive: true });
17095
+ mkdirSync13(join17(d.home, "Library", "LaunchAgents"), { recursive: true });
16714
17096
  d.exec("launchctl", ["unload", p]);
16715
17097
  writeFileSync14(p, buildLaunchdPlist(d.sledsArgv, deadline));
16716
17098
  const r = d.exec("launchctl", ["load", p]);
@@ -16739,7 +17121,7 @@ var scheduleRevert = (d, deadlineMs) => {
16739
17121
  var cancelRevert = (d, kind) => {
16740
17122
  if (kind === "launchd" || d.platform === "darwin") {
16741
17123
  const p = plistPath(d.home);
16742
- if (existsSync13(p)) {
17124
+ if (existsSync14(p)) {
16743
17125
  d.exec("launchctl", ["unload", p]);
16744
17126
  rmSync5(p, { force: true });
16745
17127
  }
@@ -16750,16 +17132,16 @@ var cancelRevert = (d, kind) => {
16750
17132
  };
16751
17133
 
16752
17134
  // src/commands/engineSystemd.ts
16753
- import { join as join17 } from "node:path";
17135
+ import { join as join18 } from "node:path";
16754
17136
  var BOX_ENV_UNIT_PATH = "%h/.config/sleds/box.env";
16755
17137
  function boxEnvPath(home) {
16756
- return join17(home, ".config", "sleds", "box.env");
17138
+ return join18(home, ".config", "sleds", "box.env");
16757
17139
  }
16758
17140
  function engineUnitDir(home) {
16759
- return join17(home, ".config", "systemd", "user");
17141
+ return join18(home, ".config", "systemd", "user");
16760
17142
  }
16761
17143
  function engineUnitPath(home, label) {
16762
- return join17(engineUnitDir(home), `${label}.service`);
17144
+ return join18(engineUnitDir(home), `${label}.service`);
16763
17145
  }
16764
17146
  function systemdQuote(s) {
16765
17147
  const body = s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/%/g, "%%").replace(/\$/g, "$$$$");
@@ -16817,13 +17199,13 @@ function engineLabel(name, org, seat) {
16817
17199
  return [ENGINE_LABEL, org, seat?.trim(), name].filter((p) => Boolean(p)).map((p, i) => i === 0 ? p : engineSlug(p)).join(".");
16818
17200
  }
16819
17201
  function enginePlistPath(home, name, org, seat) {
16820
- return join18(home, "Library", "LaunchAgents", `${engineLabel(name, org, seat)}.plist`);
17202
+ return join19(home, "Library", "LaunchAgents", `${engineLabel(name, org, seat)}.plist`);
16821
17203
  }
16822
17204
  function engineLogPath(stateDir, name) {
16823
- return join18(stateDir, `${engineSlug(name)}.log`);
17205
+ return join19(stateDir, `${engineSlug(name)}.log`);
16824
17206
  }
16825
17207
  function engineEventsPath(stateDir, name) {
16826
- return join18(stateDir, `${engineSlug(name)}.events.jsonl`);
17208
+ return join19(stateDir, `${engineSlug(name)}.events.jsonl`);
16827
17209
  }
16828
17210
  var xmlEscape3 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
16829
17211
  function buildEnginePlist(o) {
@@ -16899,7 +17281,13 @@ function parseEnginePlist(text) {
16899
17281
  if (!label || array === undefined)
16900
17282
  return null;
16901
17283
  const programArgs = [...array.matchAll(/<string>([^<]*)<\/string>/g)].map((m) => xmlUnescape(m[1] ?? ""));
16902
- return { label: xmlUnescape(label), programArgs };
17284
+ const envDict = /<key>EnvironmentVariables<\/key>\s*<dict>([\s\S]*?)<\/dict>/.exec(text)?.[1];
17285
+ const path = envDict && /<key>PATH<\/key>\s*<string>([^<]*)<\/string>/.exec(envDict)?.[1];
17286
+ return {
17287
+ label: xmlUnescape(label),
17288
+ programArgs,
17289
+ ...typeof path === "string" ? { path: xmlUnescape(path) } : {}
17290
+ };
16903
17291
  }
16904
17292
  function engineArg(programArgs, flag) {
16905
17293
  const at = programArgs.indexOf(`--${flag}`);
@@ -16914,7 +17302,7 @@ function readEngines(dir, suffix, manager, parse) {
16914
17302
  }
16915
17303
  const out = [];
16916
17304
  for (const name of names.filter((n) => n.startsWith(`${ENGINE_LABEL}.`) && n.endsWith(suffix))) {
16917
- const path = join18(dir, name);
17305
+ const path = join19(dir, name);
16918
17306
  let parsed;
16919
17307
  try {
16920
17308
  parsed = parse(readFileSync14(path, "utf8"), name);
@@ -16934,7 +17322,7 @@ function readEngines(dir, suffix, manager, parse) {
16934
17322
  }
16935
17323
  function installedEngines(home) {
16936
17324
  return [
16937
- ...readEngines(join18(home, "Library", "LaunchAgents"), ".plist", "launchd", parseEnginePlist),
17325
+ ...readEngines(join19(home, "Library", "LaunchAgents"), ".plist", "launchd", parseEnginePlist),
16938
17326
  ...readEngines(engineUnitDir(home), ".service", "systemd", (text, file) => {
16939
17327
  const parsed = parseEngineUnit(text);
16940
17328
  return parsed && { label: basename4(file, ".service"), ...parsed };
@@ -16985,7 +17373,7 @@ function engineInstall(o) {
16985
17373
  return installUnit({ o, parsed, label, sledsArgv, env: agentEnv, logPath, exec });
16986
17374
  const plist = enginePlistPath(o.home, parsed.name, parsed.org, seat);
16987
17375
  mkdirSync14(dirname12(plist), { recursive: true });
16988
- if (existsSync14(plist))
17376
+ if (existsSync15(plist))
16989
17377
  exec("launchctl", ["unload", plist]);
16990
17378
  for (const other of installedEngines(o.home)) {
16991
17379
  if (other.manager !== "launchd" || other.plist === plist || other.org !== parsed.org)
@@ -16997,7 +17385,7 @@ function engineInstall(o) {
16997
17385
  log(`replaced ${other.label}, this engine as installed before`);
16998
17386
  }
16999
17387
  const legacy = enginePlistPath(o.home, parsed.name);
17000
- if (parsed.org && existsSync14(legacy)) {
17388
+ if (parsed.org && existsSync15(legacy)) {
17001
17389
  const cfg = readConfig(o.home);
17002
17390
  if (org.sole || parsed.org === (cfg.activeOrg ?? cfg.org?.slug)) {
17003
17391
  exec("launchctl", ["unload", legacy]);
@@ -17027,7 +17415,7 @@ function installUnit(a) {
17027
17415
  const unitName = basename4(unit);
17028
17416
  const systemctl = (...args) => exec("systemctl", ["--user", ...args]);
17029
17417
  mkdirSync14(dirname12(unit), { recursive: true });
17030
- if (existsSync14(unit))
17418
+ if (existsSync15(unit))
17031
17419
  systemctl("stop", unitName);
17032
17420
  for (const other of installedEngines(o.home)) {
17033
17421
  if (other.manager !== "systemd" || other.plist === unit || other.org !== parsed.org)
@@ -17085,7 +17473,7 @@ function engineUninstall(o) {
17085
17473
  ...installed.filter((e) => e.manager === manager).map((e) => e.plist),
17086
17474
  ...args.org ? [] : [pathOf(manager)]
17087
17475
  ]);
17088
- const file = candidates.find((p) => existsSync14(p));
17476
+ const file = candidates.find((p) => existsSync15(p));
17089
17477
  if (!file) {
17090
17478
  log(`engine:${name} was not installed (no ${candidates[0]}).`);
17091
17479
  return 0;
@@ -17104,20 +17492,20 @@ function engineUninstall(o) {
17104
17492
  }
17105
17493
 
17106
17494
  // src/commands/musher.ts
17107
- import { existsSync as existsSync15, mkdirSync as mkdirSync15, readFileSync as readFileSync15, rmSync as rmSync7, writeFileSync as writeFileSync16 } from "node:fs";
17495
+ import { existsSync as existsSync16, mkdirSync as mkdirSync15, readFileSync as readFileSync15, rmSync as rmSync7, writeFileSync as writeFileSync16 } from "node:fs";
17108
17496
  init_config();
17109
17497
  init_meter();
17110
17498
  var defaultWhich = (cmd) => {
17111
17499
  const path = process.env.PATH ?? "";
17112
17500
  for (const dir of path.split(":").filter(Boolean)) {
17113
17501
  const p = `${dir}/${cmd}`;
17114
- if (existsSync15(p))
17502
+ if (existsSync16(p))
17115
17503
  return p;
17116
17504
  }
17117
17505
  return null;
17118
17506
  };
17119
17507
  var findClaude = (home, configured, which) => {
17120
- if (configured && existsSync15(configured))
17508
+ if (configured && existsSync16(configured))
17121
17509
  return configured;
17122
17510
  const found = which("claude");
17123
17511
  if (found)
@@ -17128,13 +17516,13 @@ var findClaude = (home, configured, which) => {
17128
17516
  "/usr/local/bin/claude",
17129
17517
  `${home}/.npm-global/bin/claude`
17130
17518
  ])
17131
- if (existsSync15(p))
17519
+ if (existsSync16(p))
17132
17520
  return p;
17133
17521
  return null;
17134
17522
  };
17135
17523
  var musherAgentState = (home, env = process.env) => {
17136
17524
  const plist = musherPlistPath(home, env);
17137
- if (!existsSync15(plist))
17525
+ if (!existsSync16(plist))
17138
17526
  return { installed: false, thisSeat: false };
17139
17527
  try {
17140
17528
  const text = readFileSync15(plist, "utf8");
@@ -17146,6 +17534,42 @@ var musherAgentState = (home, env = process.env) => {
17146
17534
  }
17147
17535
  };
17148
17536
 
17537
+ // src/claudeAccount.ts
17538
+ import { readFileSync as readFileSync16 } from "node:fs";
17539
+ var PLANS = {
17540
+ claude_max: "Max",
17541
+ claude_pro: "Pro",
17542
+ claude_team: "Team",
17543
+ claude_enterprise: "Enterprise"
17544
+ };
17545
+ var str11 = (v) => typeof v === "string" && v.trim() !== "" ? v.trim() : undefined;
17546
+ var parseClaudeAccount = (raw) => {
17547
+ if (typeof raw !== "object" || raw === null)
17548
+ return null;
17549
+ const acct = raw.oauthAccount;
17550
+ if (typeof acct !== "object" || acct === null)
17551
+ return null;
17552
+ const a = acct;
17553
+ const email = str11(a.emailAddress);
17554
+ if (!email)
17555
+ return null;
17556
+ const out = { email };
17557
+ const type = str11(a.organizationType);
17558
+ if (type && PLANS[type])
17559
+ out.plan = PLANS[type];
17560
+ const orgName = str11(a.organizationName);
17561
+ if (orgName)
17562
+ out.orgName = orgName;
17563
+ return out;
17564
+ };
17565
+ var readClaudeAccount = (home, env = process.env) => {
17566
+ try {
17567
+ return parseClaudeAccount(JSON.parse(readFileSync16(claudeUserConfigPath2(home, env), "utf8")));
17568
+ } catch {
17569
+ return null;
17570
+ }
17571
+ };
17572
+
17149
17573
  // src/commands/status.ts
17150
17574
  init_config();
17151
17575
  init_settings();
@@ -17214,7 +17638,7 @@ async function runDoctor(o) {
17214
17638
  ].filter(Boolean);
17215
17639
  const cfgDir = configDir(home, env);
17216
17640
  const cfg = readConfig(home);
17217
- const cfgExists = existsSync16(configPath(home));
17641
+ const cfgExists = existsSync17(configPath(home));
17218
17642
  if (!cfgExists) {
17219
17643
  checks.push({
17220
17644
  level: "fail",
@@ -17230,7 +17654,7 @@ async function runDoctor(o) {
17230
17654
  });
17231
17655
  }
17232
17656
  const sPath = settingsPath(home);
17233
- const settings = existsSync16(sPath) ? readSettings(home) : null;
17657
+ const settings = existsSync17(sPath) ? readSettings(home) : null;
17234
17658
  const pointed = settings ? readProxy(settings) : null;
17235
17659
  if (!settings) {
17236
17660
  checks.push({
@@ -17277,7 +17701,7 @@ async function runDoctor(o) {
17277
17701
  detail: `seat-event ${seat ? "on" : "missing"} · spec-event ${spec ? "on" : "missing"} · session-event ${session ? "on" : "missing"} · stop-event ${stop ? "on" : "missing"}`,
17278
17702
  fix: all ? undefined : "sleds hooks"
17279
17703
  });
17280
- const want = env.SLEDS_HOME?.trim() ? resolve8(home, env.SLEDS_HOME.trim()) : undefined;
17704
+ const want = env.SLEDS_HOME?.trim() ? resolve9(home, env.SLEDS_HOME.trim()) : undefined;
17281
17705
  const cmds = sledsCommandsIn(settings);
17282
17706
  const wrong = cmds.filter((c) => {
17283
17707
  const got = bakedHome(c);
@@ -17315,7 +17739,7 @@ async function runDoctor(o) {
17315
17739
  fix: other.length + unpinned.length === 0 ? undefined : `${[...overrides, `SLEDS_ORG=${wantOrg}`].join(" ")} sleds hooks (pins the status line + hooks to ${wantOrg}; use the org this Claude config is for)`
17316
17740
  });
17317
17741
  }
17318
- const skill = existsSync16(skillPath(home));
17742
+ const skill = existsSync17(skillPath(home));
17319
17743
  checks.push({
17320
17744
  level: skill ? "ok" : "warn",
17321
17745
  name: "skill",
@@ -17349,7 +17773,7 @@ async function runDoctor(o) {
17349
17773
  const which = (o.which ?? defaultWhich2)("sleds");
17350
17774
  const stale = which.filter((p) => {
17351
17775
  try {
17352
- const target = lstatSync(p).isSymbolicLink() ? readlinkSync(p) : p;
17776
+ const target = lstatSync2(p).isSymbolicLink() ? readlinkSync2(p) : p;
17353
17777
  return /\/src\/index\.ts$/.test(target) || /\.bun\/bin\/sleds$/.test(p);
17354
17778
  } catch {
17355
17779
  return false;
@@ -17484,7 +17908,7 @@ function sandboxChecks(o, env) {
17484
17908
  fix: "npm install -g @anthropic-ai/claude-code"
17485
17909
  }
17486
17910
  ];
17487
- if (!existsSync16(dir))
17911
+ if (!existsSync17(dir))
17488
17912
  return [
17489
17913
  {
17490
17914
  level: "warn",
@@ -17494,12 +17918,12 @@ function sandboxChecks(o, env) {
17494
17918
  }
17495
17919
  ];
17496
17920
  const nonce = o.nonce ?? `sleds-probe-${randomBytes(16).toString("hex")}`;
17497
- const probe = join19(dir, SANDBOX_PROBE);
17498
- const work = mkdtempSync(join19(tmpdir(), "sleds-sandbox-"));
17921
+ const probe = join20(dir, SANDBOX_PROBE);
17922
+ const work = mkdtempSync(join20(tmpdir(), "sleds-sandbox-"));
17499
17923
  try {
17500
17924
  writeFileSync17(probe, `${nonce}
17501
17925
  `, { mode: 384 });
17502
- const settingsFile = join19(work, "settings.json");
17926
+ const settingsFile = join20(work, "settings.json");
17503
17927
  const settings = sandboxSettings({
17504
17928
  denyRead: [dir],
17505
17929
  gitCommonDir: work,
@@ -17535,7 +17959,7 @@ function engineChecks(o, env) {
17535
17959
  const checks = [];
17536
17960
  const which = (c) => (o.which ?? defaultWhich2)(c)[0] ?? null;
17537
17961
  const exec = o.exec ?? defaultExec3;
17538
- const exists = o.exists ?? existsSync16;
17962
+ const exists = o.exists ?? existsSync17;
17539
17963
  const platform = o.platform ?? process.platform;
17540
17964
  const mac = platform === "darwin";
17541
17965
  const linux = platform === "linux";
@@ -17577,6 +18001,11 @@ function engineChecks(o, env) {
17577
18001
  fix: mac ? "brew install tmux" : "install tmux with your package manager"
17578
18002
  });
17579
18003
  }
18004
+ if (runner === "orca") {
18005
+ const path = engines.find((e) => engineArg(e.programArgs, "runner") === "orca")?.path ?? env.PATH ?? "";
18006
+ const p = orcaPreflight(exec, path, o.orcaFs);
18007
+ checks.push(p.ok ? { level: "ok", name: "orca", detail: `${p.version} · the engine's runner` } : { level: need, name: "orca", detail: p.why, fix: p.fix });
18008
+ }
17580
18009
  if (linux)
17581
18010
  checks.push(...boxChecks(o, env, which, need));
17582
18011
  if (!manager)
@@ -17630,12 +18059,12 @@ function engineChecks(o, env) {
17630
18059
  level: "warn",
17631
18060
  name: "repos dir",
17632
18061
  detail: `${dirs.join(" → ")} — ${missing.join(" and ")} ${missing.length === 1 ? "does" : "do"} not exist`,
17633
- fix: "create the folder or drop it from Repos dir in Settings › Engine"
18062
+ fix: "create the folder or drop it from Repos folders in Settings › Running work"
17634
18063
  } : dirs.length ? { level: "ok", name: "repos dir", detail: dirs.join(" → ") } : repo ? { level: "ok", name: "repos dir", detail: repo } : {
17635
18064
  level: "warn",
17636
18065
  name: "repos dir",
17637
- detail: `${e.label} names no --repos-dir — it works only if Settings › Engine sets Repos dir`,
17638
- fix: "set Repos dir in Settings › Engine, or sleds engine install --repos-dir ~/code"
18066
+ detail: `${e.label} names no --repos-dir — it works only if your engine profile sets Repos folders`,
18067
+ fix: "set Repos folders in Settings › Running work, or sleds engine install --repos-dir ~/code"
17639
18068
  });
17640
18069
  }
17641
18070
  return checks;
@@ -17645,7 +18074,7 @@ function boxChecks(o, env, which, need) {
17645
18074
  const file = boxEnvPath(o.home);
17646
18075
  let named = false;
17647
18076
  try {
17648
- named = /^\s*(?:export\s+)?ANTHROPIC_API_KEY\s*=\s*\S/m.test(readFileSync16(file, "utf8"));
18077
+ named = /^\s*(?:export\s+)?ANTHROPIC_API_KEY\s*=\s*\S/m.test(readFileSync17(file, "utf8"));
17649
18078
  } catch {
17650
18079
  named = false;
17651
18080
  }
@@ -17666,7 +18095,7 @@ function boxChecks(o, env, which, need) {
17666
18095
  }
17667
18096
  function cmuxCheck(o, env) {
17668
18097
  const exec = o.exec ?? defaultExec3;
17669
- const bin = resolveCmuxBin(o.exists ?? existsSync16, env.PATH ?? "");
18098
+ const bin = resolveCmuxBin(o.exists ?? existsSync17, env.PATH ?? "");
17670
18099
  const pw = readCmuxPassword(exec);
17671
18100
  const ping = pw ? exec(bin, ["ping"], { env: { CMUX_SOCKET_PASSWORD: pw } }) : exec(bin, ["ping"]);
17672
18101
  if (ping.status === 127)
@@ -17751,13 +18180,13 @@ import {
17751
18180
  appendFileSync as appendFileSync3,
17752
18181
  chmodSync as chmodSync5,
17753
18182
  mkdirSync as mkdirSync16,
17754
- readFileSync as readFileSync17,
18183
+ readFileSync as readFileSync18,
17755
18184
  existsSync as realExists2,
17756
18185
  rmSync as rmSync9,
17757
18186
  writeFileSync as writeFileSync18
17758
18187
  } from "node:fs";
17759
18188
  import { hostname as hostname4 } from "node:os";
17760
- import { join as join20, resolve as resolve9 } from "node:path";
18189
+ import { join as join21, resolve as resolve10 } from "node:path";
17761
18190
  init_machine();
17762
18191
  init_state();
17763
18192
  init_meter();
@@ -18012,7 +18441,7 @@ function flagsFromProfile2(flags, given, profile, home) {
18012
18441
  }
18013
18442
  }
18014
18443
  if (profile.reposDir && !has("repos-dir") && !has("repo")) {
18015
- out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ? join20(home, d.slice(1)) : d).join(":");
18444
+ out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ? join21(home, d.slice(1)) : d).join(":");
18016
18445
  used.push(`repos ${profile.reposDir}`);
18017
18446
  }
18018
18447
  if (profile.mcpStrict !== undefined && !has("strict-mcp") && !has("no-strict-mcp")) {
@@ -18102,6 +18531,29 @@ async function rereadAtOnce2(read, flags, given) {
18102
18531
  const profile = await read();
18103
18532
  return profile ? profile.atOnce ?? 1 : null;
18104
18533
  }
18534
+ async function rereadRunner2(read, flags, given, home) {
18535
+ if (given.includes("runner"))
18536
+ return null;
18537
+ const profile = await read();
18538
+ if (!profile)
18539
+ return null;
18540
+ const base = {
18541
+ ...flags,
18542
+ runner: "tmux",
18543
+ runnerCmd: given.includes("runner-cmd") ? flags.runnerCmd : undefined
18544
+ };
18545
+ const r = flagsFromProfile2(base, given, profile, home);
18546
+ const skipped = r.skipped.find((s) => s.startsWith("runner"));
18547
+ if (skipped)
18548
+ return { refused: `skipped from your engine profile: ${skipped} — fix it in Settings` };
18549
+ const refusal = sandboxRefusal({ sandbox: flags.sandbox, runner: r.flags.runner });
18550
+ if (refusal)
18551
+ return { refused: `runner ${r.flags.runner} not taken — ${refusal}` };
18552
+ return {
18553
+ runner: r.flags.runner,
18554
+ ...r.flags.runner === "command" && r.flags.runnerCmd ? { runnerCmd: r.flags.runnerCmd } : {}
18555
+ };
18556
+ }
18105
18557
  var PROFILE_RETRY_MS2 = [2000, 5000];
18106
18558
  async function withProfile2(client, flags, given, home, retry) {
18107
18559
  let profile = await readProfile(client);
@@ -18173,19 +18625,19 @@ function realPidAlive2(pid) {
18173
18625
  function memberMcpConfigs2(o, cwd) {
18174
18626
  const read = o.readJson ?? ((p) => {
18175
18627
  try {
18176
- return JSON.parse(readFileSync17(p, "utf8"));
18628
+ return JSON.parse(readFileSync18(p, "utf8"));
18177
18629
  } catch {
18178
18630
  return null;
18179
18631
  }
18180
18632
  });
18181
18633
  const claudeDir = (o.env ?? process.env).CLAUDE_CONFIG_DIR;
18182
18634
  return [
18183
- read(claudeDir ? join20(claudeDir, ".claude.json") : join20(o.home, ".claude.json")),
18184
- ...cwd ? [read(join20(cwd, ".mcp.json"))] : []
18635
+ read(claudeDir ? join21(claudeDir, ".claude.json") : join21(o.home, ".claude.json")),
18636
+ ...cwd ? [read(join21(cwd, ".mcp.json"))] : []
18185
18637
  ];
18186
18638
  }
18187
18639
  function engineStateDir2(o, org, seat) {
18188
- return seatStateDir(orgStateDir(o.stateDir ?? join20(configDir(o.home, o.env ?? process.env), "engine"), org), seat);
18640
+ return seatStateDir(orgStateDir(o.stateDir ?? join21(configDir(o.home, o.env ?? process.env), "engine"), org), seat);
18189
18641
  }
18190
18642
  function engineSeat2(o, org) {
18191
18643
  try {
@@ -18212,11 +18664,11 @@ function engineDeps2(o, flags, source, runner, stateName) {
18212
18664
  const stateDir = engineStateDir2(o, flags.org, flags.seat);
18213
18665
  const file = statePath(stateDir, stateName);
18214
18666
  const mcpOrg = flags.org && engineOrg2(o, flags.org).seated ? flags.org : undefined;
18215
- const repo = flags.repo ? resolve9(cwd, flags.repo) : undefined;
18216
- const reposDirs = splitReposDirs(flags.reposDir).map((d) => resolve9(cwd, d));
18667
+ const repo = flags.repo ? resolve10(cwd, flags.repo) : undefined;
18668
+ const reposDirs = splitReposDirs(flags.reposDir).map((d) => resolve10(cwd, d));
18217
18669
  const { branch, prTitle } = flags;
18218
- const hooksDir = join20(stateDir, "hooks");
18219
- const permissionMark = (name) => join20(hooksDir, `${name}.permission.json`);
18670
+ const hooksDir = join21(stateDir, "hooks");
18671
+ const permissionMark = (name) => join21(hooksDir, `${name}.permission.json`);
18220
18672
  const withHook = (name, settings) => applyPermissionHook(settings, [...o.sledsArgv ?? ["sleds"], "permission-event", "--mark", permissionMark(name)].map(shq2).join(" "));
18221
18673
  return {
18222
18674
  source,
@@ -18241,9 +18693,9 @@ function engineDeps2(o, flags, source, runner, stateName) {
18241
18693
  sandbox: true,
18242
18694
  writeSandboxSettings: o.writeSandboxSettings ?? ((name, cwd) => {
18243
18695
  const gitCommonDir = gitCommonDirOf2(exec, cwd);
18244
- const dir = join20(stateDir, "sandbox");
18696
+ const dir = join21(stateDir, "sandbox");
18245
18697
  mkdirSync16(dir, { recursive: true, mode: 448 });
18246
- const p = join20(dir, `${name}.json`);
18698
+ const p = join21(dir, `${name}.json`);
18247
18699
  const walls = engineSandboxSettings2(o.home, o.env ?? process.env, gitCommonDir, [
18248
18700
  ...SANDBOX_DEFAULT_ALLOW,
18249
18701
  ...flags.sandboxAllow ?? []
@@ -18257,7 +18709,7 @@ function engineDeps2(o, flags, source, runner, stateName) {
18257
18709
  } : {},
18258
18710
  writeHookSettings: (name) => {
18259
18711
  mkdirSync16(hooksDir, { recursive: true, mode: 448 });
18260
- const p = join20(hooksDir, `${name}.json`);
18712
+ const p = join21(hooksDir, `${name}.json`);
18261
18713
  writeFileSync18(p, `${JSON.stringify(withHook(name, {}), null, 2)}
18262
18714
  `, { mode: 384 });
18263
18715
  chmodSync5(p, 384);
@@ -18284,9 +18736,9 @@ function engineDeps2(o, flags, source, runner, stateName) {
18284
18736
  exists
18285
18737
  }),
18286
18738
  writeMcpConfig: o.writeMcpConfig ?? ((name, runToken, worktree) => {
18287
- const dir = join20(stateDir, "mcp");
18739
+ const dir = join21(stateDir, "mcp");
18288
18740
  mkdirSync16(dir, { recursive: true, mode: 448 });
18289
- const p = join20(dir, `${name}.json`);
18741
+ const p = join21(dir, `${name}.json`);
18290
18742
  let others = {};
18291
18743
  if (flags.strictMcp && flags.mcpAllow?.length) {
18292
18744
  const r = mcpPassThrough(flags.mcpAllow, memberMcpConfigs2(o, worktree));
@@ -18302,9 +18754,9 @@ function engineDeps2(o, flags, source, runner, stateName) {
18302
18754
  }),
18303
18755
  removeMcpConfig: o.removeMcpConfig ?? ((p) => rmSync9(p, { force: true })),
18304
18756
  writePrompt: o.writePrompt ?? ((name, text) => {
18305
- const dir = join20(stateDir, "prompts");
18757
+ const dir = join21(stateDir, "prompts");
18306
18758
  mkdirSync16(dir, { recursive: true, mode: 448 });
18307
- const p = join20(dir, `${name}.md`);
18759
+ const p = join21(dir, `${name}.md`);
18308
18760
  writeFileSync18(p, text, { mode: 384 });
18309
18761
  return p;
18310
18762
  }),
@@ -18331,8 +18783,8 @@ function engineDeps2(o, flags, source, runner, stateName) {
18331
18783
  }
18332
18784
  function sandboxDenyRead2(home, env) {
18333
18785
  return {
18334
- dirs: [...new Set([configDir(home, env), join20(home, ".config", "sleds")])],
18335
- files: [...new Set([tokenPath(home, env), join20(home, ".sleds-token")])]
18786
+ dirs: [...new Set([configDir(home, env), join21(home, ".config", "sleds")])],
18787
+ files: [...new Set([tokenPath(home, env), join21(home, ".sleds-token")])]
18336
18788
  };
18337
18789
  }
18338
18790
  function engineSandboxSettings2(home, env, gitCommonDir, allow) {
@@ -18347,7 +18799,7 @@ function gitCommonDirOf2(exec, cwd) {
18347
18799
  const dir = r.status === 0 ? r.stdout.trim() : "";
18348
18800
  if (!dir)
18349
18801
  throw new Error(`git has no common dir for ${cwd}, so the sandbox has nowhere to commit`);
18350
- return resolve9(cwd, dir);
18802
+ return resolve10(cwd, dir);
18351
18803
  }
18352
18804
  function sandboxRefusal(flags) {
18353
18805
  if (!flags.sandbox)
@@ -18398,13 +18850,14 @@ async function driveEngine2(o, flags, deps, until = {}) {
18398
18850
  runner: deps.runner.name,
18399
18851
  atOnce: flags.atOnce,
18400
18852
  interval: flags.interval,
18401
- cliVersion: "0.1.42"
18853
+ cliVersion: "0.1.44"
18402
18854
  };
18403
18855
  const beat = (checkedAt) => {
18404
18856
  const m = deps.machine;
18405
18857
  try {
18406
18858
  writeLock(lockFile, checkedAt === undefined ? lock : {
18407
18859
  ...lock,
18860
+ runner: deps.runner.name,
18408
18861
  atOnce: deps.atOnce,
18409
18862
  checkedAt,
18410
18863
  nextCheckAt: checkedAt + flags.interval * 1000,
@@ -18677,7 +19130,7 @@ var engineCmd = async (o) => {
18677
19130
  armedOnly: true,
18678
19131
  engine: `engine:${flags.name}`,
18679
19132
  ...parsed.given.includes("at-once") ? { atOnce: flags.atOnce } : {},
18680
- runner: runner.name,
19133
+ runner: () => deps.runner.name,
18681
19134
  leaseMin: flags.lease,
18682
19135
  log
18683
19136
  });
@@ -18695,6 +19148,21 @@ var engineCmd = async (o) => {
18695
19148
  const started = flags;
18696
19149
  deps.rereadRoles = (read) => rereadRoles(read, started, parsed.given);
18697
19150
  deps.rereadAtOnce = (read) => rereadAtOnce2(read, started, parsed.given);
19151
+ let current = { runner, cmd: flags.runner === "command" ? flags.runnerCmd : undefined };
19152
+ deps.rereadRunner = async (read) => {
19153
+ const next = await rereadRunner2(read, started, parsed.given, o.home);
19154
+ if (!next)
19155
+ return null;
19156
+ if ("refused" in next)
19157
+ return next.refused;
19158
+ if (next.runner === current.runner.name && next.runnerCmd === current.cmd)
19159
+ return current.runner;
19160
+ const made = engineRunner2(o, { ...started, ...next });
19161
+ if (!made)
19162
+ return `runner ${next.runner} not taken — this CLI cannot start it`;
19163
+ current = { runner: made, cmd: next.runnerCmd };
19164
+ return made;
19165
+ };
18698
19166
  }
18699
19167
  log(engineHeader2(terminalOf2(o).c, deps.engine, (source.name === "jira" ? `Jira epic ${flags.jira}` : pickup === "auto" ? "your sled, Pickup: Auto (it arms the next ready item)" : "the routes armed on your sled") + (flags.org ? ` · org ${flags.org}` : "") + (flags.seat ? ` · as ${flags.seat}` : ""), runner.name, flags));
18700
19168
  if (flags.strictMcp && flags.agent)
@@ -18704,15 +19172,21 @@ var engineCmd = async (o) => {
18704
19172
  let afterTick;
18705
19173
  if (client) {
18706
19174
  const send = beater(client, o.now ?? Date.now);
18707
- const who = { name: flags.name, runner: runner.name };
19175
+ let refused;
19176
+ const sayRefused = (r) => {
19177
+ if (!r || r.ok || !r.refused || r.refused === refused)
19178
+ return;
19179
+ refused = r.refused;
19180
+ error(`${r.refused}. This engine is not shown as up until it beats under a name of its own.`);
19181
+ };
18708
19182
  afterTick = () => {
18709
19183
  try {
18710
19184
  const m = deps.machine;
18711
- send(beatBody(deps.readState(), who, {}, {
19185
+ send(beatBody(deps.readState(), { name: flags.name, runner: deps.runner.name }, {}, {
18712
19186
  atOnce: deps.atOnce,
18713
19187
  ...m?.last ? { machine: m.last } : {},
18714
19188
  ...m?.hold && !m.off ? { hold: m.hold } : {}
18715
- }));
19189
+ }))?.then(sayRefused, () => {});
18716
19190
  } catch {}
18717
19191
  };
18718
19192
  }
@@ -18840,18 +19314,18 @@ async function enginePauseCmd2(o) {
18840
19314
 
18841
19315
  // src/commands/engineInstall.ts
18842
19316
  init_config();
18843
- init_state();
18844
19317
  import {
18845
- existsSync as existsSync17,
19318
+ existsSync as existsSync18,
18846
19319
  mkdirSync as mkdirSync17,
18847
- readFileSync as readFileSync18,
19320
+ readFileSync as readFileSync19,
18848
19321
  readdirSync as readdirSync4,
18849
19322
  realpathSync as realpathSync2,
18850
19323
  rmSync as rmSync10,
18851
19324
  writeFileSync as writeFileSync19
18852
19325
  } from "node:fs";
18853
19326
  import { hostname as hostname5 } from "node:os";
18854
- import { basename as basename5, dirname as dirname13, isAbsolute as isAbsolute3, join as join21 } from "node:path";
19327
+ import { basename as basename5, dirname as dirname13, isAbsolute as isAbsolute3, join as join22 } from "node:path";
19328
+ init_state();
18855
19329
  var ENGINE_LABEL2 = "ai.sleds.engine";
18856
19330
  var ENGINE_INSTALL_USAGE2 = `usage: sleds engine install [engine flags] | sleds engine uninstall [--name <n>] [--org <slug>]
18857
19331
  ${ENGINE_USAGE}`;
@@ -18870,13 +19344,13 @@ function engineLabel2(name, org, seat) {
18870
19344
  return [ENGINE_LABEL2, org, seat?.trim(), name].filter((p) => Boolean(p)).map((p, i) => i === 0 ? p : engineSlug(p)).join(".");
18871
19345
  }
18872
19346
  function enginePlistPath2(home, name, org, seat) {
18873
- return join21(home, "Library", "LaunchAgents", `${engineLabel2(name, org, seat)}.plist`);
19347
+ return join22(home, "Library", "LaunchAgents", `${engineLabel2(name, org, seat)}.plist`);
18874
19348
  }
18875
19349
  function engineLogPath2(stateDir, name) {
18876
- return join21(stateDir, `${engineSlug(name)}.log`);
19350
+ return join22(stateDir, `${engineSlug(name)}.log`);
18877
19351
  }
18878
19352
  function engineEventsPath2(stateDir, name) {
18879
- return join21(stateDir, `${engineSlug(name)}.events.jsonl`);
19353
+ return join22(stateDir, `${engineSlug(name)}.events.jsonl`);
18880
19354
  }
18881
19355
  var xmlEscape4 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
18882
19356
  function buildEnginePlist2(o) {
@@ -18952,7 +19426,13 @@ function parseEnginePlist2(text) {
18952
19426
  if (!label || array === undefined)
18953
19427
  return null;
18954
19428
  const programArgs = [...array.matchAll(/<string>([^<]*)<\/string>/g)].map((m) => xmlUnescape2(m[1] ?? ""));
18955
- return { label: xmlUnescape2(label), programArgs };
19429
+ const envDict = /<key>EnvironmentVariables<\/key>\s*<dict>([\s\S]*?)<\/dict>/.exec(text)?.[1];
19430
+ const path = envDict && /<key>PATH<\/key>\s*<string>([^<]*)<\/string>/.exec(envDict)?.[1];
19431
+ return {
19432
+ label: xmlUnescape2(label),
19433
+ programArgs,
19434
+ ...typeof path === "string" ? { path: xmlUnescape2(path) } : {}
19435
+ };
18956
19436
  }
18957
19437
  function engineArg2(programArgs, flag) {
18958
19438
  const at = programArgs.indexOf(`--${flag}`);
@@ -18967,10 +19447,10 @@ function readEngines2(dir, suffix, manager, parse) {
18967
19447
  }
18968
19448
  const out = [];
18969
19449
  for (const name of names.filter((n) => n.startsWith(`${ENGINE_LABEL2}.`) && n.endsWith(suffix))) {
18970
- const path = join21(dir, name);
19450
+ const path = join22(dir, name);
18971
19451
  let parsed;
18972
19452
  try {
18973
- parsed = parse(readFileSync18(path, "utf8"), name);
19453
+ parsed = parse(readFileSync19(path, "utf8"), name);
18974
19454
  } catch {
18975
19455
  parsed = null;
18976
19456
  }
@@ -18987,7 +19467,7 @@ function readEngines2(dir, suffix, manager, parse) {
18987
19467
  }
18988
19468
  function installedEngines2(home) {
18989
19469
  return [
18990
- ...readEngines2(join21(home, "Library", "LaunchAgents"), ".plist", "launchd", parseEnginePlist2),
19470
+ ...readEngines2(join22(home, "Library", "LaunchAgents"), ".plist", "launchd", parseEnginePlist2),
18991
19471
  ...readEngines2(engineUnitDir(home), ".service", "systemd", (text, file) => {
18992
19472
  const parsed = parseEngineUnit(text);
18993
19473
  return parsed && { label: basename5(file, ".service"), ...parsed };
@@ -18995,6 +19475,50 @@ function installedEngines2(home) {
18995
19475
  ];
18996
19476
  }
18997
19477
  var unsupported2 = (platform) => `sleds engine install needs launchd (macOS) or systemd (Linux). On ${platform}, keep \`sleds engine\` running under your own service manager (a scheduled task, tmux).`;
19478
+ var REPOS_DIR_NEEDED = "Set the folder your repos are cloned in first: `sleds engine profile set reposDir=~/code` (Settings › Running work › Repos folders), or `sleds engine install --repos-dir ~/code`. An installed engine starts outside any checkout, so without one every node it takes parks on No repo.";
19479
+ async function ensureReposDir(o) {
19480
+ const log = o.log ?? console.log;
19481
+ const error = o.error ?? console.error;
19482
+ const parsed = parseEngineArgs(o.argv, o.host ?? hostname5());
19483
+ if ("error" in parsed)
19484
+ return true;
19485
+ if (parsed.given.includes("repos-dir") || parsed.given.includes("repo"))
19486
+ return true;
19487
+ const client = engineClient({ home: o.home, ...o.env ? { env: o.env } : {}, ...o.client ? { client: o.client } : {} }, parsed.flags.org);
19488
+ if ("error" in client)
19489
+ return true;
19490
+ const profile = await readProfile(client);
19491
+ if (!profile) {
19492
+ log("note: your engine profile could not be read — if it names no repos folder, the engine says so when it starts");
19493
+ return true;
19494
+ }
19495
+ if (profile.reposDir)
19496
+ return true;
19497
+ if (!o.ask) {
19498
+ error(REPOS_DIR_NEEDED);
19499
+ return false;
19500
+ }
19501
+ const answer = (await o.ask("Where are your repos cloned? Folders searched in order, split on : (~/code): ")).trim();
19502
+ const dirs = splitReposDirs(answer);
19503
+ if (dirs.length === 0) {
19504
+ error(REPOS_DIR_NEEDED);
19505
+ return false;
19506
+ }
19507
+ const exists = o.exists ?? existsSync18;
19508
+ const missing = dirs.filter((d) => !exists(/^~(\/|$)/.test(d) ? join22(o.home, d.slice(1)) : d));
19509
+ if (missing.length) {
19510
+ error(`Not a folder on this machine: ${missing.join(", ")}. ${REPOS_DIR_NEEDED}`);
19511
+ return false;
19512
+ }
19513
+ const r = await client.postFull("/proxy/engine/profile", { profile: { reposDir: dirs.join(":") } }).catch(() => null);
19514
+ if (!r || r.status >= 300 || r.json?.ok === false) {
19515
+ const why = typeof r?.json?.error === "string" ? r.json.error : "SLEDS unreachable";
19516
+ error(`The repos folder was not saved (${why}). ${REPOS_DIR_NEEDED}`);
19517
+ return false;
19518
+ }
19519
+ log(`repos folders saved to your engine profile: ${dirs.join(" → ")}`);
19520
+ return true;
19521
+ }
18998
19522
  function engineInstall2(o) {
18999
19523
  const log = o.log ?? console.log;
19000
19524
  const error = o.error ?? console.error;
@@ -19038,7 +19562,7 @@ function engineInstall2(o) {
19038
19562
  return installUnit2({ o, parsed, label, sledsArgv, env: agentEnv, logPath, exec });
19039
19563
  const plist = enginePlistPath2(o.home, parsed.name, parsed.org, seat);
19040
19564
  mkdirSync17(dirname13(plist), { recursive: true });
19041
- if (existsSync17(plist))
19565
+ if (existsSync18(plist))
19042
19566
  exec("launchctl", ["unload", plist]);
19043
19567
  for (const other of installedEngines2(o.home)) {
19044
19568
  if (other.manager !== "launchd" || other.plist === plist || other.org !== parsed.org)
@@ -19050,7 +19574,7 @@ function engineInstall2(o) {
19050
19574
  log(`replaced ${other.label}, this engine as installed before`);
19051
19575
  }
19052
19576
  const legacy = enginePlistPath2(o.home, parsed.name);
19053
- if (parsed.org && existsSync17(legacy)) {
19577
+ if (parsed.org && existsSync18(legacy)) {
19054
19578
  const cfg = readConfig(o.home);
19055
19579
  if (org.sole || parsed.org === (cfg.activeOrg ?? cfg.org?.slug)) {
19056
19580
  exec("launchctl", ["unload", legacy]);
@@ -19080,7 +19604,7 @@ function installUnit2(a) {
19080
19604
  const unitName = basename5(unit);
19081
19605
  const systemctl = (...args) => exec("systemctl", ["--user", ...args]);
19082
19606
  mkdirSync17(dirname13(unit), { recursive: true });
19083
- if (existsSync17(unit))
19607
+ if (existsSync18(unit))
19084
19608
  systemctl("stop", unitName);
19085
19609
  for (const other of installedEngines2(o.home)) {
19086
19610
  if (other.manager !== "systemd" || other.plist === unit || other.org !== parsed.org)
@@ -19138,7 +19662,7 @@ function engineUninstall2(o) {
19138
19662
  ...installed.filter((e) => e.manager === manager).map((e) => e.plist),
19139
19663
  ...args.org ? [] : [pathOf(manager)]
19140
19664
  ]);
19141
- const file = candidates.find((p) => existsSync17(p));
19665
+ const file = candidates.find((p) => existsSync18(p));
19142
19666
  if (!file) {
19143
19667
  log(`engine:${name} was not installed (no ${candidates[0]}).`);
19144
19668
  return 0;
@@ -19169,13 +19693,13 @@ function ago(at, now) {
19169
19693
 
19170
19694
  // src/commands/engineList.ts
19171
19695
  var ENGINE_LIST_USAGE = "usage: sleds engine list [--json]";
19172
- var str11 = (x) => typeof x === "string" ? x : "";
19696
+ var str12 = (x) => typeof x === "string" ? x : "";
19173
19697
  var numOrNull = (x) => typeof x === "number" && Number.isFinite(x) ? x : null;
19174
19698
  function machineOf(x) {
19175
19699
  if (!x || typeof x !== "object")
19176
19700
  return null;
19177
19701
  const m = x;
19178
- const out = { pressure: str11(m.pressure) || "unknown" };
19702
+ const out = { pressure: str12(m.pressure) || "unknown" };
19179
19703
  for (const k of ["cpuPct", "load1", "cores", "loadPerCore"]) {
19180
19704
  const n = numOrNull(m[k]);
19181
19705
  if (n !== null)
@@ -19191,8 +19715,8 @@ function workOf(x) {
19191
19715
  if (!w || typeof w !== "object")
19192
19716
  return [];
19193
19717
  const o = w;
19194
- const item = str11(o.item);
19195
- return item ? [{ item, node: str11(o.node), title: typeof o.title === "string" ? o.title : null }] : [];
19718
+ const item = str12(o.item);
19719
+ return item ? [{ item, node: str12(o.node), title: typeof o.title === "string" ? o.title : null }] : [];
19196
19720
  });
19197
19721
  }
19198
19722
  function engineRows(raw) {
@@ -19201,16 +19725,16 @@ function engineRows(raw) {
19201
19725
  if (!r || typeof r !== "object")
19202
19726
  return [];
19203
19727
  const e = r;
19204
- const name = str11(e.name);
19728
+ const name = str12(e.name);
19205
19729
  if (!name)
19206
19730
  return [];
19207
19731
  return [
19208
19732
  {
19209
19733
  name,
19210
- email: str11(e.email),
19211
- os: str11(e.os),
19212
- runner: str11(e.runner),
19213
- version: str11(e.version),
19734
+ email: str12(e.email),
19735
+ os: str12(e.os),
19736
+ runner: str12(e.runner),
19737
+ version: str12(e.version),
19214
19738
  running: typeof e.running === "number" ? e.running : 0,
19215
19739
  items: Array.isArray(e.items) ? e.items.filter((i) => typeof i === "string") : [],
19216
19740
  seatKind: typeof e.seatKind === "string" ? e.seatKind : null,
@@ -19263,7 +19787,7 @@ var engineListCmd = async (o) => {
19263
19787
  return 1;
19264
19788
  }
19265
19789
  if (r.status !== 200 || !r.json || r.json.ok === false) {
19266
- error(str11(r.json?.error) || `HTTP ${r.status}`);
19790
+ error(str12(r.json?.error) || `HTTP ${r.status}`);
19267
19791
  return 1;
19268
19792
  }
19269
19793
  const rows = engineRows(r.json);
@@ -19280,7 +19804,7 @@ import { closeSync as closeSync3, fstatSync as fstatSync2, openSync as openSync3
19280
19804
  import { hostname as hostname6 } from "node:os";
19281
19805
 
19282
19806
  // src/commands/engineStatus.ts
19283
- import { existsSync as existsSync18, readFileSync as readFileSync19 } from "node:fs";
19807
+ import { existsSync as existsSync19, readFileSync as readFileSync20 } from "node:fs";
19284
19808
  init_state();
19285
19809
 
19286
19810
  // src/engine/status.ts
@@ -19463,7 +19987,7 @@ function statusDir(o, engine, org) {
19463
19987
  const env = o.env ?? process.env;
19464
19988
  const which = engineOrg({ home: o.home, env }, org);
19465
19989
  const slug = which.seated || org ? which.slug : null;
19466
- const has = (d) => existsSync18(statePath(d, engine)) || existsSync18(lockPath(d, engine));
19990
+ const has = (d) => existsSync19(statePath(d, engine)) || existsSync19(lockPath(d, engine));
19467
19991
  const seat = engineSeat({ home: o.home, env }, slug ?? undefined);
19468
19992
  const dir = engineStateDir({ ...o, env }, slug);
19469
19993
  const seatDir = engineStateDir({ ...o, env }, slug, seat);
@@ -19570,7 +20094,7 @@ var engineLogCmd = (o) => {
19570
20094
 
19571
20095
  // src/commands/engineProfile.ts
19572
20096
  init_src();
19573
- import { existsSync as existsSync19, readFileSync as readFileSync20 } from "node:fs";
20097
+ import { existsSync as existsSync20, readFileSync as readFileSync21 } from "node:fs";
19574
20098
  import { hostname as hostname7 } from "node:os";
19575
20099
  var PROFILE_USAGE = "usage: sleds engine profile [--json] | sleds engine profile set <field>=<value>… [--workspace] [--json] | sleds engine profile set --stdin [--workspace] [--json] | sleds engine profile --strict-mcp [--mcp-allow <a,b>] | --no-strict-mcp [--workspace] [--json] | sleds engine profile --sandbox [--sandbox-allow <a,b>] | --no-sandbox [--workspace] [--json] | sleds engine profile set --hold on|off [--workspace] [--json] | sleds engine profile set cmuxPassword=<pw> | --cmux-password <pw> [--json]";
19576
20100
  var PROFILE_FIELDS = [
@@ -19798,7 +20322,7 @@ function localOf(o) {
19798
20322
  return {
19799
20323
  engine: `engine:${name}`,
19800
20324
  canInstall,
19801
- installed: canInstall && existsSync19(enginePlistPath(o.home, name))
20325
+ installed: canInstall && existsSync20(enginePlistPath(o.home, name))
19802
20326
  };
19803
20327
  }
19804
20328
  async function engineProfileCmd(o) {
@@ -19835,7 +20359,7 @@ async function engineProfileCmd(o) {
19835
20359
  const rest = words.slice(1);
19836
20360
  let stdin = null;
19837
20361
  if (fromStdin) {
19838
- const taken = cmuxPasswordFromJson((o.stdin ?? (() => readFileSync20(0, "utf8")))());
20362
+ const taken = cmuxPasswordFromJson((o.stdin ?? (() => readFileSync21(0, "utf8")))());
19839
20363
  if ("error" in taken || taken.password !== undefined && password !== undefined) {
19840
20364
  error("error" in taken ? taken.error : "the cmux password is given once");
19841
20365
  error(PROFILE_USAGE);
@@ -19920,7 +20444,7 @@ var keychainLine = (k) => k === "set" ? "cmuxPassword: set (Keychain)" : k === "
19920
20444
 
19921
20445
  // src/commands/engineStatus.ts
19922
20446
  init_state();
19923
- import { existsSync as existsSync20, readFileSync as readFileSync21 } from "node:fs";
20447
+ import { existsSync as existsSync21, readFileSync as readFileSync22 } from "node:fs";
19924
20448
  import { hostname as hostname8 } from "node:os";
19925
20449
  var ENGINE_STATUS_USAGE = "usage: sleds engine status [--name <n>] [--org <slug>] [--json]";
19926
20450
  function parseStatusArgs(argv, host) {
@@ -19949,7 +20473,7 @@ function statusDir2(o, engine, org) {
19949
20473
  const env = o.env ?? process.env;
19950
20474
  const which = engineOrg({ home: o.home, env }, org);
19951
20475
  const slug = which.seated || org ? which.slug : null;
19952
- const has = (d) => existsSync20(statePath(d, engine)) || existsSync20(lockPath(d, engine));
20476
+ const has = (d) => existsSync21(statePath(d, engine)) || existsSync21(lockPath(d, engine));
19953
20477
  const seat = engineSeat({ home: o.home, env }, slug ?? undefined);
19954
20478
  const dir = engineStateDir({ ...o, env }, slug);
19955
20479
  const seatDir = engineStateDir({ ...o, env }, slug, seat);
@@ -19962,7 +20486,7 @@ function statusDir2(o, engine, org) {
19962
20486
  }
19963
20487
  function readEngineStatus(stateDir, engine, host, pidAlive, seat) {
19964
20488
  const file = statePath(stateDir, engine);
19965
- const text = existsSync20(file) ? safeRead(file) : "";
20489
+ const text = existsSync21(file) ? safeRead(file) : "";
19966
20490
  return engineStatus({
19967
20491
  engine,
19968
20492
  state: text ? parseState(text) : { runs: [] },
@@ -19976,7 +20500,7 @@ function readEngineStatus(stateDir, engine, host, pidAlive, seat) {
19976
20500
  }
19977
20501
  function safeRead(path) {
19978
20502
  try {
19979
- return readFileSync21(path, "utf8");
20503
+ return readFileSync22(path, "utf8");
19980
20504
  } catch {
19981
20505
  return "";
19982
20506
  }
@@ -20097,28 +20621,28 @@ init_meter();
20097
20621
 
20098
20622
  // src/owed.ts
20099
20623
  init_config();
20100
- import { existsSync as existsSync21, mkdirSync as mkdirSync18, readFileSync as readFileSync22, renameSync as renameSync7, writeFileSync as writeFileSync20 } from "node:fs";
20101
- import { dirname as dirname14, join as join22 } from "node:path";
20102
- var owedPath = (home) => join22(configDir(home), "owed.json");
20103
- var sessionPath = (home) => join22(configDir(home), "session.json");
20624
+ import { existsSync as existsSync22, mkdirSync as mkdirSync18, readFileSync as readFileSync23, renameSync as renameSync7, writeFileSync as writeFileSync20 } from "node:fs";
20625
+ import { dirname as dirname14, join as join23 } from "node:path";
20626
+ var owedPath = (home) => join23(configDir(home), "owed.json");
20627
+ var sessionPath = (home) => join23(configDir(home), "session.json");
20104
20628
  var OWED_TTL_MS = 3 * 24 * 60 * 60000;
20105
- var str12 = (v) => typeof v === "string" ? v : undefined;
20629
+ var str13 = (v) => typeof v === "string" ? v : undefined;
20106
20630
  function sourceKey(s) {
20107
20631
  const trim = (x) => x.trim().slice(0, 120);
20108
- const kind = str12(s.kind) ?? "manual";
20109
- const project = trim(str12(s.project) ?? "");
20110
- const doc = str12(s.doc);
20111
- const item = str12(s.item);
20632
+ const kind = str13(s.kind) ?? "manual";
20633
+ const project = trim(str13(s.project) ?? "");
20634
+ const doc = str13(s.doc);
20635
+ const item = str13(s.item);
20112
20636
  return `${kind}:${project}${doc ? `/${trim(doc)}` : ""}${item ? `#${trim(item)}` : ""}`;
20113
20637
  }
20114
20638
  function sourceText2(s) {
20115
- return [`${str12(s.kind) ?? "?"} ${str12(s.project) ?? "?"}`, str12(s.doc), str12(s.item)].filter(Boolean).join(" › ");
20639
+ return [`${str13(s.kind) ?? "?"} ${str13(s.project) ?? "?"}`, str13(s.doc), str13(s.item)].filter(Boolean).join(" › ");
20116
20640
  }
20117
20641
  var readJson = (p) => {
20118
- if (!existsSync21(p))
20642
+ if (!existsSync22(p))
20119
20643
  return null;
20120
20644
  try {
20121
- return JSON.parse(readFileSync22(p, "utf8"));
20645
+ return JSON.parse(readFileSync23(p, "utf8"));
20122
20646
  } catch {
20123
20647
  return null;
20124
20648
  }
@@ -21145,7 +21669,7 @@ var login = async (o) => {
21145
21669
  // src/commands/logout.ts
21146
21670
  init_config();
21147
21671
  init_state();
21148
- import { existsSync as existsSync22, readFileSync as readFileSync23, rmSync as rmSync11 } from "node:fs";
21672
+ import { existsSync as existsSync23, readFileSync as readFileSync24, rmSync as rmSync11 } from "node:fs";
21149
21673
  import { hostname as hostname10 } from "node:os";
21150
21674
  init_settings();
21151
21675
  var LOGOUT_USAGE = "usage: sleds logout [--org <slug>] [--json]";
@@ -21302,7 +21826,7 @@ async function logout(o) {
21302
21826
  };
21303
21827
  writeConfig(o.home, next);
21304
21828
  const tp = tokenPath(o.home, env);
21305
- if (existsSync22(tp) && readFileSync23(tp, "utf8").trim() === seat.token)
21829
+ if (existsSync23(tp) && readFileSync24(tp, "utf8").trim() === seat.token)
21306
21830
  rmSync11(tp, { force: true });
21307
21831
  const active = next.activeOrg ?? next.org?.slug ?? null;
21308
21832
  const result = { ok: true, email, org: slug, paused, active };
@@ -21380,20 +21904,20 @@ var meter = async (o) => {
21380
21904
  init_config();
21381
21905
  init_meter();
21382
21906
  import { spawnSync as spawnSync7 } from "node:child_process";
21383
- import { existsSync as existsSync23, mkdirSync as mkdirSync20, readFileSync as readFileSync24, rmSync as rmSync12, writeFileSync as writeFileSync22 } from "node:fs";
21907
+ import { existsSync as existsSync24, mkdirSync as mkdirSync20, readFileSync as readFileSync25, rmSync as rmSync12, writeFileSync as writeFileSync22 } from "node:fs";
21384
21908
  import { hostname as hostname11 } from "node:os";
21385
21909
  import { dirname as dirname15 } from "node:path";
21386
21910
  var defaultWhich3 = (cmd) => {
21387
21911
  const path = process.env.PATH ?? "";
21388
21912
  for (const dir of path.split(":").filter(Boolean)) {
21389
21913
  const p = `${dir}/${cmd}`;
21390
- if (existsSync23(p))
21914
+ if (existsSync24(p))
21391
21915
  return p;
21392
21916
  }
21393
21917
  return null;
21394
21918
  };
21395
21919
  var findClaude2 = (home, configured, which) => {
21396
- if (configured && existsSync23(configured))
21920
+ if (configured && existsSync24(configured))
21397
21921
  return configured;
21398
21922
  const found = which("claude");
21399
21923
  if (found)
@@ -21404,7 +21928,7 @@ var findClaude2 = (home, configured, which) => {
21404
21928
  "/usr/local/bin/claude",
21405
21929
  `${home}/.npm-global/bin/claude`
21406
21930
  ])
21407
- if (existsSync23(p))
21931
+ if (existsSync24(p))
21408
21932
  return p;
21409
21933
  return null;
21410
21934
  };
@@ -21430,7 +21954,7 @@ var musherInstall = (o) => {
21430
21954
  ...env.CLAUDE_CONFIG_DIR ? { CLAUDE_CONFIG_DIR: env.CLAUDE_CONFIG_DIR } : {}
21431
21955
  };
21432
21956
  const exec = o.exec ?? defaultExecSync;
21433
- if (existsSync23(plist))
21957
+ if (existsSync24(plist))
21434
21958
  exec("launchctl", ["unload", plist]);
21435
21959
  writeFileSync22(plist, buildMusherPlist({ sledsArgv: o.sledsArgv, env: agentEnv, logPath: musherLogPath(dir), label }));
21436
21960
  const r = exec("launchctl", ["load", plist]);
@@ -21451,7 +21975,7 @@ var musherUninstall = (o) => {
21451
21975
  const env = o.env ?? process.env;
21452
21976
  const plist = musherPlistPath(o.home, env);
21453
21977
  const exec = o.exec ?? defaultExecSync;
21454
- if (existsSync23(plist)) {
21978
+ if (existsSync24(plist)) {
21455
21979
  exec("launchctl", ["unload", plist]);
21456
21980
  rmSync12(plist, { force: true });
21457
21981
  log(`musher removed: ${musherLabel(env)}`);
@@ -21486,7 +22010,7 @@ var musherStatus = async (o) => {
21486
22010
  const env = o.env ?? process.env;
21487
22011
  const plist = musherPlistPath(o.home, env);
21488
22012
  const cfg = readConfig(o.home);
21489
- log(existsSync23(plist) ? `agent ${musherLabel(env)} installed (${plist})` : "agent not installed — sleds musher --install");
22013
+ log(existsSync24(plist) ? `agent ${musherLabel(env)} installed (${plist})` : "agent not installed — sleds musher --install");
21490
22014
  const claude = findClaude2(o.home, cfg.musher?.claudePath, o.which ?? defaultWhich3);
21491
22015
  log(`claude ${claude ?? "not found — sleds musher --claude /path/to/claude"}`);
21492
22016
  log(`mode ${cfg.musher?.permissionMode ?? DEFAULT_PERMISSION_MODE} · timeout ${cfg.musher?.timeoutMinutes ?? DEFAULT_TIMEOUT_MINUTES} min`);
@@ -21716,7 +22240,7 @@ var on = (o) => {
21716
22240
  init_config();
21717
22241
  init_meter();
21718
22242
  init_settings();
21719
- import { existsSync as existsSync24, rmSync as rmSync13 } from "node:fs";
22243
+ import { existsSync as existsSync25, rmSync as rmSync13 } from "node:fs";
21720
22244
  var ORG_USAGE = "usage: sleds org list [--json] | sleds org use <slug>";
21721
22245
  var orgRows = (cfg, activeSlug) => {
21722
22246
  const seats = { ...cfg.orgs ?? {} };
@@ -21783,7 +22307,7 @@ var orgUse = (o) => {
21783
22307
  }
21784
22308
  writeConfig(o.home, withActiveOrg(cfg, slug, seat));
21785
22309
  writeTokenFile(o.home, seat.token);
21786
- if (existsSync24(settingsPath(o.home)) && cfg.mode !== "on") {
22310
+ if (existsSync25(settingsPath(o.home)) && cfg.mode !== "on") {
21787
22311
  const settings = readSettings(o.home);
21788
22312
  const pointed = readProxy(settings);
21789
22313
  const url = pointed?.url ?? cfg.proxyUrl;
@@ -21820,7 +22344,7 @@ var orgCmd = (o) => {
21820
22344
  init_src();
21821
22345
  import { spawnSync as spawnSync8 } from "node:child_process";
21822
22346
  import { writeFileSync as writeFileSync23 } from "node:fs";
21823
- import { join as join23 } from "node:path";
22347
+ import { join as join24 } from "node:path";
21824
22348
  function packFileName(key) {
21825
22349
  return `pack-${slugify(key, 80) || "item"}.md`;
21826
22350
  }
@@ -21848,7 +22372,7 @@ var packCmd = async (o) => {
21848
22372
  log(r.text);
21849
22373
  return 0;
21850
22374
  }
21851
- const path = join23(o.cwd ?? process.cwd(), packFileName(key));
22375
+ const path = join24(o.cwd ?? process.cwd(), packFileName(key));
21852
22376
  (o.write ?? ((p, t) => writeFileSync23(p, t.endsWith(`
21853
22377
  `) ? t : `${t}
21854
22378
  `)))(path, r.text);
@@ -21857,7 +22381,7 @@ var packCmd = async (o) => {
21857
22381
  };
21858
22382
 
21859
22383
  // src/commands/permissionEvent.ts
21860
- import { chmodSync as chmodSync6, mkdirSync as mkdirSync21, readFileSync as readFileSync25, renameSync as renameSync8, rmSync as rmSync14, writeFileSync as writeFileSync24 } from "node:fs";
22384
+ import { chmodSync as chmodSync6, mkdirSync as mkdirSync21, readFileSync as readFileSync26, renameSync as renameSync8, rmSync as rmSync14, writeFileSync as writeFileSync24 } from "node:fs";
21861
22385
  import { dirname as dirname16 } from "node:path";
21862
22386
  var isObject13 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
21863
22387
  var messageOf = (text) => {
@@ -21868,12 +22392,20 @@ var messageOf = (text) => {
21868
22392
  return "";
21869
22393
  }
21870
22394
  };
22395
+ var NOT_A_TOOL2 = new Set(["askuserquestion", "exitplanmode", "enterplanmode"]);
22396
+ var isToolPermission2 = (message) => {
22397
+ const tool = /permission to use\s+(.+?)\.?\s*$/i.exec(message)?.[1];
22398
+ return !tool || !NOT_A_TOOL2.has(tool.replace(/[\s_-]/g, "").toLowerCase());
22399
+ };
21871
22400
  var permissionEvent = async (o) => {
21872
22401
  try {
21873
22402
  const input = o.stdin ?? await readStdin(HOOK_STDIN_TIMEOUT_MS);
21874
22403
  if (!o.mark || notificationType(input) !== "permission_prompt")
21875
22404
  return 0;
21876
- const mark = { message: messageOf(input), at: (o.now ?? Date.now)() };
22405
+ const message = messageOf(input);
22406
+ if (!isToolPermission2(message))
22407
+ return 0;
22408
+ const mark = { message, at: (o.now ?? Date.now)() };
21877
22409
  mkdirSync21(dirname16(o.mark), { recursive: true, mode: 448 });
21878
22410
  const tmp = `${o.mark}.${process.pid}.tmp`;
21879
22411
  writeFileSync24(tmp, `${JSON.stringify(mark)}
@@ -21968,7 +22500,7 @@ var promptEvent = async (o) => {
21968
22500
 
21969
22501
  // src/commands/route.ts
21970
22502
  init_src();
21971
- import { readFileSync as readFileSync26 } from "node:fs";
22503
+ import { readFileSync as readFileSync27 } from "node:fs";
21972
22504
  import { hostname as hostname12 } from "node:os";
21973
22505
  var ARM_USAGE = "usage: sleds route arm <key> [--off] [--json] [--name <engine>] [--at-once <n>] [--runner tmux|headless|command|orca|cmux] [--runner-cmd '<launcher>'] [--agent '<command>'] [--mode <permission-mode>] [--model <id>] [--effort <e>] [--branch '<template>'] [--pr-title '<template>'] [--repos-dir <dir>]";
21974
22506
  var USAGE = "usage: sleds route <key> [--long | --dot | --json] | sleds route arm <key> [--off] [--json] | sleds route answer <key>/<node> --stdin | sleds route propose <key> --file <nodes.json> | sleds route approve <key> | sleds route redraft <key> | sleds route single <key> | sleds route decisions [<key>] [--flagged] | sleds route decision <key> <id> --seen | --answer --stdin [--route accept|keep|redraft] | --keep-route | --apply [--answer --stdin] | --overrule --stdin | --ready | sleds route run <key> [--at-once <n>] [--runner tmux|headless|command|orca|cmux] [--runner-cmd '<launcher>'] [--agent '<command>'] [--interval <s>] [--lease <min>] [--idle <min>] [--repo <path>] [--repos-dir <dir>] [--mode <permission-mode>] [--model <id>] [--branch '<template>'] [--pr-title '<template>'] [--once]";
@@ -22141,7 +22673,7 @@ async function answerCmd(o, argv) {
22141
22673
  const words = argv.filter((a) => a !== "--json" && a !== "--stdin");
22142
22674
  const ref = words[0] ?? "";
22143
22675
  const slash = ref.lastIndexOf("/");
22144
- const answer = (fromStdin ? (o.stdin ?? (() => readFileSync26(0, "utf8")))() : words.slice(1).join(" ")).trim();
22676
+ const answer = (fromStdin ? (o.stdin ?? (() => readFileSync27(0, "utf8")))() : words.slice(1).join(" ")).trim();
22145
22677
  if (slash <= 0 || slash === ref.length - 1 || fromStdin && words.length > 1) {
22146
22678
  error(ANSWER_USAGE);
22147
22679
  return 2;
@@ -22338,7 +22870,7 @@ async function decisionCmd(o, argv) {
22338
22870
  error(DECISION_USAGE);
22339
22871
  return 2;
22340
22872
  }
22341
- const md = seen || routeAlone ? "" : (fromStdin ? (o.stdin ?? (() => readFileSync26(0, "utf8")))() : rest.join(" ")).trim();
22873
+ const md = seen || routeAlone ? "" : (fromStdin ? (o.stdin ?? (() => readFileSync27(0, "utf8")))() : rest.join(" ")).trim();
22342
22874
  if (!seen && !routeAlone && (!md || fromStdin && rest.length > 0)) {
22343
22875
  error(md ? DECISION_USAGE : `${answer ? "an answer" : "an overrule"} needs some text`);
22344
22876
  return 2;
@@ -22479,7 +23011,7 @@ function approvedLine(key, j) {
22479
23011
  function readNodes(o, a) {
22480
23012
  let text;
22481
23013
  try {
22482
- text = a.file ? (o.readFile ?? ((p) => readFileSync26(p, "utf8")))(a.file) : (o.stdin ?? (() => readFileSync26(0, "utf8")))();
23014
+ text = a.file ? (o.readFile ?? ((p) => readFileSync27(p, "utf8")))(a.file) : (o.stdin ?? (() => readFileSync27(0, "utf8")))();
22483
23015
  } catch (e) {
22484
23016
  return { error: e instanceof Error ? e.message : String(e) };
22485
23017
  }
@@ -22790,14 +23322,14 @@ var seatEvent = async (o) => {
22790
23322
 
22791
23323
  // src/commands/seatSync.ts
22792
23324
  import { execFileSync as execFileSync4 } from "node:child_process";
22793
- import { existsSync as existsSync25, mkdirSync as mkdirSync22, readFileSync as readFileSync27, readdirSync as readdirSync5, rmSync as rmSync16, writeFileSync as writeFileSync25 } from "node:fs";
23325
+ import { existsSync as existsSync26, mkdirSync as mkdirSync22, readFileSync as readFileSync28, readdirSync as readdirSync5, rmSync as rmSync16, writeFileSync as writeFileSync25 } from "node:fs";
22794
23326
  import { platform as platform2 } from "node:os";
22795
- import { dirname as dirname17, join as join25 } from "node:path";
23327
+ import { dirname as dirname17, join as join26 } from "node:path";
22796
23328
 
22797
23329
  // src/cookieDb.ts
22798
23330
  import { copyFileSync, rmSync as rmSync15 } from "node:fs";
22799
23331
  import { tmpdir as tmpdir2 } from "node:os";
22800
- import { join as join24 } from "node:path";
23332
+ import { join as join25 } from "node:path";
22801
23333
  var QUERY = "SELECT name, hex(encrypted_value) AS ev FROM cookies WHERE host_key LIKE '%claude.ai%'";
22802
23334
  var isBun = () => typeof globalThis.Bun !== "undefined";
22803
23335
  async function queryRows(dbPath) {
@@ -22826,7 +23358,7 @@ function nodeSqlite() {
22826
23358
  return mod;
22827
23359
  }
22828
23360
  async function readCookieRows(dbPath) {
22829
- const copy = join24(tmpdir2(), `sleds-cookies-${process.pid}-${Date.now()}.sqlite`);
23361
+ const copy = join25(tmpdir2(), `sleds-cookies-${process.pid}-${Date.now()}.sqlite`);
22830
23362
  copyFileSync(dbPath, copy);
22831
23363
  try {
22832
23364
  const rows = await queryRows(copy);
@@ -23110,7 +23642,7 @@ function findFile(root, name) {
23110
23642
  const stack = [root];
23111
23643
  while (stack.length > 0) {
23112
23644
  const dir = stack.pop();
23113
- if (!dir || !existsSync25(dir))
23645
+ if (!dir || !existsSync26(dir))
23114
23646
  continue;
23115
23647
  let entries;
23116
23648
  try {
@@ -23119,7 +23651,7 @@ function findFile(root, name) {
23119
23651
  continue;
23120
23652
  }
23121
23653
  for (const e of entries) {
23122
- const p = join25(dir, e.name);
23654
+ const p = join26(dir, e.name);
23123
23655
  if (e.isDirectory())
23124
23656
  stack.push(p);
23125
23657
  else if (e.name === name)
@@ -23130,8 +23662,8 @@ function findFile(root, name) {
23130
23662
  }
23131
23663
  function findCookieDb(home, source) {
23132
23664
  const b = BROWSERS[source.browser];
23133
- const root = join25(home, APP_SUPPORT, b.appDir);
23134
- if (!existsSync25(root))
23665
+ const root = join26(home, APP_SUPPORT, b.appDir);
23666
+ if (!existsSync26(root))
23135
23667
  throw new Error(`no ${source.browser} data at ${root} (is it installed?)`);
23136
23668
  if (!b.profiled) {
23137
23669
  const db = findFile(root, "Cookies");
@@ -23139,15 +23671,15 @@ function findCookieDb(home, source) {
23139
23671
  throw new Error(`no cookie store under ${root}`);
23140
23672
  return db;
23141
23673
  }
23142
- const localStatePath = join25(root, "Local State");
23143
- const localState = existsSync25(localStatePath) ? readFileSync27(localStatePath, "utf8") : null;
23674
+ const localStatePath = join26(root, "Local State");
23675
+ const localState = existsSync26(localStatePath) ? readFileSync28(localStatePath, "utf8") : null;
23144
23676
  const wanted = source.profile ?? "Default";
23145
23677
  const { dir, ambiguous } = resolveProfileDir(localState, wanted);
23146
23678
  if (ambiguous)
23147
23679
  throw new Error(`"${wanted}" names ${ambiguous.length} ${source.browser} profiles (${ambiguous.join(", ")}) — pass the directory or the account email instead`);
23148
23680
  if (!dir)
23149
23681
  throw new Error(`no ${source.browser} profile named "${wanted}" (check chrome://version)`);
23150
- const db = cookieDbCandidates(join25(root, dir)).find((p) => existsSync25(p));
23682
+ const db = cookieDbCandidates(join26(root, dir)).find((p) => existsSync26(p));
23151
23683
  if (!db)
23152
23684
  throw new Error(`profile "${dir}" has no cookie store yet (open claude.ai in it once)`);
23153
23685
  return db;
@@ -23191,7 +23723,7 @@ function fetchSeatUsage(jar, org, now, run) {
23191
23723
  }
23192
23724
  function launchAgentPlist(bun, script, home, source) {
23193
23725
  const label = launchLabel(source);
23194
- const log = join25(home, ".config", "sleds", `${label.slice("ai.sleds.".length)}.log`);
23726
+ const log = join26(home, ".config", "sleds", `${label.slice("ai.sleds.".length)}.log`);
23195
23727
  const esc = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
23196
23728
  const args = [bun, script, "seat-sync", ...sourceArgs(source)].map((a) => ` <string>${esc(a)}</string>`).join(`
23197
23729
  `);
@@ -23213,7 +23745,7 @@ ${args}
23213
23745
  `;
23214
23746
  }
23215
23747
  function plistPath2(home, source) {
23216
- return join25(home, "Library", "LaunchAgents", `${launchLabel(source)}.plist`);
23748
+ return join26(home, "Library", "LaunchAgents", `${launchLabel(source)}.plist`);
23217
23749
  }
23218
23750
  function install(home, argv, source, log) {
23219
23751
  const bun = argv[0] ?? process.execPath;
@@ -23222,7 +23754,7 @@ function install(home, argv, source, log) {
23222
23754
  log("cannot resolve the sleds script path to install the timer");
23223
23755
  return 1;
23224
23756
  }
23225
- const dir = join25(home, "Library", "LaunchAgents");
23757
+ const dir = join26(home, "Library", "LaunchAgents");
23226
23758
  mkdirSync22(dir, { recursive: true });
23227
23759
  const path = plistPath2(home, source);
23228
23760
  const tokenPath = seatTokenPath(home, source);
@@ -23246,7 +23778,7 @@ function uninstall(home, source, log) {
23246
23778
  execFileSync4("launchctl", ["unload", "-w", path], { stdio: "ignore" });
23247
23779
  } catch {}
23248
23780
  rmSync16(seatTokenPath(home, source), { force: true });
23249
- log(existsSync25(path) ? `seat-sync timer removed (${path} can be deleted)` : "no seat-sync timer");
23781
+ log(existsSync26(path) ? `seat-sync timer removed (${path} can be deleted)` : "no seat-sync timer");
23250
23782
  return 0;
23251
23783
  }
23252
23784
  var seatSync = async (o) => {
@@ -23320,7 +23852,7 @@ var seatSync = async (o) => {
23320
23852
  };
23321
23853
  function readSeatToken(home, source) {
23322
23854
  try {
23323
- return readFileSync27(seatTokenPath(home, source), "utf8").trim() || undefined;
23855
+ return readFileSync28(seatTokenPath(home, source), "utf8").trim() || undefined;
23324
23856
  } catch {
23325
23857
  return;
23326
23858
  }
@@ -23403,7 +23935,7 @@ var sessionEvent = async (o) => {
23403
23935
 
23404
23936
  // src/commands/specEvent.ts
23405
23937
  init_meter();
23406
- import { readFileSync as readFileSync28, statSync as statSync2 } from "node:fs";
23938
+ import { readFileSync as readFileSync29, statSync as statSync2 } from "node:fs";
23407
23939
  import { basename as basename6, isAbsolute as isAbsolute4, relative } from "node:path";
23408
23940
  var HOOK_STDIN_TIMEOUT_MS3 = 1000;
23409
23941
  var ESTIMATE_TIMEOUT_MS = 4000;
@@ -23459,7 +23991,7 @@ function readFileOrNull(path) {
23459
23991
  try {
23460
23992
  if (statSync2(path).size > 2000000)
23461
23993
  return null;
23462
- return readFileSync28(path, "utf8");
23994
+ return readFileSync29(path, "utf8");
23463
23995
  } catch {
23464
23996
  return null;
23465
23997
  }
@@ -23518,9 +24050,9 @@ var specEvent = async (o) => {
23518
24050
  };
23519
24051
 
23520
24052
  // src/commands/status.ts
24053
+ import { existsSync as existsSync27 } from "node:fs";
23521
24054
  init_config();
23522
24055
  init_settings();
23523
- import { existsSync as existsSync26 } from "node:fs";
23524
24056
  var HEALTH_TIMEOUT_MS2 = 4000;
23525
24057
  var checkHealth2 = async (url, fetchFn = fetch, timeoutMs = HEALTH_TIMEOUT_MS2) => {
23526
24058
  try {
@@ -23550,6 +24082,13 @@ var fetchProxyStatus = async (url, fetchFn = fetch, timeoutMs = HEALTH_TIMEOUT_M
23550
24082
  }
23551
24083
  };
23552
24084
  var row2 = (label, value) => `${label.padEnd(12)}${value}`;
24085
+ var claudeLine = (c, seatEmail) => {
24086
+ if (!c)
24087
+ return "no Claude login found (signed out, or on an API key)";
24088
+ const org = c.orgName && (c.plan === "Team" || c.plan === "Enterprise") ? ` (${c.orgName})` : "";
24089
+ const other = seatEmail && seatEmail.toLowerCase() !== c.email.toLowerCase() ? " — not the seat's account" : "";
24090
+ return `${c.email}${c.plan ? ` · ${c.plan}` : ""}${org}${other}`;
24091
+ };
23553
24092
  var formatStatus = (s) => {
23554
24093
  const lines = [];
23555
24094
  const stale = s.mode === "on" && !s.pointed;
@@ -23582,6 +24121,8 @@ var formatStatus = (s) => {
23582
24121
  lines.push(row2("Seat:", `${s.email}${s.agentKind ? ` · ${s.agentKind}` : ""}`));
23583
24122
  else if (s.agentKind)
23584
24123
  lines.push(row2("Agent:", s.agentKind));
24124
+ if (s.claude !== undefined)
24125
+ lines.push(row2("Claude:", claudeLine(s.claude, s.email)));
23585
24126
  if (s.org)
23586
24127
  lines.push(row2("Org:", `${s.org.name}${s.org.slug ? ` (${s.org.slug})` : ""} · ${s.org.plan} · ${s.org.upstream === "none" ? "no platform key (walls: hold or hand off)" : s.org.upstream === "own" ? "platform key" : "shared key"}${s.orgFrom === "env" ? " · from SLEDS_ORG" : ""}`));
23587
24128
  if (s.otherOrgs)
@@ -23597,7 +24138,7 @@ var status3 = async (o) => {
23597
24138
  const log = o.log ?? console.log;
23598
24139
  const nowMs = (o.now ?? Date.now)();
23599
24140
  const cfg = readConfig(o.home);
23600
- const settings = existsSync26(settingsPath(o.home)) ? readSettings(o.home) : {};
24141
+ const settings = existsSync27(settingsPath(o.home)) ? readSettings(o.home) : {};
23601
24142
  const inSettings = readProxy(settings);
23602
24143
  const picked = selectOrg(cfg, undefined, o.env ?? process.env);
23603
24144
  const viaEnv = picked.from === "env";
@@ -23627,6 +24168,8 @@ var status3 = async (o) => {
23627
24168
  info.agentKind = cfg.agentKind;
23628
24169
  if (cfg.wiring)
23629
24170
  info.wiring = cfg.wiring;
24171
+ if (cfg.agentKind !== "codex")
24172
+ info.claude = readClaudeAccount(o.home, o.env ?? process.env);
23630
24173
  if (org)
23631
24174
  info.org = {
23632
24175
  name: org.name,
@@ -23748,7 +24291,7 @@ var rememberSeat = (o, key, window, session, now, input) => {
23748
24291
  const posts = [];
23749
24292
  if (src && shouldPostSeat(prior, window, now)) {
23750
24293
  state = markPosted(state, window, now);
23751
- posts.push(postSeatWindow({ ...src, fetchFn: o.fetchFn, timeoutMs: o.timeoutMs ?? SEAT_POST_TIMEOUT_MS }, window));
24294
+ posts.push(postSeatWindow({ ...src, fetchFn: o.fetchFn, timeoutMs: o.timeoutMs ?? SEAT_POST_TIMEOUT_MS }, window, readClaudeAccount(o.home, o.env ?? process.env)));
23752
24295
  }
23753
24296
  const events = seatWallEvents(prior, window);
23754
24297
  const credits = creditsEvent(o, prior, input, now);
@@ -23788,7 +24331,7 @@ var announce = (o, events) => {
23788
24331
 
23789
24332
  // src/commands/stopEvent.ts
23790
24333
  init_meter();
23791
- import { existsSync as existsSync27, readFileSync as readFileSync29 } from "node:fs";
24334
+ import { existsSync as existsSync28, readFileSync as readFileSync30 } from "node:fs";
23792
24335
 
23793
24336
  // src/transcript.ts
23794
24337
  var isObject16 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
@@ -23884,7 +24427,7 @@ async function postTranscript(o, payload, now) {
23884
24427
  const src = meterSource(o.home);
23885
24428
  if (!src)
23886
24429
  return false;
23887
- const read = o.readFile ?? ((p) => existsSync27(p) ? readFileSync29(p, "utf8") : null);
24430
+ const read = o.readFile ?? ((p) => existsSync28(p) ? readFileSync30(p, "utf8") : null);
23888
24431
  let text;
23889
24432
  try {
23890
24433
  text = read(path);
@@ -23962,7 +24505,7 @@ var stopEvent = async (o) => {
23962
24505
 
23963
24506
  // src/commands/uninstall.ts
23964
24507
  import { spawnSync as spawnSync9 } from "node:child_process";
23965
- import { existsSync as existsSync28, rmSync as rmSync17 } from "node:fs";
24508
+ import { existsSync as existsSync29, rmSync as rmSync17 } from "node:fs";
23966
24509
  init_config();
23967
24510
  init_meter();
23968
24511
  init_settings();
@@ -23975,7 +24518,7 @@ var uninstall2 = (o) => {
23975
24518
  (o.log ?? console.log)(` ${codexLine}`);
23976
24519
  const log = o.log ?? console.log;
23977
24520
  const removed = [];
23978
- if (existsSync28(settingsPath(o.home))) {
24521
+ if (existsSync29(settingsPath(o.home))) {
23979
24522
  let settings = readSettings(o.home);
23980
24523
  let changed = false;
23981
24524
  if (hasEitherKey(settings)) {
@@ -24022,18 +24565,18 @@ var uninstall2 = (o) => {
24022
24565
  writeSettings(o.home, settings);
24023
24566
  }
24024
24567
  for (const file of [meterCachePath(o.home), ...allSeatStatePaths(o.home)]) {
24025
- if (existsSync28(file)) {
24568
+ if (existsSync29(file)) {
24026
24569
  rmSync17(file, { force: true });
24027
24570
  removed.push(file);
24028
24571
  }
24029
24572
  }
24030
24573
  const skill = skillDir(o.home);
24031
- if (existsSync28(skill)) {
24574
+ if (existsSync29(skill)) {
24032
24575
  rmSync17(skill, { recursive: true, force: true });
24033
24576
  removed.push(skill);
24034
24577
  }
24035
24578
  const plist = musherPlistPath(o.home);
24036
- if (existsSync28(plist)) {
24579
+ if (existsSync29(plist)) {
24037
24580
  (o.unloadAgent ?? defaultUnload)(plist);
24038
24581
  rmSync17(plist, { force: true });
24039
24582
  removed.push(`launchd agent ${musherLabel()}`);
@@ -24105,7 +24648,7 @@ var verify = async (o) => {
24105
24648
 
24106
24649
  // src/commands/webhooks.ts
24107
24650
  var USAGE2 = "usage: sleds webhooks [--json] | sleds webhooks deliveries <id or name> [--json]";
24108
- var str13 = (x) => typeof x === "string" ? x : "";
24651
+ var str14 = (x) => typeof x === "string" ? x : "";
24109
24652
  function ago3(at, now) {
24110
24653
  const m = Math.max(0, Math.floor((now - at) / 60000));
24111
24654
  if (m < 1)
@@ -24121,7 +24664,7 @@ function webhookLines(raw, now) {
24121
24664
  if (!rows.length)
24122
24665
  return ["no webhooks — add one in the app: Settings › Integrations › Webhooks"];
24123
24666
  return rows.map((h) => {
24124
- let host = str13(h.url);
24667
+ let host = str14(h.url);
24125
24668
  try {
24126
24669
  host = new URL(host.replace(/\{[a-z.]+\}/g, "x")).host;
24127
24670
  } catch {}
@@ -24129,21 +24672,21 @@ function webhookLines(raw, now) {
24129
24672
  const last = h.lastDelivery;
24130
24673
  const lastText = last?.at ? `last ${last.status ?? "—"} ${last.state ?? ""} ${ago3(last.at, now)}`.replace(/\s+/g, " ") : "nothing sent yet";
24131
24674
  const off = h.enabled ? "on " : "off";
24132
- const why = !h.enabled && h.disabledWhy ? ` (${str13(h.disabledWhy)})` : "";
24133
- return `${off} ${str13(h.name)} ${host} ${events.includes("*") ? "all events" : events.join(",")} ${lastText}${why} [${str13(h.id)}]`;
24675
+ const why = !h.enabled && h.disabledWhy ? ` (${str14(h.disabledWhy)})` : "";
24676
+ return `${off} ${str14(h.name)} ${host} ${events.includes("*") ? "all events" : events.join(",")} ${lastText}${why} [${str14(h.id)}]`;
24134
24677
  });
24135
24678
  }
24136
24679
  function deliveryLines(raw, now) {
24137
24680
  const j = clean(raw);
24138
24681
  const rows = Array.isArray(j.deliveries) ? j.deliveries : [];
24139
- const name = str13(j.webhook?.name);
24682
+ const name = str14(j.webhook?.name);
24140
24683
  if (!rows.length)
24141
24684
  return [`${name}: nothing sent yet`];
24142
24685
  return [
24143
24686
  `${name} — the last ${rows.length}`,
24144
24687
  ...rows.map((d) => {
24145
- const result = d.status !== null && d.status !== undefined ? String(d.status) : str13(d.error) || "—";
24146
- return `${str13(d.state).padEnd(9)} ${result.padEnd(5)} ${str13(d.event).padEnd(20)} ${str13(d.key) || "—"} ${ago3(Number(d.at), now)} tries ${d.attempts} ${str13(d.deliveryId)}`;
24688
+ const result = d.status !== null && d.status !== undefined ? String(d.status) : str14(d.error) || "—";
24689
+ return `${str14(d.state).padEnd(9)} ${result.padEnd(5)} ${str14(d.event).padEnd(20)} ${str14(d.key) || "—"} ${ago3(Number(d.at), now)} tries ${d.attempts} ${str14(d.deliveryId)}`;
24147
24690
  })
24148
24691
  ];
24149
24692
  }
@@ -24174,7 +24717,7 @@ var webhooksCmd = async (o) => {
24174
24717
  return 1;
24175
24718
  }
24176
24719
  if (r.status !== 200 || !r.json) {
24177
- const why = str13(r.json?.error) || `HTTP ${r.status}`;
24720
+ const why = str14(r.json?.error) || `HTTP ${r.status}`;
24178
24721
  error(r.status === 404 && !r.json ? "SLEDS does not know this seat — run `sleds init`" : why);
24179
24722
  return 1;
24180
24723
  }
@@ -24188,13 +24731,13 @@ var webhooksCmd = async (o) => {
24188
24731
 
24189
24732
  // src/config.ts
24190
24733
  init_settings();
24191
- import { chmodSync as chmodSync7, existsSync as existsSync29, mkdirSync as mkdirSync23, readFileSync as readFileSync30, renameSync as renameSync9, writeFileSync as writeFileSync26 } from "node:fs";
24192
- import { join as join26, resolve as resolve10 } from "node:path";
24734
+ import { chmodSync as chmodSync7, existsSync as existsSync30, mkdirSync as mkdirSync23, readFileSync as readFileSync31, renameSync as renameSync9, writeFileSync as writeFileSync26 } from "node:fs";
24735
+ import { join as join27, resolve as resolve11 } from "node:path";
24193
24736
  var configDir2 = (home, env = process.env) => {
24194
24737
  const o = env.SLEDS_HOME?.trim();
24195
- return o ? resolve10(home, o) : join26(home, ".config", "sleds");
24738
+ return o ? resolve11(home, o) : join27(home, ".config", "sleds");
24196
24739
  };
24197
- var configPath2 = (home) => join26(configDir2(home), "config.json");
24740
+ var configPath2 = (home) => join27(configDir2(home), "config.json");
24198
24741
  var isObject17 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
24199
24742
  var optString2 = (v) => typeof v === "string" ? v : undefined;
24200
24743
  var parsePriorEnv2 = (v) => {
@@ -24326,9 +24869,9 @@ var parseOrgInfo2 = (raw) => {
24326
24869
  };
24327
24870
  var readConfig2 = (home) => {
24328
24871
  const p = configPath2(home);
24329
- if (!existsSync29(p))
24872
+ if (!existsSync30(p))
24330
24873
  return {};
24331
- return parseConfig2(JSON.parse(readFileSync30(p, "utf8")));
24874
+ return parseConfig2(JSON.parse(readFileSync31(p, "utf8")));
24332
24875
  };
24333
24876
 
24334
24877
  // src/runners/exec.ts
@@ -24380,15 +24923,15 @@ var defaultExec5 = (cmd, args) => {
24380
24923
  };
24381
24924
 
24382
24925
  // src/settings.ts
24383
- import { dirname as dirname18, join as join27, resolve as resolve11 } from "node:path";
24926
+ import { dirname as dirname18, join as join28, resolve as resolve12 } from "node:path";
24384
24927
  var withSeatEnv2 = (command, home, env = process.env, org) => {
24385
24928
  const parts = [];
24386
24929
  const sh = env.SLEDS_HOME?.trim();
24387
24930
  const cc = env.CLAUDE_CONFIG_DIR?.trim();
24388
24931
  if (sh)
24389
- parts.push(`SLEDS_HOME=${shellWord2(resolve11(home, sh))}`);
24932
+ parts.push(`SLEDS_HOME=${shellWord2(resolve12(home, sh))}`);
24390
24933
  if (cc)
24391
- parts.push(`CLAUDE_CONFIG_DIR=${shellWord2(resolve11(home, cc))}`);
24934
+ parts.push(`CLAUDE_CONFIG_DIR=${shellWord2(resolve12(home, cc))}`);
24392
24935
  parts.push(command);
24393
24936
  return pinOrg4(parts.join(" "), org);
24394
24937
  };
@@ -24688,8 +25231,12 @@ var main = async (argv) => {
24688
25231
  return engineLogCmd({ home, argv: argv.slice(2) });
24689
25232
  if (cmd === "engine" && argv[1] === "list")
24690
25233
  return engineListCmd({ home, argv: argv.slice(2) });
24691
- if (cmd === "engine" && argv[1] === "install")
25234
+ if (cmd === "engine" && argv[1] === "install") {
25235
+ const ask = process.stdin.isTTY ? promptStdin : undefined;
25236
+ if (!await ensureReposDir({ home, argv: argv.slice(2), ...ask ? { ask } : {} }))
25237
+ return 1;
24692
25238
  return engineInstall2({ home, argv: argv.slice(2), sledsArgv: sledsArgv() });
25239
+ }
24693
25240
  if (cmd === "engine" && argv[1] === "uninstall")
24694
25241
  return engineUninstall2({ home, argv: argv.slice(2), sledsArgv: sledsArgv() });
24695
25242
  if (cmd === "engine" && argv[1] === "profile")
@@ -24875,7 +25422,7 @@ ${renderHelpText(argv[1])}`);
24875
25422
  case "version":
24876
25423
  case "--version":
24877
25424
  case "-v":
24878
- console.log("sleds 0.1.42");
25425
+ console.log("sleds 0.1.44");
24879
25426
  return 0;
24880
25427
  default:
24881
25428
  console.error(`unknown command: ${cmd}