@proletariat/cli 0.3.23 → 0.3.24

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 (171) hide show
  1. package/dist/commands/action/create.js +1 -1
  2. package/dist/commands/agent/{temp/cleanup.d.ts → cleanup.d.ts} +1 -1
  3. package/dist/commands/agent/{temp/cleanup.js → cleanup.js} +4 -4
  4. package/dist/commands/agent/index.js +8 -8
  5. package/dist/commands/branch/create.js +2 -2
  6. package/dist/commands/epic/create.d.ts +1 -0
  7. package/dist/commands/epic/create.js +39 -2
  8. package/dist/commands/epic/index.js +2 -2
  9. package/dist/commands/{epic/link/remove.d.ts → link/create.d.ts} +6 -7
  10. package/dist/commands/link/create.js +141 -0
  11. package/dist/commands/{epic/link/relates.d.ts → link/index.d.ts} +4 -5
  12. package/dist/commands/link/index.js +87 -0
  13. package/dist/commands/{epic/link/duplicates.d.ts → link/list.d.ts} +7 -4
  14. package/dist/commands/link/list.js +182 -0
  15. package/dist/commands/{spec/link → link}/remove.d.ts +4 -5
  16. package/dist/commands/link/remove.js +120 -0
  17. package/dist/commands/mcp-server.d.ts +22 -0
  18. package/dist/commands/mcp-server.js +98 -0
  19. package/dist/commands/phase/create.js +1 -1
  20. package/dist/commands/project/create.d.ts +1 -0
  21. package/dist/commands/project/create.js +38 -4
  22. package/dist/commands/spec/create.d.ts +1 -0
  23. package/dist/commands/spec/create.js +43 -2
  24. package/dist/commands/spec/index.js +2 -2
  25. package/dist/commands/{agent/staff → staff}/add.js +10 -10
  26. package/dist/commands/{agent/staff → staff}/index.d.ts +1 -1
  27. package/dist/commands/{agent/staff → staff}/index.js +7 -7
  28. package/dist/commands/{agent/staff → staff}/list.js +3 -3
  29. package/dist/commands/{agent/staff → staff}/remove.d.ts +1 -1
  30. package/dist/commands/{agent/staff → staff}/remove.js +8 -8
  31. package/dist/commands/{ticket/template → template}/apply.d.ts +8 -6
  32. package/dist/commands/template/apply.js +262 -0
  33. package/dist/commands/{ticket/template → template}/create.d.ts +5 -6
  34. package/dist/commands/template/create.js +238 -0
  35. package/dist/commands/template/index.js +48 -36
  36. package/dist/commands/{ticket/template → template}/save.d.ts +2 -2
  37. package/dist/commands/template/save.js +104 -0
  38. package/dist/commands/{phase/template → template}/update.d.ts +2 -2
  39. package/dist/commands/template/update.js +99 -0
  40. package/dist/commands/{agent/themes → theme}/add-names.d.ts +1 -1
  41. package/dist/commands/{agent/themes → theme}/add-names.js +6 -6
  42. package/dist/commands/{agent/themes → theme}/create.d.ts +1 -1
  43. package/dist/commands/{agent/themes → theme}/create.js +5 -5
  44. package/dist/commands/{agent/themes → theme}/index.d.ts +1 -1
  45. package/dist/commands/{agent/themes → theme}/index.js +10 -10
  46. package/dist/commands/{agent/themes → theme}/list.d.ts +1 -1
  47. package/dist/commands/{agent/themes → theme}/list.js +5 -5
  48. package/dist/commands/{agent/themes → theme}/set.d.ts +1 -1
  49. package/dist/commands/{agent/themes → theme}/set.js +7 -7
  50. package/dist/commands/ticket/create.d.ts +1 -0
  51. package/dist/commands/ticket/create.js +54 -2
  52. package/dist/commands/ticket/index.js +6 -6
  53. package/dist/commands/work/spawn.js +1 -1
  54. package/dist/lib/mcp/helpers.d.ts +43 -0
  55. package/dist/lib/mcp/helpers.js +57 -0
  56. package/dist/lib/mcp/index.d.ts +6 -0
  57. package/dist/lib/mcp/index.js +6 -0
  58. package/dist/lib/mcp/tools/action.d.ts +6 -0
  59. package/dist/lib/mcp/tools/action.js +88 -0
  60. package/dist/lib/mcp/tools/board.d.ts +6 -0
  61. package/dist/lib/mcp/tools/board.js +139 -0
  62. package/dist/lib/mcp/tools/category.d.ts +6 -0
  63. package/dist/lib/mcp/tools/category.js +84 -0
  64. package/dist/lib/mcp/tools/cli-passthrough.d.ts +15 -0
  65. package/dist/lib/mcp/tools/cli-passthrough.js +333 -0
  66. package/dist/lib/mcp/tools/epic.d.ts +6 -0
  67. package/dist/lib/mcp/tools/epic.js +178 -0
  68. package/dist/lib/mcp/tools/index.d.ts +18 -0
  69. package/dist/lib/mcp/tools/index.js +19 -0
  70. package/dist/lib/mcp/tools/phase.d.ts +6 -0
  71. package/dist/lib/mcp/tools/phase.js +131 -0
  72. package/dist/lib/mcp/tools/project.d.ts +6 -0
  73. package/dist/lib/mcp/tools/project.js +196 -0
  74. package/dist/lib/mcp/tools/roadmap.d.ts +6 -0
  75. package/dist/lib/mcp/tools/roadmap.js +123 -0
  76. package/dist/lib/mcp/tools/spec.d.ts +6 -0
  77. package/dist/lib/mcp/tools/spec.js +196 -0
  78. package/dist/lib/mcp/tools/status.d.ts +6 -0
  79. package/dist/lib/mcp/tools/status.js +109 -0
  80. package/dist/lib/mcp/tools/template.d.ts +6 -0
  81. package/dist/lib/mcp/tools/template.js +107 -0
  82. package/dist/lib/mcp/tools/ticket.d.ts +6 -0
  83. package/dist/lib/mcp/tools/ticket.js +393 -0
  84. package/dist/lib/mcp/tools/view.d.ts +6 -0
  85. package/dist/lib/mcp/tools/view.js +76 -0
  86. package/dist/lib/mcp/tools/work.d.ts +6 -0
  87. package/dist/lib/mcp/tools/work.js +132 -0
  88. package/dist/lib/mcp/tools/workflow.d.ts +6 -0
  89. package/dist/lib/mcp/tools/workflow.js +95 -0
  90. package/dist/lib/mcp/types.d.ts +17 -0
  91. package/dist/lib/mcp/types.js +4 -0
  92. package/dist/lib/prompt-json.d.ts +52 -1
  93. package/dist/lib/prompt-json.js +45 -0
  94. package/oclif.manifest.json +3660 -5564
  95. package/package.json +6 -4
  96. package/dist/commands/agent/temp/index.d.ts +0 -14
  97. package/dist/commands/agent/temp/index.js +0 -85
  98. package/dist/commands/agent/temp/list.d.ts +0 -7
  99. package/dist/commands/agent/temp/list.js +0 -108
  100. package/dist/commands/epic/link/block.d.ts +0 -14
  101. package/dist/commands/epic/link/block.js +0 -81
  102. package/dist/commands/epic/link/duplicates.js +0 -68
  103. package/dist/commands/epic/link/index.d.ts +0 -19
  104. package/dist/commands/epic/link/index.js +0 -272
  105. package/dist/commands/epic/link/relates.js +0 -68
  106. package/dist/commands/epic/link/remove.js +0 -93
  107. package/dist/commands/phase/template/apply.d.ts +0 -17
  108. package/dist/commands/phase/template/apply.js +0 -108
  109. package/dist/commands/phase/template/create.d.ts +0 -17
  110. package/dist/commands/phase/template/create.js +0 -104
  111. package/dist/commands/phase/template/delete.d.ts +0 -17
  112. package/dist/commands/phase/template/delete.js +0 -100
  113. package/dist/commands/phase/template/index.d.ts +0 -15
  114. package/dist/commands/phase/template/index.js +0 -130
  115. package/dist/commands/phase/template/list.d.ts +0 -16
  116. package/dist/commands/phase/template/list.js +0 -97
  117. package/dist/commands/phase/template/update.js +0 -89
  118. package/dist/commands/spec/link/depends.d.ts +0 -14
  119. package/dist/commands/spec/link/depends.js +0 -64
  120. package/dist/commands/spec/link/duplicates.d.ts +0 -14
  121. package/dist/commands/spec/link/duplicates.js +0 -63
  122. package/dist/commands/spec/link/index.d.ts +0 -19
  123. package/dist/commands/spec/link/index.js +0 -207
  124. package/dist/commands/spec/link/relates.d.ts +0 -14
  125. package/dist/commands/spec/link/relates.js +0 -63
  126. package/dist/commands/spec/link/remove.js +0 -96
  127. package/dist/commands/template/phase/apply.d.ts +0 -14
  128. package/dist/commands/template/phase/apply.js +0 -43
  129. package/dist/commands/template/phase/create.d.ts +0 -13
  130. package/dist/commands/template/phase/create.js +0 -38
  131. package/dist/commands/template/phase/delete.d.ts +0 -13
  132. package/dist/commands/template/phase/delete.js +0 -36
  133. package/dist/commands/template/phase/index.d.ts +0 -10
  134. package/dist/commands/template/phase/index.js +0 -63
  135. package/dist/commands/template/phase/list.d.ts +0 -11
  136. package/dist/commands/template/phase/list.js +0 -36
  137. package/dist/commands/template/phase/update.d.ts +0 -14
  138. package/dist/commands/template/phase/update.js +0 -43
  139. package/dist/commands/template/ticket/apply.d.ts +0 -17
  140. package/dist/commands/template/ticket/apply.js +0 -60
  141. package/dist/commands/template/ticket/create.d.ts +0 -20
  142. package/dist/commands/template/ticket/create.js +0 -89
  143. package/dist/commands/template/ticket/delete.d.ts +0 -13
  144. package/dist/commands/template/ticket/delete.js +0 -38
  145. package/dist/commands/template/ticket/index.d.ts +0 -10
  146. package/dist/commands/template/ticket/index.js +0 -63
  147. package/dist/commands/template/ticket/list.d.ts +0 -11
  148. package/dist/commands/template/ticket/list.js +0 -36
  149. package/dist/commands/template/ticket/save.d.ts +0 -15
  150. package/dist/commands/template/ticket/save.js +0 -46
  151. package/dist/commands/ticket/link/block.d.ts +0 -14
  152. package/dist/commands/ticket/link/block.js +0 -96
  153. package/dist/commands/ticket/link/duplicates.d.ts +0 -14
  154. package/dist/commands/ticket/link/duplicates.js +0 -95
  155. package/dist/commands/ticket/link/index.d.ts +0 -19
  156. package/dist/commands/ticket/link/index.js +0 -256
  157. package/dist/commands/ticket/link/relates.d.ts +0 -14
  158. package/dist/commands/ticket/link/relates.js +0 -95
  159. package/dist/commands/ticket/link/remove.d.ts +0 -16
  160. package/dist/commands/ticket/link/remove.js +0 -132
  161. package/dist/commands/ticket/template/apply.js +0 -252
  162. package/dist/commands/ticket/template/create.js +0 -386
  163. package/dist/commands/ticket/template/delete.d.ts +0 -17
  164. package/dist/commands/ticket/template/delete.js +0 -94
  165. package/dist/commands/ticket/template/index.d.ts +0 -15
  166. package/dist/commands/ticket/template/index.js +0 -120
  167. package/dist/commands/ticket/template/list.d.ts +0 -16
  168. package/dist/commands/ticket/template/list.js +0 -112
  169. package/dist/commands/ticket/template/save.js +0 -163
  170. /package/dist/commands/{agent/staff → staff}/add.d.ts +0 -0
  171. /package/dist/commands/{agent/staff → staff}/list.d.ts +0 -0
