@staff0rd/assist 0.190.0 → 0.191.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.
Files changed (2) hide show
  1. package/dist/index.js +270 -263
  2. package/package.json +1 -1
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.190.0",
9
+ version: "0.191.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -87,7 +87,7 @@ var package_default = {
87
87
  };
88
88
 
89
89
  // src/commands/backlog/next.ts
90
- import chalk8 from "chalk";
90
+ import chalk9 from "chalk";
91
91
  import enquirer2 from "enquirer";
92
92
 
93
93
  // src/shared/exitOnCancel.ts
@@ -763,7 +763,7 @@ function findUnblockedTodos(items) {
763
763
  }
764
764
 
765
765
  // src/commands/backlog/run.ts
766
- import chalk7 from "chalk";
766
+ import chalk8 from "chalk";
767
767
 
768
768
  // src/commands/backlog/buildCommentLines.ts
769
769
  function buildCommentLines(comments2) {
@@ -879,7 +879,7 @@ function buildReviewPhase() {
879
879
  }
880
880
 
881
881
  // src/commands/backlog/executePhase.ts
882
- import chalk5 from "chalk";
882
+ import chalk6 from "chalk";
883
883
 
884
884
  // src/commands/backlog/resolvePhaseResult.ts
885
885
  import { existsSync as existsSync6, unlinkSync as unlinkSync2 } from "fs";
@@ -965,8 +965,220 @@ Phase ${phaseNumber} completed.`));
965
965
 
966
966
  // src/commands/backlog/spawnClaude.ts
967
967
  import { spawn } from "child_process";
968
+
969
+ // src/shared/loadConfig.ts
970
+ import { existsSync as existsSync8, writeFileSync as writeFileSync5 } from "fs";
971
+ import { homedir } from "os";
972
+ import { dirname, join as join7 } from "path";
973
+ import chalk5 from "chalk";
974
+ import { stringify as stringifyYaml } from "yaml";
975
+
976
+ // src/shared/loadRawYaml.ts
977
+ import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
978
+ import { parse as parseYaml2 } from "yaml";
979
+ function loadRawYaml(path50) {
980
+ if (!existsSync7(path50)) return {};
981
+ try {
982
+ const content = readFileSync6(path50, "utf-8");
983
+ return parseYaml2(content) || {};
984
+ } catch {
985
+ return {};
986
+ }
987
+ }
988
+
989
+ // src/shared/types.ts
990
+ import { z as z2 } from "zod";
991
+ var runParamSchema = z2.strictObject({
992
+ name: z2.string(),
993
+ required: z2.boolean().optional(),
994
+ default: z2.string().optional(),
995
+ description: z2.string().optional()
996
+ });
997
+ var runConfigSchema = z2.strictObject({
998
+ name: z2.string(),
999
+ command: z2.string(),
1000
+ args: z2.array(z2.string()).optional(),
1001
+ params: z2.array(runParamSchema).optional(),
1002
+ env: z2.record(z2.string(), z2.string()).optional(),
1003
+ filter: z2.string().optional(),
1004
+ pre: z2.array(z2.string()).optional(),
1005
+ cwd: z2.string().optional()
1006
+ });
1007
+ var runLinkSchema = z2.strictObject({
1008
+ link: z2.string(),
1009
+ prefix: z2.string()
1010
+ });
1011
+ var transcriptConfigSchema = z2.strictObject({
1012
+ vttDir: z2.string(),
1013
+ transcriptsDir: z2.string(),
1014
+ summaryDir: z2.string()
1015
+ });
1016
+ var DEFAULT_WAKE_WORDS = ["computer"];
1017
+ var DEFAULT_MODELS_DIR = "~/.assist/voice/models";
1018
+ var assistConfigSchema = z2.strictObject({
1019
+ commit: z2.strictObject({
1020
+ conventional: z2.boolean().default(false),
1021
+ pull: z2.boolean().default(false),
1022
+ push: z2.boolean().default(false)
1023
+ }).default({ conventional: false, pull: false, push: false }),
1024
+ devlog: z2.strictObject({
1025
+ name: z2.string().optional(),
1026
+ ignore: z2.array(z2.string()).optional(),
1027
+ skip: z2.record(z2.string(), z2.array(z2.string())).optional()
1028
+ }).optional(),
1029
+ notify: z2.strictObject({
1030
+ enabled: z2.boolean().default(true)
1031
+ }).default({ enabled: true }),
1032
+ complexity: z2.strictObject({
1033
+ ignore: z2.array(z2.string()).default(["**/*test.ts*"])
1034
+ }).default({ ignore: ["**/*test.ts*"] }),
1035
+ hardcodedColors: z2.strictObject({
1036
+ ignore: z2.array(z2.string()).default([])
1037
+ }).optional(),
1038
+ restructure: z2.strictObject({
1039
+ ignore: z2.array(z2.string()).default([])
1040
+ }).optional(),
1041
+ jira: z2.strictObject({
1042
+ acField: z2.string().default("customfield_11937")
1043
+ }).optional(),
1044
+ roam: z2.strictObject({
1045
+ clientId: z2.string(),
1046
+ clientSecret: z2.string(),
1047
+ accessToken: z2.string().optional(),
1048
+ refreshToken: z2.string().optional(),
1049
+ tokenExpiresAt: z2.number().optional()
1050
+ }).optional(),
1051
+ run: z2.array(z2.union([runConfigSchema, runLinkSchema])).optional(),
1052
+ transcript: transcriptConfigSchema.optional(),
1053
+ cliReadVerbs: z2.record(z2.string(), z2.array(z2.string())).optional(),
1054
+ news: z2.strictObject({
1055
+ feeds: z2.array(z2.string()).default([])
1056
+ }).default({ feeds: [] }),
1057
+ dotnet: z2.strictObject({
1058
+ inspect: z2.strictObject({
1059
+ suppress: z2.array(z2.string()).default([])
1060
+ }).default({ suppress: [] })
1061
+ }).optional(),
1062
+ ravendb: z2.strictObject({
1063
+ connections: z2.array(
1064
+ z2.strictObject({
1065
+ name: z2.string(),
1066
+ url: z2.string(),
1067
+ database: z2.string(),
1068
+ apiKeyRef: z2.string()
1069
+ })
1070
+ ).default([]),
1071
+ defaultConnection: z2.string().optional()
1072
+ }).optional(),
1073
+ seq: z2.strictObject({
1074
+ connections: z2.array(
1075
+ z2.strictObject({
1076
+ name: z2.string(),
1077
+ url: z2.string(),
1078
+ apiToken: z2.string()
1079
+ })
1080
+ ).default([]),
1081
+ defaultConnection: z2.string().optional()
1082
+ }).optional(),
1083
+ screenshot: z2.strictObject({
1084
+ outputDir: z2.string().default("./screenshots")
1085
+ }).default({ outputDir: "./screenshots" }),
1086
+ backlog: z2.strictObject({
1087
+ autoCommit: z2.boolean().default(false)
1088
+ }).default({ autoCommit: false }),
1089
+ deny: z2.array(
1090
+ z2.strictObject({
1091
+ pattern: z2.string(),
1092
+ message: z2.string()
1093
+ })
1094
+ ).optional(),
1095
+ sync: z2.strictObject({
1096
+ autoConfirm: z2.boolean().default(false)
1097
+ }).default({ autoConfirm: false }),
1098
+ caveman: z2.boolean().default(true),
1099
+ voice: z2.strictObject({
1100
+ wakeWords: z2.array(z2.string()).default(DEFAULT_WAKE_WORDS),
1101
+ mic: z2.string().optional(),
1102
+ cwd: z2.string().optional(),
1103
+ modelsDir: z2.string().default(DEFAULT_MODELS_DIR),
1104
+ lockDir: z2.string().optional(),
1105
+ submitWindows: z2.array(z2.string()).optional(),
1106
+ models: z2.strictObject({
1107
+ vad: z2.string().optional(),
1108
+ smartTurn: z2.string().optional()
1109
+ }).default({})
1110
+ }).default({
1111
+ wakeWords: DEFAULT_WAKE_WORDS,
1112
+ modelsDir: DEFAULT_MODELS_DIR,
1113
+ models: {}
1114
+ })
1115
+ });
1116
+ function isRunLink(entry) {
1117
+ return "link" in entry;
1118
+ }
1119
+
1120
+ // src/shared/loadConfig.ts
1121
+ function findConfigUp(startDir) {
1122
+ let current = startDir;
1123
+ while (current !== dirname(current)) {
1124
+ const claudePath = join7(current, ".claude", "assist.yml");
1125
+ if (existsSync8(claudePath)) return claudePath;
1126
+ const rootPath = join7(current, "assist.yml");
1127
+ if (existsSync8(rootPath)) return rootPath;
1128
+ current = dirname(current);
1129
+ }
1130
+ return null;
1131
+ }
1132
+ function getConfigPath() {
1133
+ const found = findConfigUp(process.cwd());
1134
+ if (found) return found;
1135
+ return join7(process.cwd(), "assist.yml");
1136
+ }
1137
+ function getGlobalConfigPath() {
1138
+ return join7(homedir(), ".assist.yml");
1139
+ }
1140
+ function getConfigDir() {
1141
+ return dirname(getConfigPath());
1142
+ }
1143
+ function loadConfig() {
1144
+ const globalRaw = loadRawYaml(getGlobalConfigPath());
1145
+ const projectRaw = loadRawYaml(getConfigPath());
1146
+ const merged = { ...globalRaw, ...projectRaw };
1147
+ return assistConfigSchema.parse(merged);
1148
+ }
1149
+ function loadProjectConfig() {
1150
+ return loadRawYaml(getConfigPath());
1151
+ }
1152
+ function loadGlobalConfigRaw() {
1153
+ return loadRawYaml(getGlobalConfigPath());
1154
+ }
1155
+ function saveGlobalConfig(config) {
1156
+ writeFileSync5(getGlobalConfigPath(), stringifyYaml(config, { lineWidth: 0 }));
1157
+ }
1158
+ function saveConfig(config) {
1159
+ const configPath = getConfigPath();
1160
+ writeFileSync5(configPath, stringifyYaml(config, { lineWidth: 0 }));
1161
+ }
1162
+ function getTranscriptConfig() {
1163
+ const config = loadConfig();
1164
+ if (!config.transcript) {
1165
+ console.error(
1166
+ chalk5.red(
1167
+ "Transcript directories not configured. Run 'assist transcript configure' first."
1168
+ )
1169
+ );
1170
+ process.exit(1);
1171
+ }
1172
+ return config.transcript;
1173
+ }
1174
+
1175
+ // src/commands/backlog/spawnClaude.ts
968
1176
  function spawnClaude(prompt, options2 = {}) {
969
- const args = [prompt];
1177
+ const config = loadConfig();
1178
+ const finalPrompt = config.caveman ? `/caveman
1179
+
1180
+ ${prompt}` : prompt;
1181
+ const args = [finalPrompt];
970
1182
  if (options2.allowEdits) {
971
1183
  args.push("--permission-mode", "acceptEdits");
972
1184
  }
@@ -981,11 +1193,11 @@ function spawnClaude(prompt, options2 = {}) {
981
1193
  }
982
1194
 
983
1195
  // src/commands/backlog/watchForMarker.ts
984
- import { existsSync as existsSync7, unwatchFile, watchFile } from "fs";
1196
+ import { existsSync as existsSync9, unwatchFile, watchFile } from "fs";
985
1197
  function watchForMarker(child) {
986
1198
  const statusPath = getSignalPath();
987
1199
  watchFile(statusPath, { interval: 1e3 }, () => {
988
- if (!existsSync7(statusPath)) return;
1200
+ if (!existsSync9(statusPath)) return;
989
1201
  const signal = readSignal();
990
1202
  if (signal) {
991
1203
  unwatchFile(statusPath);
@@ -1002,7 +1214,7 @@ async function executePhase(item, phaseIndex, phases, spawnOptions) {
1002
1214
  const phase = phases[phaseIndex];
1003
1215
  const phaseNumber = phaseIndex + 1;
1004
1216
  console.log(
1005
- chalk5.bold(
1217
+ chalk6.bold(
1006
1218
  `
1007
1219
  --- Phase ${phaseNumber}/${phases.length}: ${phase.name} ---
1008
1220
  `
@@ -1020,7 +1232,7 @@ async function executePhase(item, phaseIndex, phases, spawnOptions) {
1020
1232
  }
1021
1233
 
1022
1234
  // src/commands/backlog/prepareRun.ts
1023
- import chalk6 from "chalk";
1235
+ import chalk7 from "chalk";
1024
1236
 
1025
1237
  // src/commands/backlog/resolvePlan.ts
1026
1238
  function resolvePlan(item) {
@@ -1043,13 +1255,13 @@ function prepareRun(id) {
1043
1255
  const plan2 = resolvePlan(item);
1044
1256
  const startPhase = (item.currentPhase ?? 1) - 1;
1045
1257
  if (item.status === "done") {
1046
- console.log(chalk6.green(`Already done: #${id}: ${item.name}`));
1258
+ console.log(chalk7.green(`Already done: #${id}: ${item.name}`));
1047
1259
  return void 0;
1048
1260
  }
