@devflow-one/cli 0.1.14 → 0.1.16

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
@@ -182,6 +182,8 @@ devflow mr create "Title" feat/x --base release/2026.4 --project ABC
182
182
  # stamped with. Omitted or unrecognized, it is auto-selected by matching configured
183
183
  # type names against the title's conventional prefix, branch prefix, Jira issue type
184
184
  # and title keywords, falling back to the first type. Pass its id or label to pick one.
185
+ # The template (its own {prMedia} uploads media) writes the description; --body is the
186
+ # fallback, where {prMedia} is filled or removed.
185
187
  devflow mr create "Title" feat/x --type Bugfix --project ABC
186
188
  devflow mr types --project ABC # configured types: id, label, default flag
187
189
 
@@ -204,17 +206,42 @@ devflow commit template /wt/ABC-123 --no-push --project ABC # commit locally,
204
206
 
205
207
  # read a PR/MR's title + description, then edit it: --title/--description replace,
206
208
  # --append-description adds text after a `---` rule (skipped if already at the end);
207
- # --base retargets the PR/MR to an existing remote branch
209
+ # --base retargets the PR/MR to an existing remote branch; `{prMedia}` in the description
210
+ # uploads .devflow/media/<ISSUE-KEY>[-n].{mp4,png,jpg,jpeg} and is replaced with the links
211
+ # (removed when the upload fails or the head branch names no issue; media.error says why)
208
212
  devflow mr get 42 --project ABC
209
213
  devflow mr update 42 --append-description "## Test plan" --project ABC
210
214
  devflow mr update 42 --title "Fix login redirect" --project ABC
211
215
  devflow mr update 42 --base release/2026.4 --project ABC
216
+ devflow mr update 42 --description "$(cat body.md)" --project ABC # body.md has {prMedia}
212
217
 
213
218
  # assembled fix-review-comments prompt (read-only; runs no AI, makes no writes)
214
219
  devflow mr fix-prompt 42 # issue key inferred from the branch
215
220
 
221
+ # issue status and the repo card's branches and PRs/MRs (read-only; the issue key is
222
+ # inferred from the branch). Status needs the Jira API token set in Settings.
223
+ devflow issue status # the issue's and its parent's status
224
+ devflow issue branches ABC-123 --project ABC
225
+ devflow issue prs # every state, merged and closed included
226
+
227
+ # review comments: counts, then "Reply as Fixed" or an AI "Fix Comments" run, which
228
+ # commits and pushes (so it needs --force). It returns at once: `started`, `prNumber` and
229
+ # `queued` (true when an automation run is busy, so the fix starts on its next tick), or
230
+ # `started: false` with a `reason` — e.g. while the panel or the timer is fixing that PR
231
+ devflow mr comments 42 # unfixed / fixed / resolved / prComments
232
+ devflow mr reply-fixed 42 # success / failed / resolved counts
233
+ devflow mr fix-comments 42 --force # then re-check the counts
234
+
216
235
  # notify the project's configured Slack channel(s)
217
236
  devflow slack notify "Review fixes ready on {pr}" --values '{"pr":"#42"}' --project ABC
237
+ devflow slack channels --project ABC # configured channels (read-only, no credentials)
238
+
239
+ # reviewer notify: per channel, were reviewers already notified, and is the next step a
240
+ # send or a ping? `source` says who posted: manual (panel), auto (auto-send), gateway
241
+ # (`slack notify --pr`) or slack (found only in Slack history). `--pr` records the post
242
+ # and threads a ping under the earlier message
243
+ devflow mr notify-status 42
244
+ devflow slack notify "Please review #42" --channel C123 --pr 42
218
245
 
219
246
  # force a specific profile when a key is ambiguous
220
247
  devflow mr ready 12 --profile prof-1
@@ -222,7 +249,8 @@ devflow mr ready 12 --profile prof-1
222
249
 
223
250
  ### Destructive actions
224
251
 
225
- `branch delete`, `mr close` and `mr merge` are destructive. They are **refused
252
+ `branch delete`, `mr close`, `mr merge`, `mr fix-comments` (its AI run commits and
253
+ pushes) and `commit template` (unless `--no-push`) are destructive. They are **refused
226
254
  unless you confirm** with `--force` (or `--yes`); the gateway enforces the same
227
255
  gate server-side, so the confirmation can't be bypassed:
228
256
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devflow-one/cli",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "Terminal CLI wrapping the local DevFlow gateway so shell scripts can trigger repo actions.",
5
5
  "keywords": [
6
6
  "devflow",
package/src/commands.js CHANGED
@@ -218,6 +218,32 @@ const COMMANDS = {
218
218
  },
219
219
  },
220
220
 
221
+ "issue status": {
222
+ method: "POST",
223
+ action: "getIssueStatus",
224
+ usage:
225
+ "issue status [issueKey] [--issue KEY] [--project KEY]" +
226
+ " (the issue's and its parent's Jira status; needs the Jira API token source; read-only)",
227
+ buildArgs: issueKeyArgs("issue status"),
228
+ },
229
+ "issue branches": {
230
+ method: "POST",
231
+ action: "listIssueBranches",
232
+ usage:
233
+ "issue branches [issueKey] [--issue KEY] [--project KEY]" +
234
+ " (each repo's remote branches for the issue and its parent, as the repo card lists them; read-only)",
235
+ buildArgs: issueKeyArgs("issue branches"),
236
+ },
237
+ "issue prs": {
238
+ method: "POST",
239
+ action: "listIssuePullRequests",
240
+ usage:
241
+ "issue prs [issueKey] [--issue KEY] [--project KEY]" +
242
+ " (each repo's PRs/MRs for the issue in every state, merged and closed included, with" +
243
+ " approvers on open ones; read-only)",
244
+ buildArgs: issueKeyArgs("issue prs"),
245
+ },
246
+
221
247
  "mr create": {
222
248
  method: "POST",
223
249
  retryUnsafe: true,
@@ -228,7 +254,8 @@ const COMMANDS = {
228
254
  " (a headBranch that exists on the remote is used as is; otherwise the repo's branch" +
229
255
  " template picks the head branch from the issue; --base defaults to the repo's configured base branch, expanding a {year}/{number} pattern;" +
230
256
  " --type is auto-selected by matching PR type names against the title prefix, branch prefix," +
231
- " Jira issue type and title keywords, falling back to the first configured type)",
257
+ " Jira issue type and title keywords, falling back to the first configured type;" +
258
+ " the description comes from the PR type template, --body is the fallback where {prMedia} is filled or removed)",
232
259
  buildArgs: ([title, headBranch], flags, context = {}) => {
233
260
  const issueKey = templateIssueKey(headBranch, flags, context);
234
261
 
@@ -341,7 +368,10 @@ const COMMANDS = {
341
368
  " [--base <branch>] [--issue KEY] [--project KEY]" +
342
369
  " (--title/--description replace; --append-description adds text after a `---` rule" +
343
370
  " and is skipped if it already ends the description after that rule; --base retargets" +
344
- " the PR/MR to an existing remote branch)",
371
+ " the PR/MR to an existing remote branch; `{prMedia}` in --description or" +
372
+ " --append-description uploads .devflow/media/<ISSUE-KEY>[-n].{mp4,png,jpg,jpeg} and is" +
373
+ " replaced with the links, so swap old media links for `{prMedia}` to refresh them." +
374
+ " It is removed if the upload fails or the head branch names no issue; media.error says why)",
345
375
  buildArgs: ([prId], flags) => {
346
376
  const title = toText("title", flags.title);
347
377
  const body = toRawText("description", flags.description);
@@ -377,6 +407,46 @@ const COMMANDS = {
377
407
  return [parsedPrId, context.issueKey];
378
408
  },
379
409
  },
410
+ "mr comments": {
411
+ method: "POST",
412
+ action: "getPrReviewCommentCounts",
413
+ usage:
414
+ "mr comments <prId> [--issue KEY] [--project KEY]" +
415
+ " (unfixed / fixed / resolved review-thread and PR-level comment counts; read-only)",
416
+ buildArgs: ([prId]) => [toInt("prId", prId)],
417
+ },
418
+ "mr notify-status": {
419
+ method: "POST",
420
+ action: "getReviewerNotifyStatus",
421
+ usage:
422
+ "mr notify-status <prId> [--issue KEY] [--project KEY]" +
423
+ " (per reviewer channel: whether reviewers were already notified on Slack and whether the" +
424
+ " next step is a send or a ping, and who posted; follow up with `slack notify` for that" +
425
+ " PR; read-only)",
426
+ buildArgs: ([prId]) => [toInt("prId", prId)],
427
+ },
428
+ "mr fix-comments": {
429
+ method: "POST",
430
+ retryUnsafe: true,
431
+ action: "fixPrComments",
432
+ destructive: true,
433
+ usage:
434
+ "mr fix-comments <prId> [--issue KEY] [--project KEY] --force" +
435
+ " (starts an AI fix of the PR's unresolved review comments, which commits and pushes;" +
436
+ " returns at once: started / prNumber / queued, or a reason it was refused, e.g. that PR" +
437
+ " is already being fixed; re-check with `mr comments`)",
438
+ buildArgs: ([prId]) => [toInt("prId", prId)],
439
+ },
440
+ "mr reply-fixed": {
441
+ method: "POST",
442
+ retryUnsafe: true,
443
+ action: "replyPrCommentsFixed",
444
+ usage:
445
+ "mr reply-fixed <prId> [--issue KEY] [--project KEY]" +
446
+ ' (replies "Fixed" to every unanswered review thread, resolving it when the repo is set to;' +
447
+ " prints success / failed counts)",
448
+ buildArgs: ([prId]) => [toInt("prId", prId)],
449
+ },
380
450
  "pipeline status": {
381
451
  method: "POST",
382
452
  action: "getPipelineStatus",
@@ -423,16 +493,27 @@ const COMMANDS = {
423
493
  retryUnsafe: true,
424
494
  action: "notifySlack",
425
495
  usage:
426
- 'slack notify <message> [--channel ID] [--values \'{"key":"val"}\'] [--issue KEY] [--project KEY]',
496
+ 'slack notify <message> [--channel ID] [--values \'{"key":"val"}\'] [--pr <prId>]' +
497
+ " [--issue KEY] [--project KEY]" +
498
+ " (--pr records the post as that PR's reviewer notify; a channel already notified for it" +
499
+ " gets a ping threaded under the earlier message)",
427
500
  buildArgs: ([message], flags) => {
428
501
  if (!message) throw new UsageError("slack notify requires <message>.");
429
502
 
430
503
  const channel = flags.channel ? String(flags.channel) : undefined;
431
504
  const values = toValues("values", flags.values);
432
505
 
433
- return [message, channel, values];
506
+ if (flags.pr === undefined) return [message, channel, values];
507
+
508
+ return [message, channel, values, { prNumber: toInt("pr", String(flags.pr)) }];
434
509
  },
435
510
  },
511
+ "slack channels": {
512
+ method: "POST",
513
+ action: "listSlackChannels",
514
+ usage: "slack channels [--issue KEY] [--project KEY] (configured channels; read-only)",
515
+ buildArgs: () => [],
516
+ },
436
517
  };
437
518
 
438
519
  /**