@@ -1,11 +1,11 @@
1
1
  import { Command, Flags } from '@oclif/core';
2
2
  import inquirer from 'inquirer';
3
3
  import chalk from 'chalk';
4
- import { getWorkspaceInfo } from '../../../lib/agents/commands.js';
5
- import { ensureBuiltinThemes } from '../../../lib/themes.js';
6
- import { getThemes, getAvailableThemeNames } from '../../../lib/database/index.js';
7
- import { shouldOutputJson, outputPromptAsJson, createMetadata, buildPromptConfig, } from '../../../lib/prompt-json.js';
8
- export default class Themes extends Command {
4
+ import { getWorkspaceInfo } from '../../lib/agents/commands.js';
5
+ import { ensureBuiltinThemes } from '../../lib/themes.js';
6
+ import { getThemes, getAvailableThemeNames } from '../../lib/database/index.js';
7
+ import { shouldOutputJson, outputPromptAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
8
+ export default class Theme extends Command {
9
9
  static description = 'Manage agent naming themes';
10
10
  static examples = [
11
11
  '<%= config.bin %> <%= command.id %> list',
@@ -21,15 +21,15 @@ export default class Themes extends Command {
21
21
  }),
22
22
  };
23
23
  async run() {
24
- const { flags } = await this.parse(Themes);
24
+ const { flags } = await this.parse(Theme);
25
25
  // Check if JSON output mode is active
26
26
  const jsonMode = shouldOutputJson(flags);
27
27
  // Define choices once, use for both JSON and interactive modes
28
28
  // Each choice includes the full command for AI agents to execute
29
29
  const menuChoices = [
30
- { id: 'list', name: 'List themes', command: 'prlt agent themes list --format json' },
31
- { id: 'create', name: 'Create a new theme', command: 'prlt agent themes create --machine' },
32
- { id: 'add-names', name: 'Add names to a theme', command: 'prlt agent themes add-names --machine' },
30
+ { id: 'list', name: 'List themes', command: 'prlt theme list --format json' },
31
+ { id: 'create', name: 'Create a new theme', command: 'prlt theme create --machine' },
32
+ { id: 'add-names', name: 'Add names to a theme', command: 'prlt theme add-names --machine' },
33
33
  { id: 'cancel', name: 'Cancel', command: '' },
34
34
  ];
35
35
  const message = 'What would you like to do?';
@@ -39,7 +39,7 @@ export default class Themes extends Command {
39
39
  name: c.name,
40
40
  value: c.id,
41
41
  command: c.command,
42
- }))), createMetadata('agent themes', flags));
42
+ }))), createMetadata('theme', flags));
43
43
  return;
44
44
  }
45
45
  this.log(chalk.bold('\nAgent Themes'));
@@ -1,5 +1,5 @@
1
1
  import { Command } from '@oclif/core';
2
- export default class ThemesList extends Command {
2
+ export default class ThemeList extends Command {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  run(): Promise<void>;
@@ -1,9 +1,9 @@
1
1
  import { Command } from '@oclif/core';
2
2
  import chalk from 'chalk';
3
- import { getWorkspaceInfo } from '../../../lib/agents/commands.js';
4
- import { ensureBuiltinThemes } from '../../../lib/themes.js';
5
- import { getThemes, getThemeNames, getAvailableThemeNames } from '../../../lib/database/index.js';
6
- export default class ThemesList extends Command {
3
+ import { getWorkspaceInfo } from '../../lib/agents/commands.js';
4
+ import { ensureBuiltinThemes } from '../../lib/themes.js';
5
+ import { getThemes, getThemeNames, getAvailableThemeNames } from '../../lib/database/index.js';
6
+ export default class ThemeList extends Command {
7
7
  static description = 'List available agent themes';
8
8
  static examples = [
9
9
  '<%= config.bin %> <%= command.id %>',
@@ -32,7 +32,7 @@ export default class ThemesList extends Command {
32
32
  this.log(chalk.gray(` Names: ${chalk.green(availableNames.length + ' available')}, ${chalk.yellow(inUse + ' in use')}`));
33
33
  this.log('');
34
34
  }
35
- this.log(chalk.blue('Use: prlt agent add --theme <theme-id>'));
35
+ this.log(chalk.blue('Use: prlt staff add --theme <theme-id>'));
36
36
  }
37
37
  catch (error) {
38
38
  this.error(error instanceof Error ? error.message : String(error));
@@ -1,5 +1,5 @@
1
1
  import { Command } from '@oclif/core';
2
- export default class ThemesSet extends Command {
2
+ export default class ThemeSet extends Command {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static args: {
@@ -1,11 +1,11 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
2
  import chalk from 'chalk';
3
3
  import inquirer from 'inquirer';
4
- import { getWorkspaceInfo } from '../../../lib/agents/commands.js';
5
- import { ensureBuiltinThemes } from '../../../lib/themes.js';
6
- import { getThemes, getAvailableThemeNames, setActiveTheme, getActiveTheme } from '../../../lib/database/index.js';
7
- import { shouldOutputJson, outputPromptAsJson, createMetadata, buildPromptConfig, } from '../../../lib/prompt-json.js';
8
- export default class ThemesSet extends Command {
4
+ import { getWorkspaceInfo } from '../../lib/agents/commands.js';
5
+ import { ensureBuiltinThemes } from '../../lib/themes.js';
6
+ import { getThemes, getAvailableThemeNames, setActiveTheme, getActiveTheme } from '../../lib/database/index.js';
7
+ import { shouldOutputJson, outputPromptAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
8
+ export default class ThemeSet extends Command {
9
9
  static description = 'Set the active theme for this workspace';
10
10
  static examples = [
11
11
  '<%= config.bin %> <%= command.id %> billionaires',
@@ -26,7 +26,7 @@ export default class ThemesSet extends Command {
26
26
  }),
27
27
  };
28
28
  async run() {
29
- const { args, flags } = await this.parse(ThemesSet);
29
+ const { args, flags } = await this.parse(ThemeSet);
30
30
  // Check if JSON output mode is active
31
31
  const jsonMode = shouldOutputJson(flags);
32
32
  try {
@@ -47,7 +47,7 @@ export default class ThemesSet extends Command {
47
47
  value: t.id
48
48
  };
49
49
  });
50
- outputPromptAsJson(buildPromptConfig('list', 'theme', 'Select theme for this workspace:', themeChoices), createMetadata('agent themes set', flags));
50
+ outputPromptAsJson(buildPromptConfig('list', 'theme', 'Select theme for this workspace:', themeChoices), createMetadata('theme set', flags));
51
51
  return;
52
52
  }
53
53
  const choices = themes.map(t => {
@@ -14,6 +14,7 @@ export default class TicketCreate extends PMOCommand {
14
14
  epic: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
15
15
  template: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
16
16
  labels: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
+ 'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
18
  project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
19
  };
19
20
  execute(): Promise<void>;
@@ -4,7 +4,7 @@ import { autoExportToBoard, PMOCommand, pmoBaseFlags } from '../../lib/pmo/index
4
4
  import { styles } from '../../lib/styles.js';
5
5
  import { updateEpicTicketsSection } from '../../lib/pmo/epic-files.js';
6
6
  import { PRIORITIES, PRIORITY_LABELS } from '../../lib/pmo/types.js';
7
- import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
7
+ import { shouldOutputJson, outputErrorAsJson, outputDryRunSuccessAsJson, outputDryRunErrorsAsJson, createMetadata, } from '../../lib/prompt-json.js';
8
8
  import { FlagResolver } from '../../lib/flags/index.js';
9
9
  export default class TicketCreate extends PMOCommand {
10
10
  static description = 'Create a new ticket on the PMO board';
@@ -15,6 +15,7 @@ export default class TicketCreate extends PMOCommand {
15
15
  '<%= config.bin %> <%= command.id %> --project mobile-app -t "New feature"',
16
16
  '<%= config.bin %> <%= command.id %> --epic EPIC-001 -t "Implement auth flow"',
17
17
  '<%= config.bin %> <%= command.id %> --json # Output column choices as JSON',
18
+ '<%= config.bin %> <%= command.id %> --title "Test" -P PROJ-001 --dry-run --json # Validate without creating',
18
19
  ];
19
20
  static flags = {
20
21
  ...pmoBaseFlags,
@@ -26,7 +27,7 @@ export default class TicketCreate extends PMOCommand {
26
27
  }),
27
28
  title: Flags.string({
28
29
  char: 't',
29
- description: 'Ticket title',
30
+ description: 'Ticket title [required for non-interactive]',
30
31
  }),
31
32
  column: Flags.string({
32
33
  char: 'c',
@@ -64,6 +65,10 @@ export default class TicketCreate extends PMOCommand {
64
65
  char: 'l',
65
66
  description: 'Labels (comma-separated)',
66
67
  }),
68
+ 'dry-run': Flags.boolean({
69
+ description: 'Validate inputs without creating ticket (use with --json for structured output)',
70
+ default: false,
71
+ }),
67
72
  };
68
73
  async execute() {
69
74
  const { flags } = await this.parse(TicketCreate);
@@ -171,8 +176,55 @@ export default class TicketCreate extends PMOCommand {
171
176
  }
172
177
  // Validate status/column
173
178
  if (!columns.includes(ticketData.statusName)) {
179
+ if (flags['dry-run']) {
180
+ if (jsonMode) {
181
+ outputDryRunErrorsAsJson([{ field: 'column', error: `Invalid column "${ticketData.statusName}". Available: ${columns.join(', ')}` }], createMetadata('ticket create', flags));
182
+ }
183
+ this.error(`Invalid column "${ticketData.statusName}". Available columns: ${columns.join(', ')}`);
184
+ }
174
185
  this.error(`Invalid column "${ticketData.statusName}". Available columns: ${columns.join(', ')}`);
175
186
  }
187
+ // Handle dry-run: show what would be created without actually creating
188
+ if (flags['dry-run']) {
189
+ const wouldCreate = {
190
+ title: ticketData.title,
191
+ project: projectId,
192
+ column: ticketData.statusName,
193
+ ...(ticketData.priority && { priority: ticketData.priority }),
194
+ ...(ticketData.category && { category: ticketData.category }),
195
+ ...(ticketData.description && { description: ticketData.description }),
196
+ ...(ticketData.epicId && { epic: ticketData.epicId }),
197
+ ...(ticketData.labels && ticketData.labels.length > 0 && { labels: ticketData.labels }),
198
+ };
199
+ if (jsonMode) {
200
+ outputDryRunSuccessAsJson('ticket', wouldCreate, createMetadata('ticket create', flags));
201
+ }
202
+ // Human-readable dry-run output
203
+ this.log(styles.warning('\n[DRY RUN] Would create ticket:'));
204
+ this.log(styles.muted(` Title: ${ticketData.title}`));
205
+ this.log(styles.muted(` Project: ${projectName}`));
206
+ this.log(styles.muted(` Column: ${ticketData.statusName}`));
207
+ if (ticketData.priority) {
208
+ this.log(styles.muted(` Priority: ${ticketData.priority}`));
209
+ }
210
+ if (ticketData.category) {
211
+ this.log(styles.muted(` Category: ${ticketData.category}`));
212
+ }
213
+ if (ticketData.epicId) {
214
+ this.log(styles.muted(` Epic: ${ticketData.epicId}`));
215
+ }
216
+ if (ticketData.labels && ticketData.labels.length > 0) {
217
+ this.log(styles.muted(` Labels: ${ticketData.labels.join(', ')}`));
218
+ }
219
+ if (template) {
220
+ this.log(styles.muted(` Template: ${template.name}`));
221
+ if (template.suggestedSubtasks.length > 0) {
222
+ this.log(styles.muted(` Subtasks: ${template.suggestedSubtasks.length} would be created`));
223
+ }
224
+ }
225
+ this.log(styles.muted('\n(No ticket was created)'));
226
+ return;
227
+ }
176
228
  const ticket = await this.storage.createTicket(projectId, {
177
229
  id: ticketData.id,
178
230
  title: ticketData.title,
@@ -27,7 +27,7 @@ export default class Ticket extends PMOCommand {
27
27
  // Each choice includes the full command for AI agents to execute
28
28
  const menuChoices = [
29
29
  { name: 'Create new ticket', value: 'create', command: 'prlt ticket create --json' },
30
- { name: 'Create from template', value: 'template', command: 'prlt ticket template apply --json' },
30
+ { name: 'Create from template', value: 'template', command: 'prlt template apply --type ticket --json' },
31
31
  { name: 'List all tickets', value: 'list', command: 'prlt ticket list --format json' },
32
32
  { name: 'View ticket details', value: 'view', command: 'prlt ticket view --json' },
33
33
  { name: 'Edit ticket', value: 'edit', command: 'prlt ticket edit --json' },
@@ -35,8 +35,8 @@ export default class Ticket extends PMOCommand {
35
35
  { name: 'Move to different project', value: 'project', command: 'prlt ticket project --json' },
36
36
  { name: 'Assign to epic', value: 'epic', command: 'prlt ticket epic --json' },
37
37
  { name: 'Assign to spec', value: 'spec', command: 'prlt ticket spec --json' },
38
- { name: 'Manage dependencies', value: 'link', command: 'prlt ticket link --json' },
39
- { name: 'Manage templates', value: 'templates', command: 'prlt ticket template --json' },
38
+ { name: 'Manage dependencies', value: 'link', command: 'prlt link list --json' },
39
+ { name: 'Manage templates', value: 'templates', command: 'prlt template --json' },
40
40
  { name: 'Delete ticket', value: 'delete', command: 'prlt ticket delete --json' },
41
41
  { name: 'Cancel', value: 'cancel' },
42
42
  ];
@@ -68,7 +68,7 @@ export default class Ticket extends PMOCommand {
68
68
  await this.config.runCommand('ticket:create', []);
69
69
  break;
70
70
  case 'template':
71
- await this.config.runCommand('ticket:template:apply', []);
71
+ await this.config.runCommand('template:apply', ['--type', 'ticket']);
72
72
  break;
73
73
  case 'list':
74
74
  await this.config.runCommand('ticket:list', []);
@@ -92,10 +92,10 @@ export default class Ticket extends PMOCommand {
92
92
  await this.config.runCommand('ticket:spec', []);
93
93
  break;
94
94
  case 'link':
95
- await this.config.runCommand('ticket:link', []);
95
+ await this.config.runCommand('link', []);
96
96
  break;
97
97
  case 'templates':
98
- await this.config.runCommand('ticket:template', []);
98
+ await this.config.runCommand('template', []);
99
99
  break;
100
100
  case 'delete':
101
101
  await this.config.runCommand('ticket:delete', []);
@@ -39,7 +39,7 @@ export default class WorkSpawn extends PMOCommand {
39
39
  }),
40
40
  column: Flags.string({
41
41
  char: 'c',
42
- description: 'Column name to spawn tickets from (used with --all)',
42
+ description: 'Column name to spawn tickets from [required for non-interactive with --all]',
43
43
  }),
44
44
  strategy: Flags.string({
45
45
  char: 's',
@@ -0,0 +1,43 @@
1
+ /**
2
+ * MCP Helper Functions
3
+ */
4
+ import type { Ticket } from '../pmo/types.js';
5
+ import type { McpToolResult } from './types.js';
6
+ export declare function formatTicket(t: Ticket): {
7
+ id: string;
8
+ title: string;
9
+ priority: string | undefined;
10
+ category: string | undefined;
11
+ statusName: string | undefined;
12
+ statusCategory: import("../pmo/types.js").StateCategory | undefined;
13
+ projectId: string | undefined;
14
+ assignee: string | undefined;
15
+ owner: string | undefined;
16
+ branch: string | undefined;
17
+ epicId: string | undefined;
18
+ };
19
+ export declare function formatTicketFull(t: Ticket): {
20
+ description: string | undefined;
21
+ subtasks: import("../pmo/types.js").Subtask[];
22
+ labels: string[];
23
+ metadata: Record<string, string>;
24
+ blockedBy: string[] | undefined;
25
+ acceptanceCriteria: import("../pmo/types.js").AcceptanceCriterion[] | undefined;
26
+ specId: string | undefined;
27
+ createdAt: string;
28
+ updatedAt: string;
29
+ id: string;
30
+ title: string;
31
+ priority: string | undefined;
32
+ category: string | undefined;
33
+ statusName: string | undefined;
34
+ statusCategory: import("../pmo/types.js").StateCategory | undefined;
35
+ projectId: string | undefined;
36
+ assignee: string | undefined;
37
+ owner: string | undefined;
38
+ branch: string | undefined;
39
+ epicId: string | undefined;
40
+ };
41
+ export declare function successResponse(data: Record<string, unknown>): McpToolResult;
42
+ export declare function errorResponse(error: unknown): McpToolResult;
43
+ export declare function textResponse(text: string): McpToolResult;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * MCP Helper Functions
3
+ */
4
+ export function formatTicket(t) {
5
+ return {
6
+ id: t.id,
7
+ title: t.title,
8
+ priority: t.priority,
9
+ category: t.category,
10
+ statusName: t.statusName,
11
+ statusCategory: t.statusCategory,
12
+ projectId: t.projectId,
13
+ assignee: t.assignee,
14
+ owner: t.owner,
15
+ branch: t.branch,
16
+ epicId: t.epicId,
17
+ };
18
+ }
19
+ export function formatTicketFull(t) {
20
+ return {
21
+ ...formatTicket(t),
22
+ description: t.description,
23
+ subtasks: t.subtasks,
24
+ labels: t.labels,
25
+ metadata: t.metadata,
26
+ blockedBy: t.blockedBy,
27
+ acceptanceCriteria: t.acceptanceCriteria,
28
+ specId: t.specId,
29
+ createdAt: t.createdAt.toISOString(),
30
+ updatedAt: t.updatedAt.toISOString(),
31
+ };
32
+ }
33
+ export function successResponse(data) {
34
+ return {
35
+ content: [{
36
+ type: 'text',
37
+ text: JSON.stringify({ success: true, ...data }, null, 2),
38
+ }],
39
+ };
40
+ }
41
+ export function errorResponse(error) {
42
+ return {
43
+ content: [{
44
+ type: 'text',
45
+ text: JSON.stringify({
46
+ success: false,
47
+ error: error instanceof Error ? error.message : 'Unknown error',
48
+ }),
49
+ }],
50
+ isError: true,
51
+ };
52
+ }
53
+ export function textResponse(text) {
54
+ return {
55
+ content: [{ type: 'text', text }],
56
+ };
57
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * MCP Library - Main exports
3
+ */
4
+ export * from './types.js';
5
+ export * from './helpers.js';
6
+ export * from './tools/index.js';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * MCP Library - Main exports
3
+ */
4
+ export * from './types.js';
5
+ export * from './helpers.js';
6
+ export * from './tools/index.js';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * MCP Action Tools
3
+ */
4
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import type { McpToolContext } from '../types.js';
6
+ export declare function registerActionTools(server: McpServer, ctx: McpToolContext): void;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * MCP Action Tools
3
+ */
4
+ import { z } from 'zod';
5
+ import { errorResponse } from '../helpers.js';
6
+ export function registerActionTools(server, ctx) {
7
+ server.tool('action_list', 'List work actions', { include_builtin: z.boolean().optional() }, async (params) => {
8
+ try {
9
+ const actions = await ctx.storage.listActions({
10
+ isBuiltin: params.include_builtin ? undefined : false,
11
+ });
12
+ return {
13
+ content: [{
14
+ type: 'text',
15
+ text: JSON.stringify({
16
+ success: true,
17
+ actions: actions.map((a) => ({
18
+ id: a.id,
19
+ name: a.name,
20
+ description: a.description,
21
+ modifiesCode: a.modifiesCode,
22
+ isBuiltin: a.isBuiltin,
23
+ })),
24
+ }, null, 2),
25
+ }],
26
+ };
27
+ }
28
+ catch (error) {
29
+ return errorResponse(error);
30
+ }
31
+ });
32
+ server.tool('action_show', 'Get action details', { id: z.string().describe('Action ID') }, async (params) => {
33
+ try {
34
+ const action = await ctx.storage.getAction(params.id);
35
+ if (!action)
36
+ throw new Error(`Action not found: ${params.id}`);
37
+ return {
38
+ content: [{
39
+ type: 'text',
40
+ text: JSON.stringify({ success: true, action }, null, 2),
41
+ }],
42
+ };
43
+ }
44
+ catch (error) {
45
+ return errorResponse(error);
46
+ }
47
+ });
48
+ server.tool('action_create', 'Create a work action', {
49
+ name: z.string().describe('Action name'),
50
+ prompt: z.string().describe('Start prompt'),
51
+ description: z.string().optional(),
52
+ end_prompt: z.string().optional(),
53
+ modifies_code: z.boolean().optional(),
54
+ }, async (params) => {
55
+ try {
56
+ const action = await ctx.storage.createAction({
57
+ name: params.name,
58
+ prompt: params.prompt,
59
+ description: params.description,
60
+ endPrompt: params.end_prompt,
61
+ modifiesCode: params.modifies_code ?? true,
62
+ });
63
+ return {
64
+ content: [{
65
+ type: 'text',
66
+ text: JSON.stringify({ success: true, action: { id: action.id, name: action.name } }, null, 2),
67
+ }],
68
+ };
69
+ }
70
+ catch (error) {
71
+ return errorResponse(error);
72
+ }
73
+ });
74
+ server.tool('action_delete', 'Delete an action', { id: z.string().describe('Action ID') }, async (params) => {
75
+ try {
76
+ await ctx.storage.deleteAction(params.id);
77
+ return {
78
+ content: [{
79
+ type: 'text',
80
+ text: JSON.stringify({ success: true, message: 'Action deleted' }, null, 2),
81
+ }],
82
+ };
83
+ }
84
+ catch (error) {
85
+ return errorResponse(error);
86
+ }
87
+ });
88
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * MCP Board Tools
3
+ */
4
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import type { McpToolContext } from '../types.js';
6
+ export declare function registerBoardTools(server: McpServer, ctx: McpToolContext): void;
@@ -0,0 +1,139 @@
1
+ /**
2
+ * MCP Board Tools
3
+ */
4
+ import { z } from 'zod';
5
+ import { errorResponse } from '../helpers.js';
6
+ export function registerBoardTools(server, ctx) {
7
+ server.tool('board_show', 'Show the kanban board', { project: z.string().optional().describe('Project ID') }, async (params) => {
8
+ try {
9
+ let projectId = params.project;
10
+ if (!projectId) {
11
+ const projects = await ctx.storage.listProjects();
12
+ if (projects.length === 0)
13
+ throw new Error('No projects found');
14
+ projectId = projects[0].id;
15
+ }
16
+ const board = await ctx.storage.getBoard(projectId);
17
+ return {
18
+ content: [{
19
+ type: 'text',
20
+ text: JSON.stringify({
21
+ success: true,
22
+ board: {
23
+ id: board.id,
24
+ name: board.name,
25
+ columns: board.columns.map((col) => ({
26
+ name: col.name,
27
+ position: col.position,
28
+ ticketCount: col.tickets.length,
29
+ tickets: col.tickets.map((t) => ({
30
+ id: t.id,
31
+ title: t.title,
32
+ priority: t.priority,
33
+ assignee: t.assignee,
34
+ })),
35
+ })),
36
+ updatedAt: board.updatedAt.toISOString(),
37
+ },
38
+ }, null, 2),
39
+ }],
40
+ };
41
+ }
42
+ catch (error) {
43
+ return errorResponse(error);
44
+ }
45
+ });
46
+ server.tool('board_columns', 'Get column names for a project', { project: z.string().optional().describe('Project ID') }, async (params) => {
47
+ try {
48
+ let projectId = params.project;
49
+ if (!projectId) {
50
+ const projects = await ctx.storage.listProjects();
51
+ if (projects.length === 0)
52
+ throw new Error('No projects found');
53
+ projectId = projects[0].id;
54
+ }
55
+ const columns = ctx.storage.getColumnNames(projectId);
56
+ return {
57
+ content: [{
58
+ type: 'text',
59
+ text: JSON.stringify({ success: true, projectId, columns }, null, 2),
60
+ }],
61
+ };
62
+ }
63
+ catch (error) {
64
+ return errorResponse(error);
65
+ }
66
+ });
67
+ server.tool('board_create_column', 'Add a new column to the board', {
68
+ project: z.string().describe('Project ID'),
69
+ name: z.string().describe('Column name'),
70
+ position: z.number().optional().describe('Position'),
71
+ }, async (params) => {
72
+ try {
73
+ const column = await ctx.storage.createColumn(params.project, params.name, params.position);
74
+ return {
75
+ content: [{
76
+ type: 'text',
77
+ text: JSON.stringify({ success: true, column: { id: column.id, name: column.name, position: column.position } }, null, 2),
78
+ }],
79
+ };
80
+ }
81
+ catch (error) {
82
+ return errorResponse(error);
83
+ }
84
+ });
85
+ server.tool('board_rename_column', 'Rename a column', {
86
+ project: z.string().describe('Project ID'),
87
+ column_id: z.string().describe('Column ID'),
88
+ name: z.string().describe('New name'),
89
+ }, async (params) => {
90
+ try {
91
+ const column = await ctx.storage.renameColumn(params.project, params.column_id, params.name);
92
+ return {
93
+ content: [{
94
+ type: 'text',
95
+ text: JSON.stringify({ success: true, column: { id: column.id, name: column.name } }, null, 2),
96
+ }],
97
+ };
98
+ }
99
+ catch (error) {
100
+ return errorResponse(error);
101
+ }
102
+ });
103
+ server.tool('board_move_column', 'Reorder a column', {
104
+ project: z.string().describe('Project ID'),
105
+ column_id: z.string().describe('Column ID'),
106
+ position: z.number().describe('New position'),
107
+ }, async (params) => {
108
+ try {
109
+ const column = await ctx.storage.moveColumn(params.project, params.column_id, params.position);
110
+ return {
111
+ content: [{
112
+ type: 'text',
113
+ text: JSON.stringify({ success: true, column: { id: column.id, name: column.name, position: column.position } }, null, 2),
114
+ }],
115
+ };
116
+ }
117
+ catch (error) {
118
+ return errorResponse(error);
119
+ }
120
+ });
121
+ server.tool('board_delete_column', 'Delete a column', {
122
+ project: z.string().describe('Project ID'),
123
+ column_id: z.string().describe('Column ID'),
124
+ cascade: z.boolean().optional().describe('Delete tickets in column'),
125
+ }, async (params) => {
126
+ try {
127
+ await ctx.storage.deleteColumn(params.project, params.column_id, params.cascade);
128
+ return {
129
+ content: [{
130
+ type: 'text',
131
+ text: JSON.stringify({ success: true, message: 'Column deleted' }, null, 2),
132
+ }],
133
+ };
134
+ }
135
+ catch (error) {
136
+ return errorResponse(error);
137
+ }
138
+ });
139
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * MCP Category Tools
3
+ */
4
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import type { McpToolContext } from '../types.js';
6
+ export declare function registerCategoryTools(server: McpServer, ctx: McpToolContext): void;