1049
1261
  if (startPhase > plan2.length) {
1050
1262
  setStatus(id, "done");
1051
1263
  console.log(
1052
- chalk6.green(`All phases already complete for #${id}: ${item.name}`)
1264
+ chalk7.green(`All phases already complete for #${id}: ${item.name}`)
1053
1265
  );
1054
1266
  return void 0;
1055
1267
  }
@@ -1074,13 +1286,13 @@ async function run(id, spawnOptions) {
1074
1286
  }
1075
1287
  }
1076
1288
  function logProgress(id, name, startPhase, total) {
1077
- console.log(chalk7.bold(`Running plan for #${id}: ${name}`));
1289
+ console.log(chalk8.bold(`Running plan for #${id}: ${name}`));
1078
1290
  if (startPhase > 0) {
1079
1291
  const phaseNumber = startPhase + 1;
1080
- console.log(chalk7.dim(`Resuming from phase ${phaseNumber}/${total}
1292
+ console.log(chalk8.dim(`Resuming from phase ${phaseNumber}/${total}
1081
1293
  `));
1082
1294
  } else {
1083
- console.log(chalk7.dim(`${total} phase(s)
1295
+ console.log(chalk8.dim(`${total} phase(s)
1084
1296
  `));
1085
1297
  }
1086
1298
  }
@@ -1113,7 +1325,7 @@ async function runReview(item, plan2, spawnOptions) {
1113
1325
  // src/commands/backlog/next.ts
1114
1326
  function toChoice(item, items) {
1115
1327
  const name = `${typeLabel(item.type)} #${item.id}: ${item.name}`;
1116
- return isBlocked(item, items) ? { name, disabled: chalk8.red("[blocked]") } : { name };
1328
+ return isBlocked(item, items) ? { name, disabled: chalk9.red("[blocked]") } : { name };
1117
1329
  }
1118
1330
  async function selectItem(todo, items) {
1119
1331
  const { selected } = await exitOnCancel(
@@ -1130,7 +1342,7 @@ async function pickItem(items, firstPick = false) {
1130
1342
  const resumable = findResumable(items);
1131
1343
  if (resumable) {
1132
1344
  console.log(
1133
- chalk8.bold(
1345
+ chalk9.bold(
1134
1346
  `Resuming in-progress item #${resumable.id}: ${resumable.name}`
1135
1347
  )
1136
1348
  );
@@ -1140,7 +1352,7 @@ async function pickItem(items, firstPick = false) {
1140
1352
  if (!unblocked) return void 0;
1141
1353
  if (firstPick && unblocked.length === 1) {
1142
1354
  const item = unblocked[0];
1143
- console.log(chalk8.bold(`Auto-selecting item #${item.id}: ${item.name}`));
1355
+ console.log(chalk9.bold(`Auto-selecting item #${item.id}: ${item.name}`));
1144
1356
  return String(item.id);
1145
1357
  }
1146
1358
  const todo = items.filter((i) => i.status === "todo");
@@ -1158,7 +1370,7 @@ async function next(options2) {
1158
1370
  }
1159
1371
 
1160
1372
  // src/commands/backlog/phaseDone.ts
1161
- import chalk9 from "chalk";
1373
+ import chalk10 from "chalk";
1162
1374
 
1163
1375
  // src/commands/backlog/addComment.ts
1164
1376
  function addComment(item, text, phase) {
@@ -1193,7 +1405,7 @@ function phaseDone(id, phase, summary) {
1193
1405
  });
1194
1406
  const result = loadAndFindItem(id);
1195
1407
  if (result?.item.status === "done") {
1196
- console.log(chalk9.dim(`Item #${id} already done, skipping phase advance.`));
1408
+ console.log(chalk10.dim(`Item #${id} already done, skipping phase advance.`));
1197
1409
  return;
1198
1410
  }
1199
1411
  if (result) {
@@ -1202,24 +1414,24 @@ function phaseDone(id, phase, summary) {
1202
1414
  }
1203
1415
  setCurrentPhase(id, phaseNumber + 1);
1204
1416
  console.log(
1205
- chalk9.green(`Phase ${phaseNumber} of item #${id} marked as complete.`)
1417
+ chalk10.green(`Phase ${phaseNumber} of item #${id} marked as complete.`)
1206
1418
  );
1207
1419
  }
1208
1420
 
1209
1421
  // src/commands/backlog/plan.ts
1210
- import chalk10 from "chalk";
1422
+ import chalk11 from "chalk";
1211
1423
  function plan(id) {
1212
1424
  const result = loadAndFindItem(id);
1213
1425
  if (!result) return;
1214
1426
  const { item } = result;
1215
1427
  if (!item.plan || item.plan.length === 0) {
1216
- console.log(chalk10.dim("No plan defined for this item."));
1428
+ console.log(chalk11.dim("No plan defined for this item."));
1217
1429
  return;
1218
1430
  }
1219
- console.log(chalk10.bold(item.name));
1431
+ console.log(chalk11.bold(item.name));
1220
1432
  console.log();
1221
1433
  for (const [i, phase] of item.plan.entries()) {
1222
- console.log(`${chalk10.bold(`Phase ${i + 1}:`)} ${phase.name}`);
1434
+ console.log(`${chalk11.bold(`Phase ${i + 1}:`)} ${phase.name}`);
1223
1435
  for (const task of phase.tasks) {
1224
1436
  console.log(` - ${task.task}`);
1225
1437
  }
@@ -1228,35 +1440,35 @@ function plan(id) {
1228
1440
  }
1229
1441
 
1230
1442
  // src/commands/backlog/show/index.ts
1231
- import chalk14 from "chalk";
1443
+ import chalk15 from "chalk";
1232
1444
 
1233
1445
  // src/commands/backlog/formatComment.ts
1234
- import chalk11 from "chalk";
1446
+ import chalk12 from "chalk";
1235
1447
  function formatComment(entry) {
1236
- const id = entry.id !== void 0 ? chalk11.dim(`#${entry.id} `) : "";
1237
- const tag = entry.type === "summary" ? chalk11.magenta("[summary]") : chalk11.cyan("[comment]");
1238
- const phase = entry.phase !== void 0 ? chalk11.dim(` (phase ${entry.phase})`) : "";
1239
- const time = chalk11.dim(entry.timestamp);
1448
+ const id = entry.id !== void 0 ? chalk12.dim(`#${entry.id} `) : "";
1449
+ const tag = entry.type === "summary" ? chalk12.magenta("[summary]") : chalk12.cyan("[comment]");
1450
+ const phase = entry.phase !== void 0 ? chalk12.dim(` (phase ${entry.phase})`) : "";
1451
+ const time = chalk12.dim(entry.timestamp);
1240
1452
  return `${id}${tag}${phase} ${time}
1241
1453
  ${entry.text}`;
1242
1454
  }
1243
1455
 
1244
1456
  // src/commands/backlog/show/printLinks.ts
1245
- import chalk12 from "chalk";
1457
+ import chalk13 from "chalk";
1246
1458
  function printLinks(item, items) {
1247
1459
  const links = item.links ?? [];
1248
1460
  if (links.length === 0) return;
1249
- console.log(chalk12.bold("Links"));
1461
+ console.log(chalk13.bold("Links"));
1250
1462
  for (const link3 of links) {
1251
1463
  const target = items.find((i) => i.id === link3.targetId);
1252
- const typeLabel2 = link3.type === "depends-on" ? chalk12.red("depends-on") : chalk12.blue("relates-to");
1464
+ const typeLabel2 = link3.type === "depends-on" ? chalk13.red("depends-on") : chalk13.blue("relates-to");
1253
1465
  if (target) {
1254
1466
  console.log(
1255
- ` ${typeLabel2} #${target.id} ${target.name} ${chalk12.dim(`(${target.status})`)}`
1467
+ ` ${typeLabel2} #${target.id} ${target.name} ${chalk13.dim(`(${target.status})`)}`
1256
1468
  );
1257
1469
  } else {
1258
1470
  console.log(
1259
- ` ${typeLabel2} #${link3.targetId} ${chalk12.dim("(not found)")}`
1471
+ ` ${typeLabel2} #${link3.targetId} ${chalk13.dim("(not found)")}`
1260
1472
  );
1261
1473
  }
1262
1474
  }
@@ -1264,15 +1476,15 @@ function printLinks(item, items) {
1264
1476
  }
1265
1477
 
1266
1478
  // src/commands/backlog/show/printPhaseTasks.ts
1267
- import chalk13 from "chalk";
1479
+ import chalk14 from "chalk";
1268
1480
  function printPhaseTasks(phase) {
1269
1481
  for (const task of phase.tasks) {
1270
1482
  console.log(` - ${task.task}`);
1271
1483
  }
1272
1484
  if (phase.manualChecks && phase.manualChecks.length > 0) {
1273
- console.log(` ${chalk13.dim("Manual checks:")}`);
1485
+ console.log(` ${chalk14.dim("Manual checks:")}`);
1274
1486
  for (const check2 of phase.manualChecks) {
1275
- console.log(` ${chalk13.dim(`- ${check2}`)}`);
1487
+ console.log(` ${chalk14.dim(`- ${check2}`)}`);
1276
1488
  }
1277
1489
  }
1278
1490
  }
@@ -1280,7 +1492,7 @@ function printPhaseTasks(phase) {
1280
1492
  // src/commands/backlog/show/index.ts
1281
1493
  function printPlan(item) {
1282
1494
  if (!item.plan || item.plan.length === 0) return;
1283
- console.log(chalk14.bold("Plan"));
1495
+ console.log(chalk15.bold("Plan"));
1284
1496
  for (const [i, phase] of item.plan.entries()) {
1285
1497
  const isCurrent = item.currentPhase === i + 1;
1286
1498
  printPhase(phase, i, isCurrent);
@@ -1289,8 +1501,8 @@ function printPlan(item) {
1289
1501
  }
1290
1502
  function phaseHeader(index, name, isCurrent) {
1291
1503
  const phaseNumber = index + 1;
1292
- const marker = isCurrent ? chalk14.green("\u25B6 ") : " ";
1293
- const label2 = isCurrent ? chalk14.green.bold(`Phase ${phaseNumber}: ${name}`) : `${chalk14.bold(`Phase ${phaseNumber}:`)} ${name}`;
1504
+ const marker = isCurrent ? chalk15.green("\u25B6 ") : " ";
1505
+ const label2 = isCurrent ? chalk15.green.bold(`Phase ${phaseNumber}: ${name}`) : `${chalk15.bold(`Phase ${phaseNumber}:`)} ${name}`;
1294
1506
  return `${marker}${label2}`;
1295
1507
  }
1296
1508
  function printPhase(phase, index, isCurrent) {
@@ -1298,15 +1510,15 @@ function printPhase(phase, index, isCurrent) {
1298
1510
  printPhaseTasks(phase);
1299
1511
  }
1300
1512
  function printHeader(item) {
1301
- console.log(chalk14.bold(`#${item.id} ${item.name}`));
1513
+ console.log(chalk15.bold(`#${item.id} ${item.name}`));
1302
1514
  console.log(
1303
- `${chalk14.dim("Type:")} ${item.type} ${chalk14.dim("Status:")} ${item.status}`
1515
+ `${chalk15.dim("Type:")} ${item.type} ${chalk15.dim("Status:")} ${item.status}`
1304
1516
  );
1305
1517
  console.log();
1306
1518
  }
1307
1519
  function printAcceptanceCriteria(criteria) {
1308
1520
  if (criteria.length === 0) return;
1309
- console.log(chalk14.bold("Acceptance Criteria"));
1521
+ console.log(chalk15.bold("Acceptance Criteria"));
1310
1522
  for (const [i, ac] of criteria.entries()) {
1311
1523
  console.log(` ${i + 1}. ${ac}`);
1312
1524
  }
@@ -1318,7 +1530,7 @@ function show(id) {
1318
1530
  const { item, items } = result;
1319
1531
  printHeader(item);
1320
1532
  if (item.description) {
1321
- console.log(chalk14.bold("Description"));
1533
+ console.log(chalk15.bold("Description"));
1322
1534
  console.log(item.description);
1323
1535
  console.log();
1324
1536
  }
@@ -1330,7 +1542,7 @@ function show(id) {
1330
1542
  function printComments(item) {
1331
1543
  const entries = item.comments ?? [];
1332
1544
  if (entries.length === 0) return;
1333
- console.log(chalk14.bold("Comments"));
1545
+ console.log(chalk15.bold("Comments"));
1334
1546
  for (const entry of entries) {
1335
1547
  console.log(` ${formatComment(entry)}`);
1336
1548
  }
@@ -1339,23 +1551,23 @@ function printComments(item) {
1339
1551
 
1340
1552
  // src/shared/web.ts
1341
1553
  import { exec } from "child_process";
1342
- import { readFileSync as readFileSync6 } from "fs";
1554
+ import { readFileSync as readFileSync7 } from "fs";
1343
1555
  import {
1344
1556
  createServer
1345
1557
  } from "http";
1346
- import { dirname, join as join7 } from "path";
1558
+ import { dirname as dirname2, join as join8 } from "path";
1347
1559
  import { fileURLToPath } from "url";
1348
- import chalk15 from "chalk";
1560
+ import chalk16 from "chalk";
1349
1561
  function respondJson(res, status2, data) {
1350
1562
  res.writeHead(status2, { "Content-Type": "application/json" });
1351
1563
  res.end(JSON.stringify(data));
1352
1564
  }
1353
1565
  function createBundleHandler(importMetaUrl, bundlePath) {
1354
- const dir = dirname(fileURLToPath(importMetaUrl));
1566
+ const dir = dirname2(fileURLToPath(importMetaUrl));
1355
1567
  let cache;
1356
1568
  return (_req, res) => {
1357
1569
  if (!cache) {
1358
- cache = readFileSync6(join7(dir, bundlePath), "utf-8");
1570
+ cache = readFileSync7(join8(dir, bundlePath), "utf-8");
1359
1571
  }
1360
1572
  res.writeHead(200, { "Content-Type": "application/javascript" });
1361
1573
  res.end(cache);
@@ -1389,8 +1601,8 @@ function startWebServer(label2, port, handler) {
1389
1601
  handler(req, res, port);
1390
1602
  });
1391
1603
  server.listen(port, () => {
1392
- console.log(chalk15.green(`${label2}: ${url}`));
1393
- console.log(chalk15.dim("Press Ctrl+C to stop"));
1604
+ console.log(chalk16.green(`${label2}: ${url}`));
1605
+ console.log(chalk16.dim("Press Ctrl+C to stop"));
1394
1606
  exec(`open ${url}`);
1395
1607
  });
1396
1608
  }
@@ -1550,7 +1762,7 @@ async function web(options2) {
1550
1762
  }
1551
1763
 
1552
1764
  // src/commands/backlog/launchMode.ts
1553
- import chalk16 from "chalk";
1765
+ import chalk17 from "chalk";
1554
1766
  async function launchMode(slashCommand) {
1555
1767
  process.env.ASSIST_SESSION_ID = String(process.pid);
1556
1768
  const { child, done: done2 } = spawnClaude(`/${slashCommand}`, { allowEdits: true });
@@ -1560,13 +1772,13 @@ async function launchMode(slashCommand) {
1560
1772
  const signal = readSignal();
1561
1773
  cleanupSignal();
1562
1774
  if (signal?.event === "next") {
1563
- console.log(chalk16.bold("\nChaining into assist next...\n"));
1775
+ console.log(chalk17.bold("\nChaining into assist next...\n"));
1564
1776
  await next({ allowEdits: true });
1565
1777
  }
1566
1778
  }
1567
1779
 
1568
1780
  // src/commands/backlog/refine.ts
1569
- import chalk17 from "chalk";
1781
+ import chalk18 from "chalk";
1570
1782
  import enquirer3 from "enquirer";
1571
1783
  async function pickItemForRefine() {
1572
1784
  const items = loadBacklog();
@@ -1574,12 +1786,12 @@ async function pickItemForRefine() {
1574
1786
  (i) => i.status === "todo" || i.status === "in-progress"
1575
1787
  );
1576
1788
  if (active.length === 0) {
1577
- console.log(chalk17.yellow("No active backlog items to refine."));
1789
+ console.log(chalk18.yellow("No active backlog items to refine."));
1578
1790
  return void 0;
1579
1791
  }
1580
1792
  if (active.length === 1) {
1581
1793
  const item = active[0];
1582
- console.log(chalk17.bold(`Auto-selecting item #${item.id}: ${item.name}`));
1794
+ console.log(chalk18.bold(`Auto-selecting item #${item.id}: ${item.name}`));
1583
1795
  return String(item.id);
1584
1796
  }
1585
1797
  const { selected } = await exitOnCancel(
@@ -1603,211 +1815,6 @@ async function refine(id) {
1603
1815
  // src/commands/commit.ts
1604
1816
  import { execSync } from "child_process";
1605
1817
 
1606
- // src/shared/loadConfig.ts
1607
- import { existsSync as existsSync9, writeFileSync as writeFileSync5 } from "fs";
1608
- import { homedir } from "os";
1609
- import { dirname as dirname2, join as join8 } from "path";
1610
- import chalk18 from "chalk";
1611
- import { stringify as stringifyYaml } from "yaml";
1612
-
1613
- // src/shared/loadRawYaml.ts
1614
- import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
1615
- import { parse as parseYaml2 } from "yaml";
1616
- function loadRawYaml(path50) {
1617
- if (!existsSync8(path50)) return {};
1618
- try {
1619
- const content = readFileSync7(path50, "utf-8");
1620
- return parseYaml2(content) || {};
1621
- } catch {
1622
- return {};
1623
- }
1624
- }
1625
-
1626
- // src/shared/types.ts
1627
- import { z as z2 } from "zod";
1628
- var runParamSchema = z2.strictObject({
1629
- name: z2.string(),
1630
- required: z2.boolean().optional(),
1631
- default: z2.string().optional(),
1632
- description: z2.string().optional()
1633
- });
1634
- var runConfigSchema = z2.strictObject({
1635
- name: z2.string(),
1636
- command: z2.string(),
1637
- args: z2.array(z2.string()).optional(),
1638
- params: z2.array(runParamSchema).optional(),
1639
- env: z2.record(z2.string(), z2.string()).optional(),
1640
- filter: z2.string().optional(),
1641
- pre: z2.array(z2.string()).optional(),
1642
- cwd: z2.string().optional()
1643
- });
1644
- var runLinkSchema = z2.strictObject({
1645
- link: z2.string(),
1646
- prefix: z2.string()
1647
- });
1648
- var transcriptConfigSchema = z2.strictObject({
1649
- vttDir: z2.string(),
1650
- transcriptsDir: z2.string(),
1651
- summaryDir: z2.string()
1652
- });
1653
- var DEFAULT_WAKE_WORDS = ["computer"];
1654
- var DEFAULT_MODELS_DIR = "~/.assist/voice/models";
1655
- var assistConfigSchema = z2.strictObject({
1656
- commit: z2.strictObject({
1657
- conventional: z2.boolean().default(false),
1658
- pull: z2.boolean().default(false),
1659
- push: z2.boolean().default(false)
1660
- }).default({ conventional: false, pull: false, push: false }),
1661
- devlog: z2.strictObject({
1662
- name: z2.string().optional(),
1663
- ignore: z2.array(z2.string()).optional(),
1664
- skip: z2.record(z2.string(), z2.array(z2.string())).optional()
1665
- }).optional(),
1666
- notify: z2.strictObject({
1667
- enabled: z2.boolean().default(true)
1668
- }).default({ enabled: true }),
1669
- complexity: z2.strictObject({
1670
- ignore: z2.array(z2.string()).default(["**/*test.ts*"])
1671
- }).default({ ignore: ["**/*test.ts*"] }),
1672
- hardcodedColors: z2.strictObject({
1673
- ignore: z2.array(z2.string()).default([])
1674
- }).optional(),
1675
- restructure: z2.strictObject({
1676
- ignore: z2.array(z2.string()).default([])
1677
- }).optional(),
1678
- jira: z2.strictObject({
1679
- acField: z2.string().default("customfield_11937")
1680
- }).optional(),
1681
- roam: z2.strictObject({
1682
- clientId: z2.string(),
1683
- clientSecret: z2.string(),
1684
- accessToken: z2.string().optional(),
1685
- refreshToken: z2.string().optional(),
1686
- tokenExpiresAt: z2.number().optional()
1687
- }).optional(),
1688
- run: z2.array(z2.union([runConfigSchema, runLinkSchema])).optional(),
1689
- transcript: transcriptConfigSchema.optional(),
1690
- cliReadVerbs: z2.record(z2.string(), z2.array(z2.string())).optional(),
1691
- news: z2.strictObject({
1692
- feeds: z2.array(z2.string()).default([])
1693
- }).default({ feeds: [] }),
1694
- dotnet: z2.strictObject({
1695
- inspect: z2.strictObject({
1696
- suppress: z2.array(z2.string()).default([])
1697
- }).default({ suppress: [] })
1698
- }).optional(),
1699
- ravendb: z2.strictObject({
1700
- connections: z2.array(
1701
- z2.strictObject({
1702
- name: z2.string(),
1703
- url: z2.string(),
1704
- database: z2.string(),
1705
- apiKeyRef: z2.string()
1706
- })
1707
- ).default([]),
1708
- defaultConnection: z2.string().optional()
1709
- }).optional(),
1710
- seq: z2.strictObject({
1711
- connections: z2.array(
1712
- z2.strictObject({
1713
- name: z2.string(),
1714
- url: z2.string(),
1715
- apiToken: z2.string()
1716
- })
1717
- ).default([]),
1718
- defaultConnection: z2.string().optional()
1719
- }).optional(),
1720
- screenshot: z2.strictObject({
1721
- outputDir: z2.string().default("./screenshots")
1722
- }).default({ outputDir: "./screenshots" }),
1723
- backlog: z2.strictObject({
1724
- autoCommit: z2.boolean().default(false)
1725
- }).default({ autoCommit: false }),
1726
- deny: z2.array(
1727
- z2.strictObject({
1728
- pattern: z2.string(),
1729
- message: z2.string()
1730
- })
1731
- ).optional(),
1732
- sync: z2.strictObject({
1733
- autoConfirm: z2.boolean().default(false)
1734
- }).default({ autoConfirm: false }),
1735
- voice: z2.strictObject({
1736
- wakeWords: z2.array(z2.string()).default(DEFAULT_WAKE_WORDS),
1737
- mic: z2.string().optional(),
1738
- cwd: z2.string().optional(),
1739
- modelsDir: z2.string().default(DEFAULT_MODELS_DIR),
1740
- lockDir: z2.string().optional(),
1741
- submitWindows: z2.array(z2.string()).optional(),
1742
- models: z2.strictObject({
1743
- vad: z2.string().optional(),
1744
- smartTurn: z2.string().optional()
1745
- }).default({})
1746
- }).default({
1747
- wakeWords: DEFAULT_WAKE_WORDS,
1748
- modelsDir: DEFAULT_MODELS_DIR,
1749
- models: {}
1750
- })
1751
- });
1752
- function isRunLink(entry) {
1753
- return "link" in entry;
1754
- }
1755
-
1756
- // src/shared/loadConfig.ts
1757
- function findConfigUp(startDir) {
1758
- let current = startDir;
1759
- while (current !== dirname2(current)) {
1760
- const claudePath = join8(current, ".claude", "assist.yml");
1761
- if (existsSync9(claudePath)) return claudePath;
1762
- const rootPath = join8(current, "assist.yml");
1763
- if (existsSync9(rootPath)) return rootPath;
1764
- current = dirname2(current);
1765
- }
1766
- return null;
1767
- }
1768
- function getConfigPath() {
1769
- const found = findConfigUp(process.cwd());
1770
- if (found) return found;
1771
- return join8(process.cwd(), "assist.yml");
1772
- }
1773
- function getGlobalConfigPath() {
1774
- return join8(homedir(), ".assist.yml");
1775
- }
1776
- function getConfigDir() {
1777
- return dirname2(getConfigPath());
1778
- }
1779
- function loadConfig() {
1780
- const globalRaw = loadRawYaml(getGlobalConfigPath());
1781
- const projectRaw = loadRawYaml(getConfigPath());
1782
- const merged = { ...globalRaw, ...projectRaw };
1783
- return assistConfigSchema.parse(merged);
1784
- }
1785
- function loadProjectConfig() {
1786
- return loadRawYaml(getConfigPath());
1787
- }
1788
- function loadGlobalConfigRaw() {
1789
- return loadRawYaml(getGlobalConfigPath());
1790
- }
1791
- function saveGlobalConfig(config) {
1792
- writeFileSync5(getGlobalConfigPath(), stringifyYaml(config, { lineWidth: 0 }));
1793
- }
1794
- function saveConfig(config) {
1795
- const configPath = getConfigPath();
1796
- writeFileSync5(configPath, stringifyYaml(config, { lineWidth: 0 }));
1797
- }
1798
- function getTranscriptConfig() {
1799
- const config = loadConfig();
1800
- if (!config.transcript) {
1801
- console.error(
1802
- chalk18.red(
1803
- "Transcript directories not configured. Run 'assist transcript configure' first."
1804
- )
1805
- );
1806
- process.exit(1);
1807
- }
1808
- return config.transcript;
1809
- }
1810
-
1811
1818
  // src/shared/shellQuote.ts
1812
1819
  function shellQuote(arg) {
1813
1820
  if (/[^a-zA-Z0-9_./:=@%^+,-]/.test(arg)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.190.0",
3
+ "version": "0.191.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {