@proletariat/cli 0.3.22 → 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.
- package/LICENSE +190 -21
- package/README.md +7 -7
- package/dist/commands/action/create.js +1 -1
- package/dist/commands/agent/{temp/cleanup.d.ts → cleanup.d.ts} +1 -1
- package/dist/commands/agent/{temp/cleanup.js → cleanup.js} +4 -4
- package/dist/commands/agent/index.js +8 -8
- package/dist/commands/branch/create.js +2 -2
- package/dist/commands/epic/create.d.ts +1 -0
- package/dist/commands/epic/create.js +39 -2
- package/dist/commands/epic/index.js +2 -2
- package/dist/commands/{epic/link/remove.d.ts → link/create.d.ts} +6 -7
- package/dist/commands/link/create.js +141 -0
- package/dist/commands/{epic/link/relates.d.ts → link/index.d.ts} +4 -5
- package/dist/commands/link/index.js +87 -0
- package/dist/commands/{epic/link/duplicates.d.ts → link/list.d.ts} +7 -4
- package/dist/commands/link/list.js +182 -0
- package/dist/commands/{spec/link → link}/remove.d.ts +4 -5
- package/dist/commands/link/remove.js +120 -0
- package/dist/commands/mcp-server.d.ts +22 -0
- package/dist/commands/mcp-server.js +98 -0
- package/dist/commands/phase/create.js +1 -1
- package/dist/commands/project/create.d.ts +1 -0
- package/dist/commands/project/create.js +38 -4
- package/dist/commands/spec/create.d.ts +1 -0
- package/dist/commands/spec/create.js +43 -2
- package/dist/commands/spec/index.js +2 -2
- package/dist/commands/{agent/staff → staff}/add.js +10 -10
- package/dist/commands/{agent/staff → staff}/index.d.ts +1 -1
- package/dist/commands/{agent/staff → staff}/index.js +7 -7
- package/dist/commands/{agent/staff → staff}/list.js +3 -3
- package/dist/commands/{agent/staff → staff}/remove.d.ts +1 -1
- package/dist/commands/{agent/staff → staff}/remove.js +8 -8
- package/dist/commands/{ticket/template → template}/apply.d.ts +8 -6
- package/dist/commands/template/apply.js +262 -0
- package/dist/commands/{ticket/template → template}/create.d.ts +5 -6
- package/dist/commands/template/create.js +238 -0
- package/dist/commands/template/index.js +48 -36
- package/dist/commands/{ticket/template → template}/save.d.ts +2 -2
- package/dist/commands/template/save.js +104 -0
- package/dist/commands/{phase/template → template}/update.d.ts +2 -2
- package/dist/commands/template/update.js +99 -0
- package/dist/commands/{agent/themes → theme}/add-names.d.ts +1 -1
- package/dist/commands/{agent/themes → theme}/add-names.js +6 -6
- package/dist/commands/{agent/themes → theme}/create.d.ts +1 -1
- package/dist/commands/{agent/themes → theme}/create.js +5 -5
- package/dist/commands/{agent/themes → theme}/index.d.ts +1 -1
- package/dist/commands/{agent/themes → theme}/index.js +10 -10
- package/dist/commands/{agent/themes → theme}/list.d.ts +1 -1
- package/dist/commands/{agent/themes → theme}/list.js +5 -5
- package/dist/commands/{agent/themes → theme}/set.d.ts +1 -1
- package/dist/commands/{agent/themes → theme}/set.js +7 -7
- package/dist/commands/ticket/create.d.ts +1 -0
- package/dist/commands/ticket/create.js +54 -2
- package/dist/commands/ticket/index.js +6 -6
- package/dist/commands/work/spawn.js +1 -1
- package/dist/lib/mcp/helpers.d.ts +43 -0
- package/dist/lib/mcp/helpers.js +57 -0
- package/dist/lib/mcp/index.d.ts +6 -0
- package/dist/lib/mcp/index.js +6 -0
- package/dist/lib/mcp/tools/action.d.ts +6 -0
- package/dist/lib/mcp/tools/action.js +88 -0
- package/dist/lib/mcp/tools/board.d.ts +6 -0
- package/dist/lib/mcp/tools/board.js +139 -0
- package/dist/lib/mcp/tools/category.d.ts +6 -0
- package/dist/lib/mcp/tools/category.js +84 -0
- package/dist/lib/mcp/tools/cli-passthrough.d.ts +15 -0
- package/dist/lib/mcp/tools/cli-passthrough.js +333 -0
- package/dist/lib/mcp/tools/epic.d.ts +6 -0
- package/dist/lib/mcp/tools/epic.js +178 -0
- package/dist/lib/mcp/tools/index.d.ts +18 -0
- package/dist/lib/mcp/tools/index.js +19 -0
- package/dist/lib/mcp/tools/phase.d.ts +6 -0
- package/dist/lib/mcp/tools/phase.js +131 -0
- package/dist/lib/mcp/tools/project.d.ts +6 -0
- package/dist/lib/mcp/tools/project.js +196 -0
- package/dist/lib/mcp/tools/roadmap.d.ts +6 -0
- package/dist/lib/mcp/tools/roadmap.js +123 -0
- package/dist/lib/mcp/tools/spec.d.ts +6 -0
- package/dist/lib/mcp/tools/spec.js +196 -0
- package/dist/lib/mcp/tools/status.d.ts +6 -0
- package/dist/lib/mcp/tools/status.js +109 -0
- package/dist/lib/mcp/tools/template.d.ts +6 -0
- package/dist/lib/mcp/tools/template.js +107 -0
- package/dist/lib/mcp/tools/ticket.d.ts +6 -0
- package/dist/lib/mcp/tools/ticket.js +393 -0
- package/dist/lib/mcp/tools/view.d.ts +6 -0
- package/dist/lib/mcp/tools/view.js +76 -0
- package/dist/lib/mcp/tools/work.d.ts +6 -0
- package/dist/lib/mcp/tools/work.js +132 -0
- package/dist/lib/mcp/tools/workflow.d.ts +6 -0
- package/dist/lib/mcp/tools/workflow.js +95 -0
- package/dist/lib/mcp/types.d.ts +17 -0
- package/dist/lib/mcp/types.js +4 -0
- package/dist/lib/prompt-json.d.ts +52 -1
- package/dist/lib/prompt-json.js +45 -0
- package/oclif.manifest.json +3553 -5457
- package/package.json +10 -7
- package/dist/commands/agent/temp/index.d.ts +0 -14
- package/dist/commands/agent/temp/index.js +0 -85
- package/dist/commands/agent/temp/list.d.ts +0 -7
- package/dist/commands/agent/temp/list.js +0 -108
- package/dist/commands/epic/link/block.d.ts +0 -14
- package/dist/commands/epic/link/block.js +0 -81
- package/dist/commands/epic/link/duplicates.js +0 -68
- package/dist/commands/epic/link/index.d.ts +0 -19
- package/dist/commands/epic/link/index.js +0 -272
- package/dist/commands/epic/link/relates.js +0 -68
- package/dist/commands/epic/link/remove.js +0 -93
- package/dist/commands/phase/template/apply.d.ts +0 -17
- package/dist/commands/phase/template/apply.js +0 -108
- package/dist/commands/phase/template/create.d.ts +0 -17
- package/dist/commands/phase/template/create.js +0 -104
- package/dist/commands/phase/template/delete.d.ts +0 -17
- package/dist/commands/phase/template/delete.js +0 -100
- package/dist/commands/phase/template/index.d.ts +0 -15
- package/dist/commands/phase/template/index.js +0 -130
- package/dist/commands/phase/template/list.d.ts +0 -16
- package/dist/commands/phase/template/list.js +0 -97
- package/dist/commands/phase/template/update.js +0 -89
- package/dist/commands/spec/link/depends.d.ts +0 -14
- package/dist/commands/spec/link/depends.js +0 -64
- package/dist/commands/spec/link/duplicates.d.ts +0 -14
- package/dist/commands/spec/link/duplicates.js +0 -63
- package/dist/commands/spec/link/index.d.ts +0 -19
- package/dist/commands/spec/link/index.js +0 -207
- package/dist/commands/spec/link/relates.d.ts +0 -14
- package/dist/commands/spec/link/relates.js +0 -63
- package/dist/commands/spec/link/remove.js +0 -96
- package/dist/commands/template/phase/apply.d.ts +0 -14
- package/dist/commands/template/phase/apply.js +0 -43
- package/dist/commands/template/phase/create.d.ts +0 -13
- package/dist/commands/template/phase/create.js +0 -38
- package/dist/commands/template/phase/delete.d.ts +0 -13
- package/dist/commands/template/phase/delete.js +0 -36
- package/dist/commands/template/phase/index.d.ts +0 -10
- package/dist/commands/template/phase/index.js +0 -63
- package/dist/commands/template/phase/list.d.ts +0 -11
- package/dist/commands/template/phase/list.js +0 -36
- package/dist/commands/template/phase/update.d.ts +0 -14
- package/dist/commands/template/phase/update.js +0 -43
- package/dist/commands/template/ticket/apply.d.ts +0 -17
- package/dist/commands/template/ticket/apply.js +0 -60
- package/dist/commands/template/ticket/create.d.ts +0 -20
- package/dist/commands/template/ticket/create.js +0 -89
- package/dist/commands/template/ticket/delete.d.ts +0 -13
- package/dist/commands/template/ticket/delete.js +0 -38
- package/dist/commands/template/ticket/index.d.ts +0 -10
- package/dist/commands/template/ticket/index.js +0 -63
- package/dist/commands/template/ticket/list.d.ts +0 -11
- package/dist/commands/template/ticket/list.js +0 -36
- package/dist/commands/template/ticket/save.d.ts +0 -15
- package/dist/commands/template/ticket/save.js +0 -46
- package/dist/commands/ticket/link/block.d.ts +0 -14
- package/dist/commands/ticket/link/block.js +0 -96
- package/dist/commands/ticket/link/duplicates.d.ts +0 -14
- package/dist/commands/ticket/link/duplicates.js +0 -95
- package/dist/commands/ticket/link/index.d.ts +0 -19
- package/dist/commands/ticket/link/index.js +0 -256
- package/dist/commands/ticket/link/relates.d.ts +0 -14
- package/dist/commands/ticket/link/relates.js +0 -95
- package/dist/commands/ticket/link/remove.d.ts +0 -16
- package/dist/commands/ticket/link/remove.js +0 -132
- package/dist/commands/ticket/template/apply.js +0 -252
- package/dist/commands/ticket/template/create.js +0 -386
- package/dist/commands/ticket/template/delete.d.ts +0 -17
- package/dist/commands/ticket/template/delete.js +0 -94
- package/dist/commands/ticket/template/index.d.ts +0 -15
- package/dist/commands/ticket/template/index.js +0 -120
- package/dist/commands/ticket/template/list.d.ts +0 -16
- package/dist/commands/ticket/template/list.js +0 -112
- package/dist/commands/ticket/template/save.js +0 -163
- /package/dist/commands/{agent/staff → staff}/add.d.ts +0 -0
- /package/dist/commands/{agent/staff → staff}/list.d.ts +0 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Flags, Args } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
|
+
import { styles } from '../../lib/styles.js';
|
|
5
|
+
import { shouldOutputJson, outputPromptAsJson, outputSuccessAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
6
|
+
export default class TemplateSave extends PMOCommand {
|
|
7
|
+
static description = 'Create a ticket template from an existing ticket';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> <%= command.id %> TKT-001 "Bug Report Template"',
|
|
10
|
+
'<%= config.bin %> <%= command.id %> TKT-042 "Feature Request" -d "Standard feature request"',
|
|
11
|
+
];
|
|
12
|
+
static args = {
|
|
13
|
+
ticket: Args.string({
|
|
14
|
+
description: 'Ticket ID to create template from',
|
|
15
|
+
required: false,
|
|
16
|
+
}),
|
|
17
|
+
name: Args.string({
|
|
18
|
+
description: 'Template name',
|
|
19
|
+
required: false,
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
static flags = {
|
|
23
|
+
...pmoBaseFlags,
|
|
24
|
+
'template-name': Flags.string({
|
|
25
|
+
char: 'n',
|
|
26
|
+
description: 'Template name (alternative to positional arg)',
|
|
27
|
+
}),
|
|
28
|
+
description: Flags.string({
|
|
29
|
+
char: 'd',
|
|
30
|
+
description: 'Template description',
|
|
31
|
+
}),
|
|
32
|
+
json: Flags.boolean({
|
|
33
|
+
char: 'm',
|
|
34
|
+
aliases: ['machine'],
|
|
35
|
+
description: 'Output as JSON for AI agents/scripts',
|
|
36
|
+
default: false,
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
39
|
+
async execute() {
|
|
40
|
+
const { args, flags } = await this.parse(TemplateSave);
|
|
41
|
+
const jsonMode = shouldOutputJson(flags);
|
|
42
|
+
const handleError = (code, message) => {
|
|
43
|
+
if (jsonMode) {
|
|
44
|
+
outputErrorAsJson(code, message, createMetadata('template save', flags));
|
|
45
|
+
}
|
|
46
|
+
this.error(message);
|
|
47
|
+
};
|
|
48
|
+
// Get ticket ID
|
|
49
|
+
let ticketId = args.ticket;
|
|
50
|
+
if (!ticketId) {
|
|
51
|
+
const projectId = await this.requireProject();
|
|
52
|
+
const tickets = await this.storage.listTickets(projectId);
|
|
53
|
+
if (tickets.length === 0) {
|
|
54
|
+
return handleError('NO_TICKETS', 'No tickets found. Create a ticket first.');
|
|
55
|
+
}
|
|
56
|
+
if (jsonMode) {
|
|
57
|
+
const choices = tickets.slice(0, 20).map(t => ({ name: `${t.id} - ${t.title}`, value: t.id }));
|
|
58
|
+
outputPromptAsJson(buildPromptConfig('list', 'ticket', 'Select ticket:', choices), createMetadata('template save', flags));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const { selected } = await inquirer.prompt([{
|
|
62
|
+
type: 'list',
|
|
63
|
+
name: 'selected',
|
|
64
|
+
message: 'Select ticket:',
|
|
65
|
+
choices: tickets.slice(0, 20).map(t => ({ name: `${t.id} - ${t.title}`, value: t.id })),
|
|
66
|
+
}]);
|
|
67
|
+
ticketId = selected;
|
|
68
|
+
}
|
|
69
|
+
const ticket = await this.storage.getTicket(ticketId);
|
|
70
|
+
if (!ticket) {
|
|
71
|
+
return handleError('TICKET_NOT_FOUND', `Ticket not found: ${ticketId}`);
|
|
72
|
+
}
|
|
73
|
+
// Get template name
|
|
74
|
+
let templateName = flags['template-name'] || args.name;
|
|
75
|
+
if (!templateName) {
|
|
76
|
+
if (jsonMode) {
|
|
77
|
+
outputPromptAsJson(buildPromptConfig('input', 'name', 'Template name:', undefined, ticket.category || ticket.title.split(' ')[0]), createMetadata('template save', flags));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const { name } = await inquirer.prompt([{
|
|
81
|
+
type: 'input',
|
|
82
|
+
name: 'name',
|
|
83
|
+
message: 'Template name:',
|
|
84
|
+
default: ticket.category || ticket.title.split(' ')[0],
|
|
85
|
+
validate: (i) => i.length > 0 || 'Required',
|
|
86
|
+
}]);
|
|
87
|
+
templateName = name;
|
|
88
|
+
}
|
|
89
|
+
// Get description
|
|
90
|
+
let description = flags.description;
|
|
91
|
+
if (description === undefined && !jsonMode) {
|
|
92
|
+
const { desc } = await inquirer.prompt([{ type: 'input', name: 'desc', message: 'Description (optional):' }]);
|
|
93
|
+
description = desc || undefined;
|
|
94
|
+
}
|
|
95
|
+
const template = await this.storage.createTicketTemplateFromTicket(ticketId, templateName, description);
|
|
96
|
+
if (jsonMode) {
|
|
97
|
+
outputSuccessAsJson({ template, sourceTicketId: ticketId }, createMetadata('template save', flags));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
this.log(styles.success(`\nCreated template "${styles.emphasis(template.name)}" from ${ticketId}`));
|
|
101
|
+
this.log(styles.muted(` ID: ${template.id}`));
|
|
102
|
+
this.log(styles.muted(`\nApply with: prlt template apply --type ticket ${template.id}`));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PMOCommand } from '
|
|
2
|
-
export default class
|
|
1
|
+
import { PMOCommand } from '../../lib/pmo/index.js';
|
|
2
|
+
export default class TemplateUpdate extends PMOCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static args: {
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Flags, Args } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
|
+
import { styles } from '../../lib/styles.js';
|
|
5
|
+
import { shouldOutputJson, outputPromptAsJson, outputSuccessAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
6
|
+
export default class TemplateUpdate extends PMOCommand {
|
|
7
|
+
static description = 'Update a phase template';
|
|
8
|
+
static examples = [
|
|
9
|
+
'<%= config.bin %> <%= command.id %> my-template --name "New Name"',
|
|
10
|
+
'<%= config.bin %> <%= command.id %> my-template -d "Updated description"',
|
|
11
|
+
];
|
|
12
|
+
static args = {
|
|
13
|
+
id: Args.string({
|
|
14
|
+
description: 'Template ID to update',
|
|
15
|
+
required: false,
|
|
16
|
+
}),
|
|
17
|
+
};
|
|
18
|
+
static flags = {
|
|
19
|
+
...pmoBaseFlags,
|
|
20
|
+
name: Flags.string({
|
|
21
|
+
char: 'n',
|
|
22
|
+
description: 'New template name',
|
|
23
|
+
}),
|
|
24
|
+
description: Flags.string({
|
|
25
|
+
char: 'd',
|
|
26
|
+
description: 'New template description',
|
|
27
|
+
}),
|
|
28
|
+
json: Flags.boolean({
|
|
29
|
+
char: 'm',
|
|
30
|
+
aliases: ['machine'],
|
|
31
|
+
description: 'Output as JSON for AI agents/scripts',
|
|
32
|
+
default: false,
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
getPMOOptions() {
|
|
36
|
+
return { promptIfMultiple: false };
|
|
37
|
+
}
|
|
38
|
+
async execute() {
|
|
39
|
+
const { args, flags } = await this.parse(TemplateUpdate);
|
|
40
|
+
const jsonMode = shouldOutputJson(flags);
|
|
41
|
+
const handleError = (code, message) => {
|
|
42
|
+
if (jsonMode) {
|
|
43
|
+
outputErrorAsJson(code, message, createMetadata('template update', flags));
|
|
44
|
+
}
|
|
45
|
+
this.error(message);
|
|
46
|
+
};
|
|
47
|
+
// Get template ID
|
|
48
|
+
let templateId = args.id;
|
|
49
|
+
if (!templateId) {
|
|
50
|
+
const templates = await this.storage.listPhaseTemplates();
|
|
51
|
+
const editable = templates.filter(t => !t.isBuiltin);
|
|
52
|
+
if (editable.length === 0) {
|
|
53
|
+
return handleError('NO_TEMPLATES', 'No editable phase templates (built-in cannot be updated).');
|
|
54
|
+
}
|
|
55
|
+
if (jsonMode) {
|
|
56
|
+
const choices = editable.map(t => ({ name: `${t.name}${t.description ? ` - ${t.description}` : ''}`, value: t.id }));
|
|
57
|
+
outputPromptAsJson(buildPromptConfig('list', 'id', 'Select template:', choices), createMetadata('template update', flags));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const { selected } = await inquirer.prompt([{
|
|
61
|
+
type: 'list',
|
|
62
|
+
name: 'selected',
|
|
63
|
+
message: 'Select template:',
|
|
64
|
+
choices: editable.map(t => ({ name: `${t.name}${t.description ? ` - ${t.description}` : ''}`, value: t.id })),
|
|
65
|
+
}]);
|
|
66
|
+
templateId = selected;
|
|
67
|
+
}
|
|
68
|
+
// Get updates
|
|
69
|
+
let newName = flags.name;
|
|
70
|
+
let newDescription = flags.description;
|
|
71
|
+
if (!newName && newDescription === undefined && !jsonMode) {
|
|
72
|
+
const { updateName } = await inquirer.prompt([{
|
|
73
|
+
type: 'input', name: 'updateName', message: 'New name (leave empty to keep):',
|
|
74
|
+
}]);
|
|
75
|
+
if (updateName)
|
|
76
|
+
newName = updateName;
|
|
77
|
+
const { updateDesc } = await inquirer.prompt([{
|
|
78
|
+
type: 'input', name: 'updateDesc', message: 'New description (leave empty to keep):',
|
|
79
|
+
}]);
|
|
80
|
+
if (updateDesc)
|
|
81
|
+
newDescription = updateDesc;
|
|
82
|
+
if (!newName && !newDescription) {
|
|
83
|
+
this.log(styles.muted('No changes.'));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const changes = {};
|
|
88
|
+
if (newName)
|
|
89
|
+
changes.name = newName;
|
|
90
|
+
if (newDescription !== undefined)
|
|
91
|
+
changes.description = newDescription;
|
|
92
|
+
const template = await this.storage.updatePhaseTemplate(templateId, changes);
|
|
93
|
+
if (jsonMode) {
|
|
94
|
+
outputSuccessAsJson({ template }, createMetadata('template update', flags));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
this.log(styles.success(`\nUpdated template "${styles.emphasis(template.name)}"`));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Command, Args } from '@oclif/core';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import { getWorkspaceInfo } from '
|
|
4
|
-
import { isValidAgentName, normalizeAgentName } from '
|
|
5
|
-
import { getTheme, addThemeNames, getThemeNames } from '
|
|
6
|
-
export default class
|
|
3
|
+
import { getWorkspaceInfo } from '../../lib/agents/commands.js';
|
|
4
|
+
import { isValidAgentName, normalizeAgentName } from '../../lib/themes.js';
|
|
5
|
+
import { getTheme, addThemeNames, getThemeNames } from '../../lib/database/index.js';
|
|
6
|
+
export default class ThemeAddNames extends Command {
|
|
7
7
|
static description = 'Add names to a theme';
|
|
8
8
|
static examples = [
|
|
9
9
|
'<%= config.bin %> <%= command.id %> greek-gods zeus athena poseidon',
|
|
@@ -21,13 +21,13 @@ export default class ThemesAddNames extends Command {
|
|
|
21
21
|
};
|
|
22
22
|
static strict = false; // Allow multiple name arguments
|
|
23
23
|
async run() {
|
|
24
|
-
const { args, argv } = await this.parse(
|
|
24
|
+
const { args, argv } = await this.parse(ThemeAddNames);
|
|
25
25
|
try {
|
|
26
26
|
const workspaceInfo = getWorkspaceInfo();
|
|
27
27
|
// Validate theme exists
|
|
28
28
|
const theme = getTheme(workspaceInfo.path, args.theme);
|
|
29
29
|
if (!theme) {
|
|
30
|
-
this.error(`Theme "${args.theme}" not found. Run "prlt
|
|
30
|
+
this.error(`Theme "${args.theme}" not found. Run "prlt theme list" to see available themes.`);
|
|
31
31
|
}
|
|
32
32
|
// Get names from remaining arguments (skip the theme arg)
|
|
33
33
|
const rawNames = argv.slice(1);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Command, Args, Flags } from '@oclif/core';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import { getWorkspaceInfo } from '
|
|
4
|
-
import { createTheme, getTheme } from '
|
|
5
|
-
export default class
|
|
3
|
+
import { getWorkspaceInfo } from '../../lib/agents/commands.js';
|
|
4
|
+
import { createTheme, getTheme } from '../../lib/database/index.js';
|
|
5
|
+
export default class ThemeCreate extends Command {
|
|
6
6
|
static description = 'Create a custom agent theme';
|
|
7
7
|
static examples = [
|
|
8
8
|
'<%= config.bin %> <%= command.id %> greek-gods',
|
|
@@ -25,7 +25,7 @@ export default class ThemesCreate extends Command {
|
|
|
25
25
|
}),
|
|
26
26
|
};
|
|
27
27
|
async run() {
|
|
28
|
-
const { args, flags } = await this.parse(
|
|
28
|
+
const { args, flags } = await this.parse(ThemeCreate);
|
|
29
29
|
try {
|
|
30
30
|
const workspaceInfo = getWorkspaceInfo();
|
|
31
31
|
// Validate theme name format
|
|
@@ -57,7 +57,7 @@ export default class ThemesCreate extends Command {
|
|
|
57
57
|
this.log(chalk.gray(` ${theme.description}`));
|
|
58
58
|
}
|
|
59
59
|
this.log('');
|
|
60
|
-
this.log(chalk.blue('Add names with: prlt
|
|
60
|
+
this.log(chalk.blue('Add names with: prlt theme add-names ' + name + ' <names...>'));
|
|
61
61
|
}
|
|
62
62
|
catch (error) {
|
|
63
63
|
this.error(error instanceof Error ? error.message : String(error));
|
|
@@ -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 '
|
|
5
|
-
import { ensureBuiltinThemes } from '
|
|
6
|
-
import { getThemes, getAvailableThemeNames } from '
|
|
7
|
-
import { shouldOutputJson, outputPromptAsJson, createMetadata, buildPromptConfig, } from '
|
|
8
|
-
export default class
|
|
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(
|
|
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
|
|
31
|
-
{ id: 'create', name: 'Create a new theme', command: 'prlt
|
|
32
|
-
{ id: 'add-names', name: 'Add names to a theme', command: 'prlt
|
|
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('
|
|
42
|
+
}))), createMetadata('theme', flags));
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
this.log(chalk.bold('\nAgent Themes'));
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import { getWorkspaceInfo } from '
|
|
4
|
-
import { ensureBuiltinThemes } from '
|
|
5
|
-
import { getThemes, getThemeNames, getAvailableThemeNames } from '
|
|
6
|
-
export default class
|
|
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
|
|
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,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 '
|
|
5
|
-
import { ensureBuiltinThemes } from '
|
|
6
|
-
import { getThemes, getAvailableThemeNames, setActiveTheme, getActiveTheme } from '
|
|
7
|
-
import { shouldOutputJson, outputPromptAsJson, createMetadata, buildPromptConfig, } from '
|
|
8
|
-
export default class
|
|
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(
|
|
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('
|
|
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
|
|
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
|
|
39
|
-
{ name: 'Manage templates', value: 'templates', command: 'prlt
|
|
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('
|
|
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('
|
|
95
|
+
await this.config.runCommand('link', []);
|
|
96
96
|
break;
|
|
97
97
|
case 'templates':
|
|
98
|
-
await this.config.runCommand('
|
|
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
|
|
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;
|