@staff0rd/assist 0.362.1 → 0.364.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@staff0rd/assist",
9
- version: "0.362.1",
9
+ version: "0.364.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -254,7 +254,8 @@ var assistConfigSchema = z2.strictObject({
254
254
  tokenExpiresAt: z2.number().optional()
255
255
  }).optional(),
256
256
  prs: z2.strictObject({
257
- slack: z2.string()
257
+ slack: z2.string().optional(),
258
+ required: z2.boolean().default(false)
258
259
  }).optional(),
259
260
  run: z2.array(z2.union([runConfigSchema, runLinkSchema])).optional(),
260
261
  subtasks: z2.array(
@@ -3120,7 +3121,7 @@ ${failed2.length} script(s) failed:`);
3120
3121
  }
3121
3122
  }
3122
3123
  function runEntry(entry) {
3123
- return new Promise((resolve17) => {
3124
+ return new Promise((resolve18) => {
3124
3125
  const startTime = Date.now();
3125
3126
  const child = spawnCommand(
3126
3127
  entry.fullCommand,
@@ -3132,7 +3133,7 @@ function runEntry(entry) {
3132
3133
  child.on("close", (code) => {
3133
3134
  const exitCode = code ?? 1;
3134
3135
  flushIfFailed(exitCode, chunks);
3135
- resolve17({
3136
+ resolve18({
3136
3137
  script: entry.name,
3137
3138
  code: exitCode,
3138
3139
  durationMs: Date.now() - startTime
@@ -4266,8 +4267,8 @@ function spawnClaude(prompt, options2 = {}) {
4266
4267
  stdio: "inherit",
4267
4268
  env
4268
4269
  });
4269
- const done2 = new Promise((resolve17, reject) => {
4270
- child.on("close", (code) => resolve17(code ?? 0));
4270
+ const done2 = new Promise((resolve18, reject) => {
4271
+ child.on("close", (code) => resolve18(code ?? 0));
4271
4272
  child.on("error", reject);
4272
4273
  });
4273
4274
  return { child, done: done2 };
@@ -4329,6 +4330,89 @@ function consumePause(itemId) {
4329
4330
  return true;
4330
4331
  }
4331
4332
 
4333
+ // src/commands/branch/createBranch.ts
4334
+ import { execSync as execSync21 } from "child_process";
4335
+
4336
+ // src/commands/branch/buildBranchName.ts
4337
+ function buildBranchName({
4338
+ prefix: prefix2,
4339
+ jira,
4340
+ slug
4341
+ }) {
4342
+ const segments = [];
4343
+ if (prefix2) segments.push(`${prefix2}/`);
4344
+ if (jira) segments.push(`${jira}-`);
4345
+ segments.push(slug);
4346
+ return segments.join("");
4347
+ }
4348
+
4349
+ // src/commands/branch/resolveDefaultBranch.ts
4350
+ import { execSync as execSync20 } from "child_process";
4351
+ var REMOTE_HEAD_REGEX = /^ref:\s+refs\/heads\/(\S+)\s+HEAD$/m;
4352
+ function resolveDefaultBranch(override, cwd) {
4353
+ if (override) return override;
4354
+ try {
4355
+ const output = execSync20("git ls-remote --symref origin HEAD", {
4356
+ encoding: "utf8",
4357
+ stdio: ["pipe", "pipe", "pipe"],
4358
+ cwd
4359
+ });
4360
+ const match = output.match(REMOTE_HEAD_REGEX);
4361
+ if (match) return match[1];
4362
+ } catch {
4363
+ }
4364
+ return "main";
4365
+ }
4366
+
4367
+ // src/commands/branch/createBranch.ts
4368
+ async function createBranch({
4369
+ slug,
4370
+ jira
4371
+ }) {
4372
+ const config = loadConfig();
4373
+ const branchName = buildBranchName({
4374
+ prefix: config.branch?.prefix,
4375
+ jira,
4376
+ slug
4377
+ });
4378
+ const defaultBranch = resolveDefaultBranch(config.branch?.defaultBranch);
4379
+ execSync21("git fetch", { stdio: "inherit" });
4380
+ execSync21(
4381
+ `git switch -c ${shellQuote(branchName)} ${shellQuote(`origin/${defaultBranch}`)}`,
4382
+ { stdio: "inherit" }
4383
+ );
4384
+ await recordBranchActivity(branchName);
4385
+ return { branchName, defaultBranch };
4386
+ }
4387
+ async function recordBranchActivity(branchName) {
4388
+ if (resolveSessionItemId() === null) return;
4389
+ await recordSessionRefs([
4390
+ { kind: "branch", ref: branchName, url: gitRefUrl("branch", branchName) }
4391
+ ]);
4392
+ }
4393
+
4394
+ // src/commands/branch/deriveBranchSlug.ts
4395
+ function deriveBranchSlug(name) {
4396
+ const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
4397
+ return slug || "story";
4398
+ }
4399
+
4400
+ // src/commands/backlog/ensureStoryBranch.ts
4401
+ async function ensureStoryBranch(item) {
4402
+ const config = loadConfig();
4403
+ if (!config.prs?.required) return;
4404
+ if (hasBranchRef(item)) return;
4405
+ process.env.ASSIST_BACKLOG_ITEM_ID = String(item.id);
4406
+ const slug = deriveBranchSlug(item.name);
4407
+ const { branchName } = await createBranch({ slug, jira: item.jiraKey });
4408
+ appendDaemonLog(
4409
+ `backlog run ${item.id}: prs.required set and no branch recorded; created ${branchName}`
4410
+ );
4411
+ }
4412
+ function hasBranchRef(item) {
4413
+ return (item.gitRefs ?? []).some((ref) => ref.kind === "branch");
4414
+ }
4415
+
4332
4416
  // src/commands/backlog/shared.ts
4333
4417
  import chalk37 from "chalk";
4334
4418
 
@@ -4354,11 +4438,11 @@ function backupLocalBacklogFiles(dir) {
4354
4438
  }
4355
4439
 
4356
4440
  // src/commands/backlog/gitPullBacklog.ts
4357
- import { execSync as execSync20 } from "child_process";
4441
+ import { execSync as execSync22 } from "child_process";
4358
4442
  import chalk35 from "chalk";
4359
4443
  function gitPullBacklog(dir) {
4360
4444
  try {
4361
- execSync20("git pull --ff-only", {
4445
+ execSync22("git pull --ff-only", {
4362
4446
  cwd: dir,
4363
4447
  stdio: ["pipe", "pipe", "pipe"]
4364
4448
  });
@@ -4925,6 +5009,7 @@ async function searchItemIds(orm, query, origin) {
4925
5009
  ilike(items.name, pattern2),
4926
5010
  ilike(items.description, pattern2),
4927
5011
  ilike(items.acceptanceCriteria, pattern2),
5012
+ ilike(items.jiraKey, pattern2),
4928
5013
  ilike(comments.text, pattern2),
4929
5014
  ilike(planPhases.name, pattern2)
4930
5015
  )
@@ -5082,9 +5167,9 @@ Failed to launch Claude for ${context}: ${message}`)
5082
5167
  // src/commands/sessions/daemon/connectToDaemon.ts
5083
5168
  import * as net from "net";
5084
5169
  function connectToDaemon() {
5085
- return new Promise((resolve17, reject) => {
5170
+ return new Promise((resolve18, reject) => {
5086
5171
  const socket = net.connect(daemonPaths.socket);
5087
- socket.once("connect", () => resolve17(socket));
5172
+ socket.once("connect", () => resolve18(socket));
5088
5173
  socket.once("error", reject);
5089
5174
  });
5090
5175
  }
@@ -5531,6 +5616,7 @@ async function runOnce(item, startPhase, plan2, spawnOptions) {
5531
5616
  async function run2(id2, spawnOptions) {
5532
5617
  const prepared = await prepareRun(id2);
5533
5618
  if (!prepared) return false;
5619
+ await ensureStoryBranch(prepared.item);
5534
5620
  await setStatus(id2, "in-progress");
5535
5621
  discardStalePause(prepared.item.id);
5536
5622
  logProgress(id2, prepared);
@@ -5925,7 +6011,7 @@ import chalk59 from "chalk";
5925
6011
  import { WebSocketServer } from "ws";
5926
6012
 
5927
6013
  // src/shared/getInstallDir.ts
5928
- import { execSync as execSync21 } from "child_process";
6014
+ import { execSync as execSync23 } from "child_process";
5929
6015
  import { dirname as dirname16, resolve as resolve7 } from "path";
5930
6016
  import { fileURLToPath as fileURLToPath2 } from "url";
5931
6017
  var __filename2 = fileURLToPath2(import.meta.url);
@@ -5935,7 +6021,7 @@ function getInstallDir() {
5935
6021
  }
5936
6022
  function isGitRepo(dir) {
5937
6023
  try {
5938
- const result = execSync21("git rev-parse --show-toplevel", {
6024
+ const result = execSync23("git rev-parse --show-toplevel", {
5939
6025
  cwd: dir,
5940
6026
  stdio: "pipe"
5941
6027
  }).toString().trim();
@@ -5952,11 +6038,11 @@ import {
5952
6038
  import chalk54 from "chalk";
5953
6039
 
5954
6040
  // src/lib/openBrowser.ts
5955
- import { execSync as execSync22 } from "child_process";
6041
+ import { execSync as execSync24 } from "child_process";
5956
6042
  function tryExec(commands) {
5957
6043
  for (const cmd of commands) {
5958
6044
  try {
5959
- execSync22(cmd, { stdio: "ignore" });
6045
+ execSync24(cmd, { stdio: "ignore" });
5960
6046
  return true;
5961
6047
  } catch {
5962
6048
  }
@@ -6144,7 +6230,7 @@ function spawnDaemon(reason) {
6144
6230
  child.unref();
6145
6231
  }
6146
6232
  function delay(ms) {
6147
- return new Promise((resolve17) => setTimeout(resolve17, ms));
6233
+ return new Promise((resolve18) => setTimeout(resolve18, ms));
6148
6234
  }
6149
6235
 
6150
6236
  // src/shared/createBundleHandler.ts
@@ -6354,12 +6440,12 @@ async function loadVisibleItems(req) {
6354
6440
 
6355
6441
  // src/commands/backlog/web/parseStatusBody.ts
6356
6442
  function readBody(req) {
6357
- return new Promise((resolve17, reject) => {
6443
+ return new Promise((resolve18, reject) => {
6358
6444
  let body = "";
6359
6445
  req.on("data", (chunk) => {
6360
6446
  body += chunk.toString();
6361
6447
  });
6362
- req.on("end", () => resolve17(body));
6448
+ req.on("end", () => resolve18(body));
6363
6449
  req.on("error", reject);
6364
6450
  });
6365
6451
  }
@@ -7106,17 +7192,17 @@ async function stopDaemon() {
7106
7192
  }
7107
7193
  }
7108
7194
  function closedBeforeTimeout(socket) {
7109
- return new Promise((resolve17) => {
7195
+ return new Promise((resolve18) => {
7110
7196
  const timer = setTimeout(() => {
7111
7197
  socket.destroy();
7112
- resolve17(false);
7198
+ resolve18(false);
7113
7199
  }, STOP_TIMEOUT_MS);
7114
7200
  socket.resume();
7115
7201
  socket.on("error", () => {
7116
7202
  });
7117
7203
  socket.once("close", () => {
7118
7204
  clearTimeout(timer);
7119
- resolve17(true);
7205
+ resolve18(true);
7120
7206
  });
7121
7207
  });
7122
7208
  }
@@ -7167,8 +7253,8 @@ async function restartWeb(req, res, deps2 = {}) {
7167
7253
  respondJson(res, 400, { error: "Invalid target" });
7168
7254
  return;
7169
7255
  }
7170
- await new Promise((resolve17) => {
7171
- res.once("finish", resolve17);
7256
+ await new Promise((resolve18) => {
7257
+ res.once("finish", resolve18);
7172
7258
  respondJson(res, 200, { ok: true });
7173
7259
  });
7174
7260
  if (target === "daemon" || target === "both") {
@@ -7617,12 +7703,12 @@ import chalk61 from "chalk";
7617
7703
  import { eq as eq17 } from "drizzle-orm";
7618
7704
 
7619
7705
  // src/commands/jira/fetchIssue.ts
7620
- import { execSync as execSync23 } from "child_process";
7706
+ import { execSync as execSync25 } from "child_process";
7621
7707
  import chalk60 from "chalk";
7622
7708
  function fetchIssue(issueKey, fields) {
7623
7709
  let result;
7624
7710
  try {
7625
- result = execSync23(
7711
+ result = execSync25(
7626
7712
  `acli jira workitem view ${issueKey} -f ${fields} --json`,
7627
7713
  { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }
7628
7714
  );
@@ -8224,7 +8310,10 @@ function registerItemCommands(cmd) {
8224
8310
  "--status <type>",
8225
8311
  "Filter by status (todo, in-progress, done, wontdo)"
8226
8312
  ).option("-a, --all", "Include done/wontdo items").option("--all-repos", "List items across all repositories").option("-v, --verbose", "Show all item details").action(list2);
8227
- cmd.command("add").description("Add a new backlog item").option("--name <name>", "Item name").option("--type <type>", "Item type (story or bug)").option("--desc <description>", "Item description").option("--ac <criterion...>", "Acceptance criteria (repeatable)").action(add);
8313
+ cmd.command("add").description("Add a new backlog item").option("--name <name>", "Item name").option("--type <type>", "Item type (story or bug)").option(
8314
+ "--desc <description>",
8315
+ String.raw`Item description (Markdown supported; use \n for line breaks)`
8316
+ ).option("--ac <criterion...>", "Acceptance criteria (repeatable)").action(add);
8228
8317
  cmd.command("add-phase <id> <name>").description("Add a phase to an existing backlog item").option("--task <task...>", "Task description (repeatable)").option(
8229
8318
  "--manual-check <check...>",
8230
8319
  "Manual check description (repeatable)"
@@ -8847,7 +8936,8 @@ async function addSubtask(id2, options2) {
8847
8936
  return;
8848
8937
  }
8849
8938
  const { orm, item } = found;
8850
- await insertSubtask(orm, item.id, title, options2.desc);
8939
+ const description = options2.desc?.replaceAll(String.raw`\n`, "\n");
8940
+ await insertSubtask(orm, item.id, title, description);
8851
8941
  console.log(chalk91.green(`Added sub-task to item #${id2}: ${title}`));
8852
8942
  }
8853
8943
 
@@ -8896,7 +8986,10 @@ async function subtaskStatus(id2, index3, status2) {
8896
8986
 
8897
8987
  // src/commands/backlog/registerSubtaskCommands.ts
8898
8988
  function registerSubtaskCommands(cmd) {
8899
- cmd.command("add-subtask <id>").description("Add a sub-task to an existing backlog item").requiredOption("--title <title>", "Sub-task title").option("--desc <description>", "Sub-task description").action(addSubtask);
8989
+ cmd.command("add-subtask <id>").description("Add a sub-task to an existing backlog item").requiredOption("--title <title>", "Sub-task title").option(
8990
+ "--desc <description>",
8991
+ String.raw`Sub-task description (Markdown supported; use \n for line breaks)`
8992
+ ).action(addSubtask);
8900
8993
  cmd.command("subtask-status <id> <idx> <status>").description(
8901
8994
  "Set a sub-task's status (todo, in-progress, done) by its 1-based index"
8902
8995
  ).action(subtaskStatus);
@@ -9271,7 +9364,7 @@ function buildUpdateValues(options2) {
9271
9364
  fieldNames.push("name");
9272
9365
  }
9273
9366
  if (desc6) {
9274
- set.description = desc6;
9367
+ set.description = desc6.replaceAll(String.raw`\n`, "\n");
9275
9368
  fieldNames.push("description");
9276
9369
  }
9277
9370
  if (type) {
@@ -9319,7 +9412,10 @@ function collect2(value, previous) {
9319
9412
  return [...previous, value];
9320
9413
  }
9321
9414
  function registerUpdateCommands(cmd) {
9322
- cmd.command("update-field <id>").description("Update fields on a backlog item").option("--name <name>", "New item name").option("--desc <description>", "New description").option("--type <type>", "New type (story or bug)").option("--ac <criterion...>", "Replace acceptance criteria (repeatable)").option(
9415
+ cmd.command("update-field <id>").description("Update fields on a backlog item").option("--name <name>", "New item name").option(
9416
+ "--desc <description>",
9417
+ String.raw`New description (Markdown supported; use \n for line breaks)`
9418
+ ).option("--type <type>", "New type (story or bug)").option("--ac <criterion...>", "Replace acceptance criteria (repeatable)").option(
9323
9419
  "--add-ac <text>",
9324
9420
  "Append one acceptance criterion (repeatable)",
9325
9421
  collect2,
@@ -9371,40 +9467,6 @@ function registerBacklog(program2) {
9371
9467
  }
9372
9468
  }
9373
9469
 
9374
- // src/commands/branch/branch.ts
9375
- import { execSync as execSync25 } from "child_process";
9376
-
9377
- // src/commands/branch/buildBranchName.ts
9378
- function buildBranchName({
9379
- prefix: prefix2,
9380
- jira,
9381
- slug
9382
- }) {
9383
- const segments = [];
9384
- if (prefix2) segments.push(`${prefix2}/`);
9385
- if (jira) segments.push(`${jira}-`);
9386
- segments.push(slug);
9387
- return segments.join("");
9388
- }
9389
-
9390
- // src/commands/branch/resolveDefaultBranch.ts
9391
- import { execSync as execSync24 } from "child_process";
9392
- var REMOTE_HEAD_REGEX = /^ref:\s+refs\/heads\/(\S+)\s+HEAD$/m;
9393
- function resolveDefaultBranch(override, cwd) {
9394
- if (override) return override;
9395
- try {
9396
- const output = execSync24("git ls-remote --symref origin HEAD", {
9397
- encoding: "utf8",
9398
- stdio: ["pipe", "pipe", "pipe"],
9399
- cwd
9400
- });
9401
- const match = output.match(REMOTE_HEAD_REGEX);
9402
- if (match) return match[1];
9403
- } catch {
9404
- }
9405
- return "main";
9406
- }
9407
-
9408
9470
  // src/commands/branch/validateSlug.ts
9409
9471
  var KEBAB_CASE_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
9410
9472
  var HASH_REF_REGEX = /#\d+/;
@@ -9432,23 +9494,14 @@ async function branch(slug, options2) {
9432
9494
  console.error(`Error: ${slugError}`);
9433
9495
  process.exit(1);
9434
9496
  }
9435
- const config = loadConfig();
9436
- const branchName = buildBranchName({
9437
- prefix: config.branch?.prefix,
9438
- jira: options2.jira,
9439
- slug
9440
- });
9441
9497
  try {
9442
- const defaultBranch = resolveDefaultBranch(config.branch?.defaultBranch);
9443
- execSync25("git fetch", { stdio: "inherit" });
9444
- execSync25(
9445
- `git switch -c ${shellQuote(branchName)} ${shellQuote(`origin/${defaultBranch}`)}`,
9446
- { stdio: "inherit" }
9447
- );
9498
+ const { branchName, defaultBranch } = await createBranch({
9499
+ slug,
9500
+ jira: options2.jira
9501
+ });
9448
9502
  console.log(
9449
9503
  `Created and switched to ${branchName} (from origin/${defaultBranch})`
9450
9504
  );
9451
- await recordBranchActivity(branchName);
9452
9505
  process.exit(0);
9453
9506
  } catch (error) {
9454
9507
  console.error(
@@ -9457,12 +9510,6 @@ async function branch(slug, options2) {
9457
9510
  process.exit(1);
9458
9511
  }
9459
9512
  }
9460
- async function recordBranchActivity(branchName) {
9461
- if (resolveSessionItemId() === null) return;
9462
- await recordSessionRefs([
9463
- { kind: "branch", ref: branchName, url: gitRefUrl("branch", branchName) }
9464
- ]);
9465
- }
9466
9513
 
9467
9514
  // src/commands/registerBranch.ts
9468
9515
  function registerBranch(program2) {
@@ -10245,12 +10292,12 @@ function hasSubcommands(helpText) {
10245
10292
  // src/commands/permitCliReads/runHelp.ts
10246
10293
  import { exec as exec2 } from "child_process";
10247
10294
  function runHelp(args) {
10248
- return new Promise((resolve17) => {
10295
+ return new Promise((resolve18) => {
10249
10296
  exec2(
10250
10297
  `${args.join(" ")} --help`,
10251
10298
  { encoding: "utf8", timeout: 3e4 },
10252
10299
  (_err, stdout, stderr) => {
10253
- resolve17(stdout || stderr || "");
10300
+ resolve18(stdout || stderr || "");
10254
10301
  }
10255
10302
  );
10256
10303
  });
@@ -13889,25 +13936,25 @@ function isVisibleText(t) {
13889
13936
  return /[a-zA-Z]{3,}/.test(t);
13890
13937
  }
13891
13938
  var isHashtag = (t) => /^#[A-Za-z0-9_]+$/.test(t);
13892
- function collectRscText(v, resolve17, sink2, seen) {
13939
+ function collectRscText(v, resolve18, sink2, seen) {
13893
13940
  if (v == null) return;
13894
13941
  if (typeof v === "string") {
13895
13942
  if (isRscRef(v)) {
13896
13943
  if (!seen.has(v)) {
13897
13944
  seen.add(v);
13898
- collectRscText(resolve17(v), resolve17, sink2, seen);
13945
+ collectRscText(resolve18(v), resolve18, sink2, seen);
13899
13946
  }
13900
13947
  } else if (isHashtag(v)) sink2.hashtags.push(v);
13901
13948
  else if (isVisibleText(v)) sink2.text.push(v);
13902
13949
  return;
13903
13950
  }
13904
13951
  if (Array.isArray(v)) {
13905
- for (const x of v) collectRscText(x, resolve17, sink2, seen);
13952
+ for (const x of v) collectRscText(x, resolve18, sink2, seen);
13906
13953
  return;
13907
13954
  }
13908
13955
  if (typeof v === "object") {
13909
13956
  for (const val of Object.values(v)) {
13910
- collectRscText(val, resolve17, sink2, seen);
13957
+ collectRscText(val, resolve18, sink2, seen);
13911
13958
  }
13912
13959
  }
13913
13960
  }
@@ -13939,7 +13986,7 @@ function visitObjects(root, fn) {
13939
13986
  }
13940
13987
  }
13941
13988
  }
13942
- function buildMentionMap(rows, resolve17) {
13989
+ function buildMentionMap(rows, resolve18) {
13943
13990
  const map = /* @__PURE__ */ new Map();
13944
13991
  visitObjects(rows, (o) => {
13945
13992
  const url = profileActionUrl(o);
@@ -13947,7 +13994,7 @@ function buildMentionMap(rows, resolve17) {
13947
13994
  const slug = slugFromProfileUrl(url);
13948
13995
  if (!slug || map.has(slug)) return;
13949
13996
  const sink2 = { text: [], hashtags: [] };
13950
- collectRscText(o.children, resolve17, sink2, /* @__PURE__ */ new Set());
13997
+ collectRscText(o.children, resolve18, sink2, /* @__PURE__ */ new Set());
13951
13998
  const name = sink2.text.join(" ").replace(/\s+/g, " ").trim();
13952
13999
  map.set(slug, name ? { slug, name, url } : { slug, url });
13953
14000
  });
@@ -14033,10 +14080,10 @@ function buildPost(raw, mentionMap, author) {
14033
14080
 
14034
14081
  // src/commands/netcap/walkPostRow.ts
14035
14082
  var isCommentary = (o) => asObject(o.viewTrackingSpecs)?.viewName === "feed-commentary";
14036
- function walkPostRow(v, resolve17, raw) {
14083
+ function walkPostRow(v, resolve18, raw) {
14037
14084
  if (v == null || typeof v !== "object") return;
14038
14085
  if (Array.isArray(v)) {
14039
- for (const x of v) walkPostRow(x, resolve17, raw);
14086
+ for (const x of v) walkPostRow(x, resolve18, raw);
14040
14087
  return;
14041
14088
  }
14042
14089
  const o = v;
@@ -14050,9 +14097,9 @@ function walkPostRow(v, resolve17, raw) {
14050
14097
  }
14051
14098
  if (isCommentary(o)) {
14052
14099
  const sink2 = { text: raw.text, hashtags: raw.hashtags };
14053
- collectRscText(o.children, resolve17, sink2, /* @__PURE__ */ new Set());
14100
+ collectRscText(o.children, resolve18, sink2, /* @__PURE__ */ new Set());
14054
14101
  }
14055
- for (const val of Object.values(o)) walkPostRow(val, resolve17, raw);
14102
+ for (const val of Object.values(o)) walkPostRow(val, resolve18, raw);
14056
14103
  }
14057
14104
 
14058
14105
  // src/commands/netcap/extractLinkedInPosts.ts
@@ -14066,8 +14113,8 @@ function findCommentaryRows(rows) {
14066
14113
  }
14067
14114
  function extractLinkedInPosts(flight, author = findAuthorSlug(flight)) {
14068
14115
  const rows = parseRscRows(flight);
14069
- const resolve17 = makeRscResolver(rows);
14070
- const mentionMap = buildMentionMap(rows, resolve17);
14116
+ const resolve18 = makeRscResolver(rows);
14117
+ const mentionMap = buildMentionMap(rows, resolve18);
14071
14118
  const posts = [];
14072
14119
  for (const id2 of findCommentaryRows(rows)) {
14073
14120
  const raw = {
@@ -14077,7 +14124,7 @@ function extractLinkedInPosts(flight, author = findAuthorSlug(flight)) {
14077
14124
  links: [],
14078
14125
  related: []
14079
14126
  };
14080
- walkPostRow(rows[id2], resolve17, raw);
14127
+ walkPostRow(rows[id2], resolve18, raw);
14081
14128
  const post = buildPost(raw, mentionMap, author);
14082
14129
  if (post) posts.push(post);
14083
14130
  }
@@ -15956,7 +16003,7 @@ function getViolations(pattern2, options2 = {}, maxLines = DEFAULT_MAX_LINES) {
15956
16003
 
15957
16004
  // src/commands/refactor/check/index.ts
15958
16005
  function runScript(script, cwd) {
15959
- return new Promise((resolve17) => {
16006
+ return new Promise((resolve18) => {
15960
16007
  const child = spawn5("npm", ["run", script], {
15961
16008
  stdio: "pipe",
15962
16009
  shell: true,
@@ -15970,7 +16017,7 @@ function runScript(script, cwd) {
15970
16017
  output += data.toString();
15971
16018
  });
15972
16019
  child.on("close", (code) => {
15973
- resolve17({ script, code: code ?? 1, output });
16020
+ resolve18({ script, code: code ?? 1, output });
15974
16021
  });
15975
16022
  });
15976
16023
  }
@@ -18716,12 +18763,12 @@ function onCloseResult(ctx, code) {
18716
18763
  return { ...closed, stderr: ctx.stderr.value, stdout: ctx.stdout.value };
18717
18764
  }
18718
18765
  function waitForChildExit(ctx) {
18719
- return new Promise((resolve17) => {
18766
+ return new Promise((resolve18) => {
18720
18767
  let settled = false;
18721
18768
  const settle = (result) => {
18722
18769
  if (settled) return;
18723
18770
  settled = true;
18724
- resolve17(result);
18771
+ resolve18(result);
18725
18772
  };
18726
18773
  ctx.child.on("error", (err) => settle(onErrorResult(ctx, err)));
18727
18774
  ctx.child.on("close", (code) => settle(onCloseResult(ctx, code)));
@@ -19798,9 +19845,9 @@ function createReadlineInterface() {
19798
19845
  });
19799
19846
  }
19800
19847
  function askQuestion(rl, question) {
19801
- return new Promise((resolve17) => {
19848
+ return new Promise((resolve18) => {
19802
19849
  rl.question(question, (answer) => {
19803
- resolve17(answer.trim());
19850
+ resolve18(answer.trim());
19804
19851
  });
19805
19852
  });
19806
19853
  }
@@ -20448,7 +20495,7 @@ function extractCode(url, expectedState) {
20448
20495
  return code;
20449
20496
  }
20450
20497
  function waitForCallback(port, expectedState) {
20451
- return new Promise((resolve17, reject) => {
20498
+ return new Promise((resolve18, reject) => {
20452
20499
  const timeout = setTimeout(() => {
20453
20500
  server.close();
20454
20501
  reject(new Error("Authorization timed out after 120 seconds"));
@@ -20465,7 +20512,7 @@ function waitForCallback(port, expectedState) {
20465
20512
  const code = extractCode(url, expectedState);
20466
20513
  respondHtml(res, 200, "Authorization successful!");
20467
20514
  server.close();
20468
- resolve17(code);
20515
+ resolve18(code);
20469
20516
  } catch (error) {
20470
20517
  respondHtml(res, 400, error.message);
20471
20518
  server.close();
@@ -21214,10 +21261,10 @@ var STATUS_TIMEOUT_MS = 5e3;
21214
21261
  function queryDaemon(socket) {
21215
21262
  socket.write(`${JSON.stringify({ type: "ping" })}
21216
21263
  `);
21217
- return new Promise((resolve17) => {
21264
+ return new Promise((resolve18) => {
21218
21265
  const result = { sessions: [] };
21219
21266
  const pending = /* @__PURE__ */ new Set(["sessions", "pong"]);
21220
- const timer = setTimeout(() => resolve17(result), STATUS_TIMEOUT_MS);
21267
+ const timer = setTimeout(() => resolve18(result), STATUS_TIMEOUT_MS);
21221
21268
  const lines = createInterface5({ input: socket });
21222
21269
  lines.on("error", () => {
21223
21270
  });
@@ -21225,7 +21272,7 @@ function queryDaemon(socket) {
21225
21272
  applyLine(result, pending, line);
21226
21273
  if (pending.size === 0) {
21227
21274
  clearTimeout(timer);
21228
- resolve17(result);
21275
+ resolve18(result);
21229
21276
  }
21230
21277
  });
21231
21278
  });
@@ -21411,8 +21458,8 @@ async function drainDaemon() {
21411
21458
  function requestDrain(socket) {
21412
21459
  socket.write(`${JSON.stringify({ type: "drain" })}
21413
21460
  `);
21414
- return new Promise((resolve17) => {
21415
- const timer = setTimeout(() => resolve17(0), DRAIN_TIMEOUT_MS);
21461
+ return new Promise((resolve18) => {
21462
+ const timer = setTimeout(() => resolve18(0), DRAIN_TIMEOUT_MS);
21416
21463
  const lines = createInterface6({ input: socket });
21417
21464
  lines.on("error", () => {
21418
21465
  });
@@ -21421,7 +21468,7 @@ function requestDrain(socket) {
21421
21468
  const data = JSON.parse(line);
21422
21469
  if (data.type === "drained") {
21423
21470
  clearTimeout(timer);
21424
- resolve17(data.count ?? 0);
21471
+ resolve18(data.count ?? 0);
21425
21472
  }
21426
21473
  } catch {
21427
21474
  }
@@ -22507,7 +22554,7 @@ function windowsDaemonHost() {
22507
22554
  var CONNECT_TIMEOUT_MS = 2e3;
22508
22555
  var KEEPALIVE_PROBE_MS = 1e4;
22509
22556
  function connectToWindowsDaemon() {
22510
- return new Promise((resolve17, reject) => {
22557
+ return new Promise((resolve18, reject) => {
22511
22558
  const socket = net2.connect(windowsDaemonPort(), windowsDaemonHost());
22512
22559
  socket.setTimeout(CONNECT_TIMEOUT_MS);
22513
22560
  socket.once("timeout", () => {
@@ -22517,7 +22564,7 @@ function connectToWindowsDaemon() {
22517
22564
  socket.once("connect", () => {
22518
22565
  socket.setTimeout(0);
22519
22566
  socket.setKeepAlive(true, KEEPALIVE_PROBE_MS);
22520
- resolve17(socket);
22567
+ resolve18(socket);
22521
22568
  });
22522
22569
  socket.once("error", reject);
22523
22570
  });
@@ -22595,7 +22642,7 @@ async function waitForWindowsDaemon() {
22595
22642
  );
22596
22643
  }
22597
22644
  function delay2(ms) {
22598
- return new Promise((resolve17) => setTimeout(resolve17, ms));
22645
+ return new Promise((resolve18) => setTimeout(resolve18, ms));
22599
22646
  }
22600
22647
 
22601
22648
  // src/commands/sessions/daemon/defaultConnect.ts
@@ -22843,7 +22890,7 @@ async function healWindowsDaemon() {
22843
22890
  daemonLog("windows daemon: auto-heal: stale daemon stopped");
22844
22891
  }
22845
22892
  function runOnWindowsHost(command, timeoutMs) {
22846
- return new Promise((resolve17, reject) => {
22893
+ return new Promise((resolve18, reject) => {
22847
22894
  const child = spawn11("pwsh.exe", ["-Command", command], {
22848
22895
  stdio: ["ignore", "pipe", "pipe"]
22849
22896
  });
@@ -22863,7 +22910,7 @@ function runOnWindowsHost(command, timeoutMs) {
22863
22910
  });
22864
22911
  child.on("exit", (code) => {
22865
22912
  clearTimeout(timer);
22866
- if (code === 0) resolve17();
22913
+ if (code === 0) resolve18();
22867
22914
  else
22868
22915
  reject(
22869
22916
  new Error(
@@ -24132,6 +24179,48 @@ function buildLimitsSegment(rateLimits) {
24132
24179
  return ` | Limits - ${fiveHr}, ${sevenDay}`;
24133
24180
  }
24134
24181
 
24182
+ // src/commands/readGitBranch.ts
24183
+ import { readFileSync as readFileSync47, statSync as statSync11 } from "fs";
24184
+ import { isAbsolute as isAbsolute2, join as join63, resolve as resolve16 } from "path";
24185
+ function resolveGitDir(cwd) {
24186
+ const dotGit = join63(cwd, ".git");
24187
+ let stat2;
24188
+ try {
24189
+ stat2 = statSync11(dotGit);
24190
+ } catch {
24191
+ return null;
24192
+ }
24193
+ if (stat2.isDirectory()) {
24194
+ return dotGit;
24195
+ }
24196
+ let contents;
24197
+ try {
24198
+ contents = readFileSync47(dotGit, "utf8");
24199
+ } catch {
24200
+ return null;
24201
+ }
24202
+ const match = /^gitdir:\s*(.+)$/m.exec(contents.trim());
24203
+ if (!match) {
24204
+ return null;
24205
+ }
24206
+ const gitDir = match[1].trim();
24207
+ return isAbsolute2(gitDir) ? gitDir : resolve16(cwd, gitDir);
24208
+ }
24209
+ function readGitBranch(cwd) {
24210
+ const gitDir = resolveGitDir(cwd);
24211
+ if (!gitDir) {
24212
+ return null;
24213
+ }
24214
+ let head;
24215
+ try {
24216
+ head = readFileSync47(join63(gitDir, "HEAD"), "utf8");
24217
+ } catch {
24218
+ return null;
24219
+ }
24220
+ const match = /^ref:\s*refs\/heads\/(.+)$/m.exec(head.trim());
24221
+ return match ? match[1] : null;
24222
+ }
24223
+
24135
24224
  // src/commands/relayRateLimits.ts
24136
24225
  async function relayRateLimits(rateLimits) {
24137
24226
  if (!rateLimits) return;
@@ -24167,8 +24256,11 @@ async function statusLine() {
24167
24256
  const model = data.model.display_name;
24168
24257
  const { total_input_tokens: totalIn, total_output_tokens: totalOut } = data.context_window;
24169
24258
  const usedPct = data.context_window.used_percentage ?? 0;
24259
+ const dir = data.workspace?.current_dir ?? data.cwd;
24260
+ const branch2 = dir ? readGitBranch(windowsCwdToWslPath(dir)) : null;
24261
+ const branchSegment = branch2 ? `\u{1F343}\uFE0F ${chalk191.cyan(branch2)} | ` : "";
24170
24262
  console.log(
24171
- `${model} | Tokens - ${formatNumber(totalOut)} \u2191 : ${formatNumber(totalIn)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
24263
+ `${branchSegment}${model} | Tokens - ${formatNumber(totalOut)} \u2191 : ${formatNumber(totalIn)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
24172
24264
  );
24173
24265
  await relayRateLimits(data.rate_limits);
24174
24266
  await relayUsage(data.session_id, totalIn, totalOut);