@staff0rd/assist 0.78.0 → 0.79.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,6 +31,7 @@ After installation, the `assist` command will be available globally.
31
31
 
32
32
  ## Claude Commands
33
33
 
34
+ - `/comment` - Add pending review comments to the current PR
34
35
  - `/commit` - Commit only relevant files from the session
35
36
  - `/devlog` - Generate devlog entry for the next unversioned day
36
37
  - `/next-backlog-item` - Pick and implement the next backlog item
@@ -54,6 +55,7 @@ After installation, the `assist` command will be available globally.
54
55
  - `assist prs list-comments` - List all comments on the current branch's pull request
55
56
  - `assist prs fixed <comment-id> <sha>` - Reply with commit link and resolve thread
56
57
  - `assist prs wontfix <comment-id> <reason>` - Reply with reason and resolve thread
58
+ - `assist prs comment <path> <line> <body>` - Add a line comment to the pending review
57
59
  - `assist backlog` - Start the backlog web UI (same as `backlog web`)
58
60
  - `assist backlog init` - Create an empty assist.backlog.yml
59
61
  - `assist backlog list [--status <type>] [-v]` - List all backlog items with status icons
@@ -0,0 +1,39 @@
1
+ ---
2
+ description: Add pending review comments to the current PR
3
+ allowed_args: "<item numbers, e.g. 1,2,3>"
4
+ ---
5
+
6
+ Add pending review comments to the current branch's pull request for the specified items.
7
+
8
+ ## Parsing Arguments
9
+
10
+ Parse `$ARGUMENTS` as a comma-separated list of item numbers (e.g. `1,2` or `1,2,3`). These refer to items in a numbered list from earlier in the conversation.
11
+
12
+ ## Finding the Referenced List
13
+
14
+ Look back through the conversation for the most recent numbered list of issues, suggestions, or comments. Each item should have enough context to determine:
15
+ - **path**: the file path
16
+ - **line**: the line number
17
+ - **body**: a concise comment describing the issue
18
+
19
+ If any referenced item number doesn't exist in the list, report the error and skip it.
20
+
21
+ ## Posting Comments
22
+
23
+ For each referenced item, run:
24
+
25
+ ```
26
+ assist prs comment <path> <line> '<body>' 2>&1
27
+ ```
28
+
29
+ **Important:** Always use single quotes around `<body>`, never double quotes. Double quotes cause shell escaping issues with backticks and special characters.
30
+
31
+ The body must:
32
+ - Be a clear, concise description of the issue (1-2 sentences)
33
+ - Not contain "claude" or "opus" (case-insensitive) — the command will reject it
34
+ - Not contain single quotes (reword to avoid them)
35
+ - Use backticks to wrap inline code or keywords (e.g. `functionName`)
36
+
37
+ ## Report
38
+
39
+ After posting, summarise which comments were added and any that failed.
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.78.0",
9
+ version: "0.79.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -3269,37 +3269,11 @@ function registerDevlog(program2) {
3269
3269
  devlogCommand.command("skip <date>").description("Add a date (YYYY-MM-DD) to the skip list").action(skip);
3270
3270
  }
3271
3271
 
3272
- // src/commands/prs/fixed.ts
3273
- import { execSync as execSync17 } from "child_process";
3274
-
3275
- // src/commands/prs/resolveCommentWithReply.ts
3276
- import { execSync as execSync16 } from "child_process";
3277
- import { unlinkSync as unlinkSync4, writeFileSync as writeFileSync13 } from "fs";
3272
+ // src/commands/prs/comment.ts
3273
+ import { spawnSync as spawnSync2 } from "child_process";
3274
+ import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync13 } from "fs";
3278
3275
  import { tmpdir as tmpdir2 } from "os";
3279
- import { join as join13 } from "path";
3280
-
3281
- // src/commands/prs/loadCommentsCache.ts
3282
- import { existsSync as existsSync16, readFileSync as readFileSync14, unlinkSync as unlinkSync3 } from "fs";
3283
3276
  import { join as join12 } from "path";
3284
- import { parse } from "yaml";
3285
- function getCachePath(prNumber) {
3286
- return join12(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
3287
- }
3288
- function loadCommentsCache(prNumber) {
3289
- const cachePath = getCachePath(prNumber);
3290
- if (!existsSync16(cachePath)) {
3291
- return null;
3292
- }
3293
- const content = readFileSync14(cachePath, "utf-8");
3294
- return parse(content);
3295
- }
3296
- function deleteCommentsCache(prNumber) {
3297
- const cachePath = getCachePath(prNumber);
3298
- if (existsSync16(cachePath)) {
3299
- unlinkSync3(cachePath);
3300
- console.log("No more unresolved line comments. Cache dropped.");
3301
- }
3302
- }
3303
3277
 
3304
3278
  // src/commands/prs/shared.ts
3305
3279
  import { execSync as execSync15 } from "child_process";
@@ -3336,6 +3310,110 @@ function getCurrentPrNumber() {
3336
3310
  throw error;
3337
3311
  }
3338
3312
  }
3313
+ function getCurrentPrNodeId() {
3314
+ try {
3315
+ const prInfo = JSON.parse(
3316
+ execSync15("gh pr view --json id", { encoding: "utf-8" })
3317
+ );
3318
+ return prInfo.id;
3319
+ } catch (error) {
3320
+ if (error instanceof Error && error.message.includes("no pull requests")) {
3321
+ console.error("Error: No pull request found for the current branch.");
3322
+ process.exit(1);
3323
+ }
3324
+ throw error;
3325
+ }
3326
+ }
3327
+
3328
+ // src/commands/prs/comment.ts
3329
+ var MUTATION = `mutation($prId: ID!, $body: String!, $path: String!, $line: Int!) { addPullRequestReviewThread(input: { pullRequestId: $prId, body: $body, path: $path, line: $line, side: RIGHT }) { thread { id } } }`;
3330
+ function validateBody(body) {
3331
+ const lower = body.toLowerCase();
3332
+ if (lower.includes("claude") || lower.includes("opus")) {
3333
+ console.error('Error: Body must not contain "claude" or "opus"');
3334
+ process.exit(1);
3335
+ }
3336
+ }
3337
+ function validateLine(line) {
3338
+ if (!Number.isInteger(line) || line < 1) {
3339
+ console.error("Error: Line must be a positive integer");
3340
+ process.exit(1);
3341
+ }
3342
+ }
3343
+ function comment(path31, line, body) {
3344
+ validateBody(body);
3345
+ validateLine(line);
3346
+ try {
3347
+ const prId = getCurrentPrNodeId();
3348
+ const queryFile = join12(tmpdir2(), `gh-query-${Date.now()}.graphql`);
3349
+ writeFileSync13(queryFile, MUTATION);
3350
+ try {
3351
+ const result = spawnSync2(
3352
+ "gh",
3353
+ [
3354
+ "api",
3355
+ "graphql",
3356
+ "-F",
3357
+ `query=@${queryFile}`,
3358
+ "-f",
3359
+ `prId=${prId}`,
3360
+ "-f",
3361
+ `body=${body}`,
3362
+ "-f",
3363
+ `path=${path31}`,
3364
+ "-F",
3365
+ `line=${line}`
3366
+ ],
3367
+ { encoding: "utf-8" }
3368
+ );
3369
+ if (result.status !== 0) {
3370
+ throw new Error(result.stderr || result.stdout);
3371
+ }
3372
+ console.log(`Added review comment on ${path31}:${line}`);
3373
+ } finally {
3374
+ unlinkSync3(queryFile);
3375
+ }
3376
+ } catch (error) {
3377
+ if (isGhNotInstalled(error)) {
3378
+ console.error("Error: GitHub CLI (gh) is not installed.");
3379
+ console.error("Install it from https://cli.github.com/");
3380
+ process.exit(1);
3381
+ }
3382
+ throw error;
3383
+ }
3384
+ }
3385
+
3386
+ // src/commands/prs/fixed.ts
3387
+ import { execSync as execSync17 } from "child_process";
3388
+
3389
+ // src/commands/prs/resolveCommentWithReply.ts
3390
+ import { execSync as execSync16 } from "child_process";
3391
+ import { unlinkSync as unlinkSync5, writeFileSync as writeFileSync14 } from "fs";
3392
+ import { tmpdir as tmpdir3 } from "os";
3393
+ import { join as join14 } from "path";
3394
+
3395
+ // src/commands/prs/loadCommentsCache.ts
3396
+ import { existsSync as existsSync16, readFileSync as readFileSync14, unlinkSync as unlinkSync4 } from "fs";
3397
+ import { join as join13 } from "path";
3398
+ import { parse } from "yaml";
3399
+ function getCachePath(prNumber) {
3400
+ return join13(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
3401
+ }
3402
+ function loadCommentsCache(prNumber) {
3403
+ const cachePath = getCachePath(prNumber);
3404
+ if (!existsSync16(cachePath)) {
3405
+ return null;
3406
+ }
3407
+ const content = readFileSync14(cachePath, "utf-8");
3408
+ return parse(content);
3409
+ }
3410
+ function deleteCommentsCache(prNumber) {
3411
+ const cachePath = getCachePath(prNumber);
3412
+ if (existsSync16(cachePath)) {
3413
+ unlinkSync4(cachePath);
3414
+ console.log("No more unresolved line comments. Cache dropped.");
3415
+ }
3416
+ }
3339
3417
 
3340
3418
  // src/commands/prs/resolveCommentWithReply.ts
3341
3419
  function replyToComment(org, repo, prNumber, commentId, message) {
@@ -3346,15 +3424,15 @@ function replyToComment(org, repo, prNumber, commentId, message) {
3346
3424
  }
3347
3425
  function resolveThread(threadId) {
3348
3426
  const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
3349
- const queryFile = join13(tmpdir2(), `gh-mutation-${Date.now()}.graphql`);
3350
- writeFileSync13(queryFile, mutation);
3427
+ const queryFile = join14(tmpdir3(), `gh-mutation-${Date.now()}.graphql`);
3428
+ writeFileSync14(queryFile, mutation);
3351
3429
  try {
3352
3430
  execSync16(
3353
3431
  `gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
3354
3432
  { stdio: "inherit" }
3355
3433
  );
3356
3434
  } finally {
3357
- unlinkSync4(queryFile);
3435
+ unlinkSync5(queryFile);
3358
3436
  }
3359
3437
  }
3360
3438
  function requireCache(prNumber) {
@@ -3371,14 +3449,14 @@ function findLineComment(comments, commentId) {
3371
3449
  return comments.find((c) => c.type === "line" && c.id === commentId);
3372
3450
  }
3373
3451
  function requireLineComment(cache, commentId) {
3374
- const comment = findLineComment(cache.comments, commentId);
3375
- if (!comment || comment.type !== "line" || !comment.threadId) {
3452
+ const comment2 = findLineComment(cache.comments, commentId);
3453
+ if (!comment2 || comment2.type !== "line" || !comment2.threadId) {
3376
3454
  console.error(
3377
3455
  `Error: Comment #${commentId} not found or has no thread ID.`
3378
3456
  );
3379
3457
  process.exit(1);
3380
3458
  }
3381
- return comment;
3459
+ return comment2;
3382
3460
  }
3383
3461
  function cleanupCacheIfDone(cache, prNumber, commentId) {
3384
3462
  const hasRemaining = cache.comments.some(
@@ -3390,10 +3468,10 @@ function resolveCommentWithReply(commentId, message) {
3390
3468
  const prNumber = getCurrentPrNumber();
3391
3469
  const { org, repo } = getRepoInfo();
3392
3470
  const cache = requireCache(prNumber);
3393
- const comment = requireLineComment(cache, commentId);
3471
+ const comment2 = requireLineComment(cache, commentId);
3394
3472
  replyToComment(org, repo, prNumber, commentId, message);
3395
3473
  console.log("Reply posted successfully.");
3396
- resolveThread(comment.threadId);
3474
+ resolveThread(comment2.threadId);
3397
3475
  console.log("Thread resolved successfully.");
3398
3476
  cleanupCacheIfDone(cache, prNumber, commentId);
3399
3477
  }
@@ -3427,8 +3505,8 @@ function fixed(commentId, sha) {
3427
3505
  }
3428
3506
 
3429
3507
  // src/commands/prs/listComments/index.ts
3430
- import { existsSync as existsSync17, mkdirSync as mkdirSync4, writeFileSync as writeFileSync15 } from "fs";
3431
- import { join as join15 } from "path";
3508
+ import { existsSync as existsSync17, mkdirSync as mkdirSync4, writeFileSync as writeFileSync16 } from "fs";
3509
+ import { join as join16 } from "path";
3432
3510
  import { stringify } from "yaml";
3433
3511
 
3434
3512
  // src/lib/isClaudeCode.ts
@@ -3438,13 +3516,13 @@ function isClaudeCode2() {
3438
3516
 
3439
3517
  // src/commands/prs/fetchThreadIds.ts
3440
3518
  import { execSync as execSync18 } from "child_process";
3441
- import { unlinkSync as unlinkSync5, writeFileSync as writeFileSync14 } from "fs";
3442
- import { tmpdir as tmpdir3 } from "os";
3443
- import { join as join14 } from "path";
3519
+ import { unlinkSync as unlinkSync6, writeFileSync as writeFileSync15 } from "fs";
3520
+ import { tmpdir as tmpdir4 } from "os";
3521
+ import { join as join15 } from "path";
3444
3522
  var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
3445
3523
  function fetchThreadIds(org, repo, prNumber) {
3446
- const queryFile = join14(tmpdir3(), `gh-query-${Date.now()}.graphql`);
3447
- writeFileSync14(queryFile, THREAD_QUERY);
3524
+ const queryFile = join15(tmpdir4(), `gh-query-${Date.now()}.graphql`);
3525
+ writeFileSync15(queryFile, THREAD_QUERY);
3448
3526
  try {
3449
3527
  const result = execSync18(
3450
3528
  `gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
@@ -3457,13 +3535,13 @@ function fetchThreadIds(org, repo, prNumber) {
3457
3535
  if (thread.isResolved) {
3458
3536
  resolvedThreadIds.add(thread.id);
3459
3537
  }
3460
- for (const comment of thread.comments.nodes) {
3461
- threadMap.set(comment.databaseId, thread.id);
3538
+ for (const comment2 of thread.comments.nodes) {
3539
+ threadMap.set(comment2.databaseId, thread.id);
3462
3540
  }
3463
3541
  }
3464
3542
  return { threadMap, resolvedThreadIds };
3465
3543
  } finally {
3466
- unlinkSync5(queryFile);
3544
+ unlinkSync6(queryFile);
3467
3545
  }
3468
3546
  }
3469
3547
 
@@ -3511,42 +3589,42 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
3511
3589
 
3512
3590
  // src/commands/prs/listComments/formatForHuman.ts
3513
3591
  import chalk43 from "chalk";
3514
- function formatForHuman(comment) {
3515
- if (comment.type === "review") {
3516
- const stateColor = comment.state === "APPROVED" ? chalk43.green : comment.state === "CHANGES_REQUESTED" ? chalk43.red : chalk43.yellow;
3592
+ function formatForHuman(comment2) {
3593
+ if (comment2.type === "review") {
3594
+ const stateColor = comment2.state === "APPROVED" ? chalk43.green : comment2.state === "CHANGES_REQUESTED" ? chalk43.red : chalk43.yellow;
3517
3595
  return [
3518
- `${chalk43.cyan("Review")} by ${chalk43.bold(comment.user)} ${stateColor(`[${comment.state}]`)}`,
3519
- comment.body,
3596
+ `${chalk43.cyan("Review")} by ${chalk43.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
3597
+ comment2.body,
3520
3598
  ""
3521
3599
  ].join("\n");
3522
3600
  }
3523
- const location = comment.line ? `:${comment.line}` : "";
3601
+ const location = comment2.line ? `:${comment2.line}` : "";
3524
3602
  return [
3525
- `${chalk43.cyan("Line comment")} by ${chalk43.bold(comment.user)} on ${chalk43.dim(`${comment.path}${location}`)}`,
3526
- chalk43.dim(comment.diff_hunk.split("\n").slice(-3).join("\n")),
3527
- comment.body,
3603
+ `${chalk43.cyan("Line comment")} by ${chalk43.bold(comment2.user)} on ${chalk43.dim(`${comment2.path}${location}`)}`,
3604
+ chalk43.dim(comment2.diff_hunk.split("\n").slice(-3).join("\n")),
3605
+ comment2.body,
3528
3606
  ""
3529
3607
  ].join("\n");
3530
3608
  }
3531
3609
 
3532
3610
  // src/commands/prs/listComments/index.ts
3533
- function formatComment(comment) {
3534
- return isClaudeCode2() ? JSON.stringify(comment) : formatForHuman(comment);
3611
+ function formatComment(comment2) {
3612
+ return isClaudeCode2() ? JSON.stringify(comment2) : formatForHuman(comment2);
3535
3613
  }
3536
3614
  function printComments(comments) {
3537
3615
  if (comments.length === 0) {
3538
3616
  console.log("No comments found.");
3539
3617
  return;
3540
3618
  }
3541
- for (const comment of comments) {
3542
- console.log(formatComment(comment));
3619
+ for (const comment2 of comments) {
3620
+ console.log(formatComment(comment2));
3543
3621
  }
3544
3622
  if (!comments.some((c) => c.type === "line")) {
3545
3623
  console.log("No line comments to process.");
3546
3624
  }
3547
3625
  }
3548
3626
  function writeCommentsCache(prNumber, comments) {
3549
- const assistDir = join15(process.cwd(), ".assist");
3627
+ const assistDir = join16(process.cwd(), ".assist");
3550
3628
  if (!existsSync17(assistDir)) {
3551
3629
  mkdirSync4(assistDir, { recursive: true });
3552
3630
  }
@@ -3555,8 +3633,8 @@ function writeCommentsCache(prNumber, comments) {
3555
3633
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
3556
3634
  comments
3557
3635
  };
3558
- const cachePath = join15(assistDir, `pr-${prNumber}-comments.yaml`);
3559
- writeFileSync15(cachePath, stringify(cacheData));
3636
+ const cachePath = join16(assistDir, `pr-${prNumber}-comments.yaml`);
3637
+ writeFileSync16(cachePath, stringify(cacheData));
3560
3638
  }
3561
3639
  function handleKnownErrors(error) {
3562
3640
  if (isGhNotInstalled(error)) {
@@ -3781,6 +3859,9 @@ function registerPrs(program2) {
3781
3859
  prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
3782
3860
  wontfix(Number.parseInt(commentId, 10), reason);
3783
3861
  });
3862
+ prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path31, line, body) => {
3863
+ comment(path31, Number.parseInt(line, 10), body);
3864
+ });
3784
3865
  }
3785
3866
 
3786
3867
  // src/commands/refactor/check/index.ts
@@ -4518,7 +4599,7 @@ function registerRefactor(program2) {
4518
4599
 
4519
4600
  // src/commands/transcript/shared.ts
4520
4601
  import { existsSync as existsSync18, readdirSync as readdirSync2, statSync } from "fs";
4521
- import { basename as basename4, join as join16, relative } from "path";
4602
+ import { basename as basename4, join as join17, relative } from "path";
4522
4603
  import * as readline2 from "readline";
4523
4604
  var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
4524
4605
  function getDatePrefix(daysOffset = 0) {
@@ -4536,7 +4617,7 @@ function collectFiles(dir, extension) {
4536
4617
  if (!existsSync18(dir)) return [];
4537
4618
  const results = [];
4538
4619
  for (const entry of readdirSync2(dir)) {
4539
- const fullPath = join16(dir, entry);
4620
+ const fullPath = join17(dir, entry);
4540
4621
  if (statSync(fullPath).isDirectory()) {
4541
4622
  results.push(...collectFiles(fullPath, extension));
4542
4623
  } else if (entry.endsWith(extension)) {
@@ -4633,11 +4714,11 @@ async function configure() {
4633
4714
  import { existsSync as existsSync20 } from "fs";
4634
4715
 
4635
4716
  // src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
4636
- import { dirname as dirname13, join as join18 } from "path";
4717
+ import { dirname as dirname13, join as join19 } from "path";
4637
4718
 
4638
4719
  // src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
4639
4720
  import { renameSync } from "fs";
4640
- import { join as join17 } from "path";
4721
+ import { join as join18 } from "path";
4641
4722
  async function resolveDate(rl, choice) {
4642
4723
  if (choice === "1") return getDatePrefix(0);
4643
4724
  if (choice === "2") return getDatePrefix(-1);
@@ -4652,7 +4733,7 @@ async function resolveDate(rl, choice) {
4652
4733
  }
4653
4734
  function renameWithPrefix(vttDir, vttFile, prefix) {
4654
4735
  const newFilename = `${prefix}.${vttFile}`;
4655
- renameSync(join17(vttDir, vttFile), join17(vttDir, newFilename));
4736
+ renameSync(join18(vttDir, vttFile), join18(vttDir, newFilename));
4656
4737
  console.log(`Renamed to: ${newFilename}`);
4657
4738
  return newFilename;
4658
4739
  }
@@ -4686,12 +4767,12 @@ async function fixInvalidDatePrefixes(vttFiles) {
4686
4767
  const vttFileDir = dirname13(vttFile.absolutePath);
4687
4768
  const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
4688
4769
  if (newFilename) {
4689
- const newRelativePath = join18(
4770
+ const newRelativePath = join19(
4690
4771
  dirname13(vttFile.relativePath),
4691
4772
  newFilename
4692
4773
  );
4693
4774
  vttFiles[i] = {
4694
- absolutePath: join18(vttFileDir, newFilename),
4775
+ absolutePath: join19(vttFileDir, newFilename),
4695
4776
  relativePath: newRelativePath,
4696
4777
  filename: newFilename
4697
4778
  };
@@ -4704,8 +4785,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
4704
4785
  }
4705
4786
 
4706
4787
  // src/commands/transcript/format/processVttFile/index.ts
4707
- import { existsSync as existsSync19, mkdirSync as mkdirSync5, readFileSync as readFileSync15, writeFileSync as writeFileSync16 } from "fs";
4708
- import { basename as basename5, dirname as dirname14, join as join19 } from "path";
4788
+ import { existsSync as existsSync19, mkdirSync as mkdirSync5, readFileSync as readFileSync15, writeFileSync as writeFileSync17 } from "fs";
4789
+ import { basename as basename5, dirname as dirname14, join as join20 } from "path";
4709
4790
 
4710
4791
  // src/commands/transcript/cleanText.ts
4711
4792
  function cleanText(text) {
@@ -4915,17 +4996,17 @@ function toMdFilename(vttFilename) {
4915
4996
  return `${basename5(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
4916
4997
  }
4917
4998
  function resolveOutputDir(relativeDir, transcriptsDir) {
4918
- return relativeDir === "." ? transcriptsDir : join19(transcriptsDir, relativeDir);
4999
+ return relativeDir === "." ? transcriptsDir : join20(transcriptsDir, relativeDir);
4919
5000
  }
4920
5001
  function buildOutputPaths(vttFile, transcriptsDir) {
4921
5002
  const mdFile = toMdFilename(vttFile.filename);
4922
5003
  const relativeDir = dirname14(vttFile.relativePath);
4923
5004
  const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
4924
- const outputPath = join19(outputDir, mdFile);
5005
+ const outputPath = join20(outputDir, mdFile);
4925
5006
  return { outputDir, outputPath, mdFile, relativeDir };
4926
5007
  }
4927
5008
  function logSkipped(relativeDir, mdFile) {
4928
- console.log(`Skipping (already exists): ${join19(relativeDir, mdFile)}`);
5009
+ console.log(`Skipping (already exists): ${join20(relativeDir, mdFile)}`);
4929
5010
  return "skipped";
4930
5011
  }
4931
5012
  function ensureDirectory(dir, label2) {
@@ -4955,7 +5036,7 @@ function readAndParseCues(inputPath) {
4955
5036
  return processCues(readFileSync15(inputPath, "utf-8"));
4956
5037
  }
4957
5038
  function writeFormatted(outputPath, content) {
4958
- writeFileSync16(outputPath, content, "utf-8");
5039
+ writeFileSync17(outputPath, content, "utf-8");
4959
5040
  console.log(`Written: ${outputPath}`);
4960
5041
  }
4961
5042
  function convertVttToMarkdown(inputPath, outputPath) {
@@ -5024,7 +5105,7 @@ async function format() {
5024
5105
 
5025
5106
  // src/commands/transcript/summarise/index.ts
5026
5107
  import { existsSync as existsSync22 } from "fs";
5027
- import { basename as basename6, dirname as dirname16, join as join21, relative as relative2 } from "path";
5108
+ import { basename as basename6, dirname as dirname16, join as join22, relative as relative2 } from "path";
5028
5109
 
5029
5110
  // src/commands/transcript/summarise/processStagedFile/index.ts
5030
5111
  import {
@@ -5034,7 +5115,7 @@ import {
5034
5115
  renameSync as renameSync2,
5035
5116
  rmSync
5036
5117
  } from "fs";
5037
- import { dirname as dirname15, join as join20 } from "path";
5118
+ import { dirname as dirname15, join as join21 } from "path";
5038
5119
 
5039
5120
  // src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
5040
5121
  import chalk50 from "chalk";
@@ -5063,7 +5144,7 @@ function validateStagedContent(filename, content) {
5063
5144
  }
5064
5145
 
5065
5146
  // src/commands/transcript/summarise/processStagedFile/index.ts
5066
- var STAGING_DIR = join20(process.cwd(), ".assist", "transcript");
5147
+ var STAGING_DIR = join21(process.cwd(), ".assist", "transcript");
5067
5148
  function processStagedFile() {
5068
5149
  if (!existsSync21(STAGING_DIR)) {
5069
5150
  return false;
@@ -5087,7 +5168,7 @@ function processStagedFile() {
5087
5168
  );
5088
5169
  process.exit(1);
5089
5170
  }
5090
- const destPath = join20(summaryDir, matchingTranscript.relativePath);
5171
+ const destPath = join21(summaryDir, matchingTranscript.relativePath);
5091
5172
  const destDir = dirname15(destPath);
5092
5173
  if (!existsSync21(destDir)) {
5093
5174
  mkdirSync6(destDir, { recursive: true });
@@ -5103,7 +5184,7 @@ function processStagedFile() {
5103
5184
  // src/commands/transcript/summarise/index.ts
5104
5185
  function buildRelativeKey(relativePath, baseName) {
5105
5186
  const relDir = dirname16(relativePath);
5106
- return relDir === "." ? baseName : join21(relDir, baseName);
5187
+ return relDir === "." ? baseName : join22(relDir, baseName);
5107
5188
  }
5108
5189
  function buildSummaryIndex(summaryDir) {
5109
5190
  const summaryFiles = findMdFilesRecursive(summaryDir);
@@ -5137,8 +5218,8 @@ function summarise() {
5137
5218
  }
5138
5219
  const next2 = missing[0];
5139
5220
  const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
5140
- const outputPath = join21(STAGING_DIR, outputFilename);
5141
- const summaryFileDir = join21(summaryDir, dirname16(next2.relativePath));
5221
+ const outputPath = join22(STAGING_DIR, outputFilename);
5222
+ const summaryFileDir = join22(summaryDir, dirname16(next2.relativePath));
5142
5223
  const relativeTranscriptPath = encodeURI(
5143
5224
  relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
5144
5225
  );
@@ -5383,8 +5464,8 @@ function registerRoam(program2) {
5383
5464
  import { spawn as spawn4 } from "child_process";
5384
5465
 
5385
5466
  // src/commands/run/add.ts
5386
- import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync17 } from "fs";
5387
- import { join as join22 } from "path";
5467
+ import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync18 } from "fs";
5468
+ import { join as join23 } from "path";
5388
5469
  function findAddIndex() {
5389
5470
  const addIndex = process.argv.indexOf("add");
5390
5471
  if (addIndex === -1 || addIndex + 2 >= process.argv.length) return -1;
@@ -5438,7 +5519,7 @@ function saveNewRunConfig(name, command, args) {
5438
5519
  saveConfig(config);
5439
5520
  }
5440
5521
  function createCommandFile(name) {
5441
- const dir = join22(".claude", "commands");
5522
+ const dir = join23(".claude", "commands");
5442
5523
  mkdirSync7(dir, { recursive: true });
5443
5524
  const content = `---
5444
5525
  description: Run ${name}
@@ -5446,8 +5527,8 @@ description: Run ${name}
5446
5527
 
5447
5528
  Run \`assist run ${name} $ARGUMENTS 2>&1\`.
5448
5529
  `;
5449
- const filePath = join22(dir, `${name}.md`);
5450
- writeFileSync17(filePath, content);
5530
+ const filePath = join23(dir, `${name}.md`);
5531
+ writeFileSync18(filePath, content);
5451
5532
  console.log(`Created command file: ${filePath}`);
5452
5533
  }
5453
5534
  function add2() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@staff0rd/assist",
3
- "version": "0.78.0",
3
+ "version": "0.79.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {