@braingrid/cli 0.2.13 → 0.2.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/CHANGELOG.md CHANGED
@@ -7,6 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.16] - 2025-12-17
11
+
12
+ ### Added
13
+
14
+ - **--format option for show commands**
15
+ - Added `--format` option to `requirement show` command
16
+ - Added `--format` option to `task show` command
17
+ - Supports all standard formats: table (default), json, xml, markdown
18
+ - Consistent with other commands that already support `--format`
19
+
20
+ ## [0.2.15] - 2025-12-15
21
+
22
+ ### Changed
23
+
24
+ - **CI/CD: Switch to OIDC-based npm publishing**
25
+ - GitHub Actions workflow now uses OpenID Connect (Trusted Publishing) for npm authentication
26
+ - No longer requires NPM_TOKEN secret - authentication is handled via OIDC
27
+ - More secure and eliminates token expiration issues
28
+
29
+ ## [0.2.14] - 2025-12-15
30
+
31
+ ### Added
32
+
33
+ - **Requirement auto-detection for task commands**
34
+ - Task commands now auto-detect the requirement ID from git branch names (e.g., `feature/REQ-123-something` → `REQ-123`)
35
+ - Matches the existing behavior of requirement commands
36
+ - Applies to all task commands: `list`, `summary`, `show`, `create`, `update`, `delete`
37
+ - Explicit `-r/--requirement` flag still works and takes precedence over auto-detection
38
+
10
39
  ## [0.2.13] - 2025-12-08
11
40
 
12
41
  ### Added
package/dist/cli.js CHANGED
@@ -422,7 +422,7 @@ import axios3, { AxiosError as AxiosError2 } from "axios";
422
422
 
423
423
  // src/build-config.ts
424
424
  var BUILD_ENV = true ? "production" : process.env.NODE_ENV === "test" ? "development" : "production";
425
- var CLI_VERSION = true ? "0.2.13" : "0.0.0-test";
425
+ var CLI_VERSION = true ? "0.2.16" : "0.0.0-test";
426
426
  var PRODUCTION_CONFIG = {
427
427
  apiUrl: "https://app.braingrid.ai",
428
428
  workosAuthUrl: "https://auth.braingrid.ai",
@@ -3940,6 +3940,15 @@ async function handleRequirementShow(opts) {
3940
3940
  message: chalk7.red("\u274C Not authenticated. Please run `braingrid login` first.")
3941
3941
  };
3942
3942
  }
3943
+ const format = opts?.format || "table";
3944
+ if (!["table", "json", "xml", "markdown"].includes(format)) {
3945
+ return {
3946
+ success: false,
3947
+ message: chalk7.red(
3948
+ `\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
3949
+ )
3950
+ };
3951
+ }
3943
3952
  const requirementResult = await workspaceManager.getRequirement(opts?.id);
3944
3953
  if (!requirementResult.success) {
3945
3954
  return {
@@ -3961,17 +3970,39 @@ async function handleRequirementShow(opts) {
3961
3970
  const requirement2 = await requirementService.getProjectRequirement(projectId, normalizedId);
3962
3971
  stopSpinner();
3963
3972
  stopSpinner = null;
3964
- const output = formatRequirementOutput(requirement2, {
3965
- showDescription: true,
3966
- showContent: true,
3967
- showTasks: true,
3968
- showUpdated: true,
3969
- apiUrl: config.apiUrl,
3970
- projectShortId: projectId
3971
- });
3973
+ let output;
3974
+ switch (format) {
3975
+ case "json": {
3976
+ output = JSON.stringify(requirement2, null, 2);
3977
+ break;
3978
+ }
3979
+ case "xml": {
3980
+ output = formatRequirementBuildXml(requirement2);
3981
+ break;
3982
+ }
3983
+ case "markdown": {
3984
+ output = formatRequirementBuildMarkdown(requirement2, {
3985
+ apiUrl: config.apiUrl,
3986
+ projectShortId: projectId
3987
+ });
3988
+ break;
3989
+ }
3990
+ case "table":
3991
+ default: {
3992
+ output = "\n" + formatRequirementOutput(requirement2, {
3993
+ showDescription: true,
3994
+ showContent: true,
3995
+ showTasks: true,
3996
+ showUpdated: true,
3997
+ apiUrl: config.apiUrl,
3998
+ projectShortId: projectId
3999
+ });
4000
+ break;
4001
+ }
4002
+ }
3972
4003
  return {
3973
4004
  success: true,
3974
- message: "\n" + output,
4005
+ message: output,
3975
4006
  data: requirement2
3976
4007
  };
3977
4008
  } catch (error) {
@@ -4498,12 +4529,6 @@ async function handleTaskList(opts) {
4498
4529
  message: chalk8.red("\u274C Not authenticated. Please run `braingrid login` first.")
4499
4530
  };
4500
4531
  }
4501
- if (!opts.requirement) {
4502
- return {
4503
- success: false,
4504
- message: chalk8.red("\u274C No requirement specified.\n\n") + chalk8.dim("Please provide a requirement ID:\n") + chalk8.cyan("braingrid task list -r REQ-456") + chalk8.dim(" (if initialized) or\n") + chalk8.cyan("braingrid task list -r REQ-456 -p PROJ-123")
4505
- };
4506
- }
4507
4532
  const workspace = await workspaceManager.getProject(opts.project);
4508
4533
  if (!workspace.success) {
4509
4534
  return {
@@ -4512,7 +4537,14 @@ async function handleTaskList(opts) {
4512
4537
  };
4513
4538
  }
4514
4539
  const projectId = workspace.projectId;
4515
- const requirementId = normalizeRequirementId(opts.requirement);
4540
+ const requirementResult = await workspaceManager.getRequirement(opts.requirement);
4541
+ if (!requirementResult.success) {
4542
+ return {
4543
+ success: false,
4544
+ message: requirementResult.error
4545
+ };
4546
+ }
4547
+ const requirementId = requirementResult.requirementId;
4516
4548
  stopSpinner = showSpinner("Loading tasks", chalk8.gray);
4517
4549
  const response = await taskService.listTasks(projectId, requirementId);
4518
4550
  stopSpinner();
@@ -4525,7 +4557,7 @@ async function handleTaskList(opts) {
4525
4557
  };
4526
4558
  }
4527
4559
  const projectShortId = projectId;
4528
- const requirementShortId = opts.requirement;
4560
+ const requirementShortId = opts.requirement || requirementId;
4529
4561
  const format = opts.format || "markdown";
4530
4562
  const config = getConfig();
4531
4563
  const output = formatTasksListOutput(response.tasks, format, true, {
@@ -4560,12 +4592,6 @@ async function handleTaskSummary(opts) {
4560
4592
  message: chalk8.red("\u274C Not authenticated. Please run `braingrid login` first.")
4561
4593
  };
4562
4594
  }
4563
- if (!opts.requirement) {
4564
- return {
4565
- success: false,
4566
- message: chalk8.red("\u274C No requirement specified.\n\n") + chalk8.dim("Please provide a requirement ID:\n") + chalk8.cyan("braingrid task summary -r REQ-456") + chalk8.dim(" (if initialized) or\n") + chalk8.cyan("braingrid task summary -r REQ-456 -p PROJ-123")
4567
- };
4568
- }
4569
4595
  const workspace = await workspaceManager.getProject(opts.project);
4570
4596
  if (!workspace.success) {
4571
4597
  return {
@@ -4574,7 +4600,14 @@ async function handleTaskSummary(opts) {
4574
4600
  };
4575
4601
  }
4576
4602
  const projectId = workspace.projectId;
4577
- const requirementId = normalizeRequirementId(opts.requirement);
4603
+ const requirementResult = await workspaceManager.getRequirement(opts.requirement);
4604
+ if (!requirementResult.success) {
4605
+ return {
4606
+ success: false,
4607
+ message: requirementResult.error
4608
+ };
4609
+ }
4610
+ const requirementId = requirementResult.requirementId;
4578
4611
  stopSpinner = showSpinner("Loading tasks", chalk8.gray);
4579
4612
  const response = await taskService.listTasks(projectId, requirementId);
4580
4613
  stopSpinner();
@@ -4587,7 +4620,7 @@ async function handleTaskSummary(opts) {
4587
4620
  };
4588
4621
  }
4589
4622
  const projectShortId = projectId;
4590
- const requirementShortId = opts.requirement;
4623
+ const requirementShortId = opts.requirement || requirementId;
4591
4624
  const config = getConfig();
4592
4625
  const output = formatTasksListOutput(response.tasks, "table", false, {
4593
4626
  requirementId,
@@ -4621,13 +4654,16 @@ async function handleTaskShow(id, opts) {
4621
4654
  message: chalk8.red("\u274C Not authenticated. Please run `braingrid login` first.")
4622
4655
  };
4623
4656
  }
4624
- if (!opts?.requirement) {
4657
+ const format = opts?.format || "table";
4658
+ if (!["table", "json", "xml", "markdown"].includes(format)) {
4625
4659
  return {
4626
4660
  success: false,
4627
- message: chalk8.red("\u274C No requirement specified.\n\n") + chalk8.dim("Please provide a requirement ID:\n") + chalk8.cyan("braingrid task show TASK-789 -r REQ-456") + chalk8.dim(" (if initialized) or\n") + chalk8.cyan("braingrid task show TASK-789 -r REQ-456 -p PROJ-123")
4661
+ message: chalk8.red(
4662
+ `\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
4663
+ )
4628
4664
  };
4629
4665
  }
4630
- const workspace = await workspaceManager.getProject(opts.project);
4666
+ const workspace = await workspaceManager.getProject(opts?.project);
4631
4667
  if (!workspace.success) {
4632
4668
  return {
4633
4669
  success: false,
@@ -4635,20 +4671,48 @@ async function handleTaskShow(id, opts) {
4635
4671
  };
4636
4672
  }
4637
4673
  const projectId = workspace.projectId;
4638
- const requirementId = normalizeRequirementId(opts.requirement);
4674
+ const requirementResult = await workspaceManager.getRequirement(opts?.requirement);
4675
+ if (!requirementResult.success) {
4676
+ return {
4677
+ success: false,
4678
+ message: requirementResult.error
4679
+ };
4680
+ }
4681
+ const requirementId = requirementResult.requirementId;
4639
4682
  const taskId = normalizeTaskId(id);
4640
4683
  const config = getConfig();
4641
4684
  stopSpinner = showSpinner("Loading task", chalk8.gray);
4642
4685
  const task2 = await taskService.getTask(projectId, requirementId, taskId);
4643
4686
  stopSpinner();
4644
4687
  stopSpinner = null;
4645
- const output = formatTaskOutput(task2, {
4646
- showContent: true,
4647
- apiUrl: config.apiUrl,
4648
- projectShortId: projectId,
4649
- requirementShortId: opts.requirement,
4650
- requirementId
4651
- });
4688
+ let output;
4689
+ switch (format) {
4690
+ case "json": {
4691
+ output = JSON.stringify(task2, null, 2);
4692
+ break;
4693
+ }
4694
+ case "xml":
4695
+ case "markdown": {
4696
+ output = formatTasksListOutput([task2], format, true, {
4697
+ requirementId,
4698
+ projectShortId: projectId,
4699
+ requirementShortId: opts?.requirement || requirementId,
4700
+ apiUrl: config.apiUrl
4701
+ });
4702
+ break;
4703
+ }
4704
+ case "table":
4705
+ default: {
4706
+ output = formatTaskOutput(task2, {
4707
+ showContent: true,
4708
+ apiUrl: config.apiUrl,
4709
+ projectShortId: projectId,
4710
+ requirementShortId: opts?.requirement || requirementId,
4711
+ requirementId
4712
+ });
4713
+ break;
4714
+ }
4715
+ }
4652
4716
  return {
4653
4717
  success: true,
4654
4718
  message: output,
@@ -4675,12 +4739,6 @@ async function handleTaskCreate(opts) {
4675
4739
  message: chalk8.red("\u274C Not authenticated. Please run `braingrid login` first.")
4676
4740
  };
4677
4741
  }
4678
- if (!opts.requirement) {
4679
- return {
4680
- success: false,
4681
- message: chalk8.red("\u274C No requirement specified.\n\n") + chalk8.dim("Please provide a requirement ID:\n") + chalk8.cyan('braingrid task create -r REQ-456 --title "..."') + chalk8.dim(" (if initialized) or\n") + chalk8.cyan('braingrid task create -r REQ-456 -p PROJ-123 --title "..."')
4682
- };
4683
- }
4684
4742
  const workspace = await workspaceManager.getProject(opts.project);
4685
4743
  if (!workspace.success) {
4686
4744
  return {
@@ -4689,9 +4747,16 @@ async function handleTaskCreate(opts) {
4689
4747
  };
4690
4748
  }
4691
4749
  const projectId = workspace.projectId;
4692
- const requirementId = normalizeRequirementId(opts.requirement);
4750
+ const requirementResult = await workspaceManager.getRequirement(opts.requirement);
4751
+ if (!requirementResult.success) {
4752
+ return {
4753
+ success: false,
4754
+ message: requirementResult.error
4755
+ };
4756
+ }
4757
+ const requirementId = requirementResult.requirementId;
4693
4758
  const projectShortId = projectId;
4694
- const requirementShortId = opts.requirement;
4759
+ const requirementShortId = opts.requirement || requirementId;
4695
4760
  const config = getConfig();
4696
4761
  stopSpinner = showSpinner("Creating task", chalk8.gray);
4697
4762
  const task2 = await taskService.createTask(projectId, requirementId, {
@@ -4740,12 +4805,6 @@ async function handleTaskUpdate(id, opts) {
4740
4805
  message: chalk8.red("\u274C Please provide at least one field to update (--status or --title)")
4741
4806
  };
4742
4807
  }
4743
- if (!opts.requirement) {
4744
- return {
4745
- success: false,
4746
- message: chalk8.red("\u274C No requirement specified.\n\n") + chalk8.dim("Please provide a requirement ID:\n") + chalk8.cyan("braingrid task update TASK-789 -r REQ-456 --status COMPLETED") + chalk8.dim(" (if initialized) or\n") + chalk8.cyan("braingrid task update TASK-789 -r REQ-456 -p PROJ-123 --status COMPLETED")
4747
- };
4748
- }
4749
4808
  const workspace = await workspaceManager.getProject(opts.project);
4750
4809
  if (!workspace.success) {
4751
4810
  return {
@@ -4754,7 +4813,14 @@ async function handleTaskUpdate(id, opts) {
4754
4813
  };
4755
4814
  }
4756
4815
  const projectId = workspace.projectId;
4757
- const requirementId = normalizeRequirementId(opts.requirement);
4816
+ const requirementResult = await workspaceManager.getRequirement(opts.requirement);
4817
+ if (!requirementResult.success) {
4818
+ return {
4819
+ success: false,
4820
+ message: requirementResult.error
4821
+ };
4822
+ }
4823
+ const requirementId = requirementResult.requirementId;
4758
4824
  const taskId = normalizeTaskId(id);
4759
4825
  const config = getConfig();
4760
4826
  stopSpinner = showSpinner("Updating task", chalk8.gray);
@@ -4769,7 +4835,7 @@ async function handleTaskUpdate(id, opts) {
4769
4835
  successMessage: `Updated task ${task2.number}`,
4770
4836
  apiUrl: config.apiUrl,
4771
4837
  projectShortId: projectId,
4772
- requirementShortId: opts.requirement,
4838
+ requirementShortId: opts.requirement || requirementId,
4773
4839
  requirementId
4774
4840
  });
4775
4841
  return {
@@ -4804,12 +4870,6 @@ async function handleTaskDelete(id, opts) {
4804
4870
  message: chalk8.yellow("\u26A0\uFE0F Deleting a task is permanent. Use --force to confirm deletion.")
4805
4871
  };
4806
4872
  }
4807
- if (!opts.requirement) {
4808
- return {
4809
- success: false,
4810
- message: chalk8.red("\u274C No requirement specified.\n\n") + chalk8.dim("Please provide a requirement ID:\n") + chalk8.cyan("braingrid task delete TASK-789 -r REQ-456 --force") + chalk8.dim(" (if initialized) or\n") + chalk8.cyan("braingrid task delete TASK-789 -r REQ-456 -p PROJ-123 --force")
4811
- };
4812
- }
4813
4873
  const workspace = await workspaceManager.getProject(opts.project);
4814
4874
  if (!workspace.success) {
4815
4875
  return {
@@ -4818,7 +4878,14 @@ async function handleTaskDelete(id, opts) {
4818
4878
  };
4819
4879
  }
4820
4880
  const projectId = workspace.projectId;
4821
- const requirementId = normalizeRequirementId(opts.requirement);
4881
+ const requirementResult = await workspaceManager.getRequirement(opts.requirement);
4882
+ if (!requirementResult.success) {
4883
+ return {
4884
+ success: false,
4885
+ message: requirementResult.error
4886
+ };
4887
+ }
4888
+ const requirementId = requirementResult.requirementId;
4822
4889
  const taskId = normalizeTaskId(id);
4823
4890
  stopSpinner = showSpinner("Deleting task", chalk8.gray);
4824
4891
  await taskService.deleteTask(projectId, requirementId, taskId);
@@ -6948,7 +7015,7 @@ requirement.command("list").description("List requirements for a project").optio
6948
7015
  requirement.command("show [id]").description("Show requirement details (auto-detects ID from git branch if not provided)").option(
6949
7016
  "-p, --project <id>",
6950
7017
  "project ID (auto-detects from .braingrid/project.json if not provided)"
6951
- ).action(async (id, opts) => {
7018
+ ).option("--format <format>", "output format (table, json, xml, markdown)", "table").action(async (id, opts) => {
6952
7019
  const result = await handleRequirementShow({ ...opts, id });
6953
7020
  console.log(result.message);
6954
7021
  if (!result.success) {
@@ -7021,7 +7088,7 @@ task.command("summary").description("Show task summary table (quick overview wit
7021
7088
  process.exit(1);
7022
7089
  }
7023
7090
  });
7024
- task.command("show <id>").description("Show task details").option("-r, --requirement <id>", "requirement ID (REQ-456, auto-detects project if initialized)").option("-p, --project <id>", "project ID (PROJ-123, optional if project is initialized)").action(async (id, opts) => {
7091
+ task.command("show <id>").description("Show task details").option("-r, --requirement <id>", "requirement ID (REQ-456, auto-detects project if initialized)").option("-p, --project <id>", "project ID (PROJ-123, optional if project is initialized)").option("--format <format>", "output format (table, json, xml, markdown)", "table").action(async (id, opts) => {
7025
7092
  const result = await handleTaskShow(id, opts);
7026
7093
  console.log(result.message);
7027
7094
  if (!result.success) {