@proletariat/cli 0.3.19 → 0.3.21
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/dist/commands/agent/login.js +2 -2
- package/dist/commands/agent/remove.d.ts +1 -0
- package/dist/commands/agent/remove.js +36 -28
- package/dist/commands/agent/shell.js +2 -2
- package/dist/commands/agent/staff/remove.d.ts +1 -0
- package/dist/commands/agent/staff/remove.js +36 -28
- package/dist/commands/agent/status.js +2 -2
- package/dist/commands/agent/temp/cleanup.js +10 -17
- package/dist/commands/agent/themes/add-names.d.ts +1 -0
- package/dist/commands/agent/themes/add-names.js +5 -1
- package/dist/commands/agent/visit.js +2 -2
- package/dist/commands/board/view.d.ts +15 -0
- package/dist/commands/board/view.js +136 -0
- package/dist/commands/config/index.js +6 -3
- package/dist/commands/epic/link/index.js +17 -0
- package/dist/commands/execution/config.d.ts +34 -0
- package/dist/commands/execution/config.js +433 -0
- package/dist/commands/execution/index.js +6 -1
- package/dist/commands/execution/kill.d.ts +12 -0
- package/dist/commands/execution/kill.js +17 -0
- package/dist/commands/execution/list.js +5 -4
- package/dist/commands/execution/logs.js +1 -0
- package/dist/commands/execution/view.d.ts +17 -0
- package/dist/commands/execution/view.js +288 -0
- package/dist/commands/phase/move.js +8 -0
- package/dist/commands/phase/template/apply.js +2 -2
- package/dist/commands/phase/template/create.js +67 -20
- package/dist/commands/phase/template/list.js +1 -1
- package/dist/commands/pr/index.js +6 -2
- package/dist/commands/pr/list.d.ts +17 -0
- package/dist/commands/pr/list.js +163 -0
- package/dist/commands/project/update.d.ts +19 -0
- package/dist/commands/project/update.js +163 -0
- package/dist/commands/roadmap/create.js +5 -0
- package/dist/commands/spec/delete.d.ts +18 -0
- package/dist/commands/spec/delete.js +111 -0
- package/dist/commands/spec/edit.d.ts +23 -0
- package/dist/commands/spec/edit.js +232 -0
- package/dist/commands/spec/index.js +5 -0
- package/dist/commands/status/create.js +38 -34
- package/dist/commands/status/list.js +5 -3
- package/dist/commands/template/phase/create.d.ts +1 -0
- package/dist/commands/template/phase/create.js +10 -1
- package/dist/commands/template/phase/index.js +4 -4
- package/dist/commands/template/ticket/create.d.ts +20 -0
- package/dist/commands/template/ticket/create.js +87 -0
- package/dist/commands/template/ticket/delete.d.ts +1 -1
- package/dist/commands/template/ticket/delete.js +4 -2
- package/dist/commands/template/ticket/save.d.ts +2 -0
- package/dist/commands/template/ticket/save.js +11 -0
- package/dist/commands/ticket/create.js +8 -1
- package/dist/commands/ticket/edit.js +1 -1
- package/dist/commands/ticket/list.d.ts +2 -0
- package/dist/commands/ticket/list.js +39 -2
- package/dist/commands/ticket/template/create.d.ts +9 -1
- package/dist/commands/ticket/template/create.js +224 -52
- package/dist/commands/ticket/template/save.d.ts +2 -1
- package/dist/commands/ticket/template/save.js +58 -7
- package/dist/commands/ticket/update.js +2 -2
- package/dist/commands/work/ready.js +8 -8
- package/dist/commands/work/spawn.js +32 -8
- package/dist/commands/work/watch.js +2 -0
- package/dist/lib/agents/commands.d.ts +7 -0
- package/dist/lib/agents/commands.js +11 -0
- package/dist/lib/agents/index.js +14 -4
- package/dist/lib/branch/index.js +24 -0
- package/dist/lib/execution/config.d.ts +2 -0
- package/dist/lib/execution/config.js +12 -0
- package/dist/lib/execution/runners.js +1 -2
- package/dist/lib/pmo/storage/epics.js +20 -10
- package/dist/lib/pmo/storage/helpers.d.ts +10 -0
- package/dist/lib/pmo/storage/helpers.js +59 -1
- package/dist/lib/pmo/storage/projects.js +20 -8
- package/dist/lib/pmo/storage/specs.js +23 -13
- package/dist/lib/pmo/storage/statuses.js +39 -18
- package/dist/lib/pmo/storage/subtasks.js +19 -8
- package/dist/lib/pmo/storage/tickets.js +27 -15
- package/dist/lib/pmo/utils.d.ts +4 -2
- package/dist/lib/pmo/utils.js +4 -2
- package/oclif.manifest.json +4037 -3234
- package/package.json +2 -4
|
@@ -88,40 +88,44 @@ export default class StatusCreate extends PMOCommand {
|
|
|
88
88
|
default: flags.category || 'backlog',
|
|
89
89
|
when: (ctx) => !ctx.flags.category || flags.interactive,
|
|
90
90
|
});
|
|
91
|
-
//
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
91
|
+
// Optional prompts - only shown in interactive mode
|
|
92
|
+
// In JSON/machine mode, optional fields should be passed as flags or omitted
|
|
93
|
+
if (flags.interactive) {
|
|
94
|
+
// Add color prompt
|
|
95
|
+
resolver.addPrompt({
|
|
96
|
+
flagName: 'color',
|
|
97
|
+
type: 'input',
|
|
98
|
+
message: 'Color (hex, optional):',
|
|
99
|
+
default: flags.color,
|
|
100
|
+
validate: (value) => {
|
|
101
|
+
const v = value;
|
|
102
|
+
if (!v)
|
|
103
|
+
return true;
|
|
104
|
+
return /^#[0-9A-Fa-f]{6}$/.test(v) || 'Invalid hex color (e.g., #FF0000)';
|
|
105
|
+
},
|
|
106
|
+
when: (ctx) => ctx.flags.color === undefined,
|
|
107
|
+
});
|
|
108
|
+
// Add description prompt
|
|
109
|
+
resolver.addPrompt({
|
|
110
|
+
flagName: 'description',
|
|
111
|
+
type: 'input',
|
|
112
|
+
message: 'Description (optional):',
|
|
113
|
+
default: flags.description,
|
|
114
|
+
when: (ctx) => ctx.flags.description === undefined,
|
|
115
|
+
});
|
|
116
|
+
// Add default prompt
|
|
117
|
+
resolver.addPrompt({
|
|
118
|
+
flagName: 'default',
|
|
119
|
+
type: 'list',
|
|
120
|
+
message: 'Set as default status for new tickets?',
|
|
121
|
+
choices: () => [
|
|
122
|
+
{ name: 'No', value: false, command: 'prlt status create --json' },
|
|
123
|
+
{ name: 'Yes', value: true, command: 'prlt status create --default --json' },
|
|
124
|
+
],
|
|
125
|
+
default: flags.default || false,
|
|
126
|
+
when: (ctx) => ctx.flags.default === undefined,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
125
129
|
// Resolve all flags
|
|
126
130
|
const resolved = await resolver.resolve();
|
|
127
131
|
const status = await this.storage.createStatus(projectId, {
|
|
@@ -35,7 +35,11 @@ export default class StatusList extends PMOCommand {
|
|
|
35
35
|
if (!project?.workflowId) {
|
|
36
36
|
this.error(`Project "${projectId}" has no workflow assigned.`);
|
|
37
37
|
}
|
|
38
|
-
const
|
|
38
|
+
const allStatuses = await this.storage.listStatuses(project.workflowId);
|
|
39
|
+
// Apply category filter if specified
|
|
40
|
+
const statuses = flags.category
|
|
41
|
+
? allStatuses.filter(s => s.category === flags.category)
|
|
42
|
+
: allStatuses;
|
|
39
43
|
if (jsonMode) {
|
|
40
44
|
this.log(JSON.stringify(statuses, null, 2));
|
|
41
45
|
return;
|
|
@@ -59,8 +63,6 @@ export default class StatusList extends PMOCommand {
|
|
|
59
63
|
canceled: '🚫',
|
|
60
64
|
};
|
|
61
65
|
for (const category of STATE_CATEGORY_ORDER) {
|
|
62
|
-
if (flags.category && flags.category !== category)
|
|
63
|
-
continue;
|
|
64
66
|
const categoryStatuses = grouped.get(category);
|
|
65
67
|
if (!categoryStatuses || categoryStatuses.length === 0)
|
|
66
68
|
continue;
|
|
@@ -7,6 +7,7 @@ export default class TemplatePhaseCreate extends Command {
|
|
|
7
7
|
};
|
|
8
8
|
static flags: {
|
|
9
9
|
description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
11
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
12
|
};
|
|
12
13
|
run(): Promise<void>;
|
|
@@ -4,6 +4,7 @@ export default class TemplatePhaseCreate extends Command {
|
|
|
4
4
|
static examples = [
|
|
5
5
|
'<%= config.bin %> <%= command.id %> "My Phases"',
|
|
6
6
|
'<%= config.bin %> <%= command.id %> "Sprint Phases" --description "Agile sprint phases"',
|
|
7
|
+
'<%= config.bin %> <%= command.id %> "My Phases" --description "Custom phases" --json',
|
|
7
8
|
];
|
|
8
9
|
static args = {
|
|
9
10
|
name: Args.string({
|
|
@@ -16,9 +17,15 @@ export default class TemplatePhaseCreate extends Command {
|
|
|
16
17
|
char: 'd',
|
|
17
18
|
description: 'Template description',
|
|
18
19
|
}),
|
|
20
|
+
machine: Flags.boolean({
|
|
21
|
+
char: 'm',
|
|
22
|
+
description: 'Output as JSON for AI agents/scripts (machine-readable mode)',
|
|
23
|
+
default: false,
|
|
24
|
+
}),
|
|
19
25
|
json: Flags.boolean({
|
|
20
|
-
description: 'Output
|
|
26
|
+
description: 'Output as JSON (deprecated, use --machine)',
|
|
21
27
|
default: false,
|
|
28
|
+
hidden: true,
|
|
22
29
|
}),
|
|
23
30
|
};
|
|
24
31
|
async run() {
|
|
@@ -28,6 +35,8 @@ export default class TemplatePhaseCreate extends Command {
|
|
|
28
35
|
cmdArgs.push(args.name);
|
|
29
36
|
if (flags.description)
|
|
30
37
|
cmdArgs.push('--description', flags.description);
|
|
38
|
+
if (flags.machine)
|
|
39
|
+
cmdArgs.push('--machine');
|
|
31
40
|
if (flags.json)
|
|
32
41
|
cmdArgs.push('--json');
|
|
33
42
|
await this.config.runCommand('phase:template:create', cmdArgs);
|
|
@@ -30,10 +30,10 @@ export default class TemplatePhase extends Command {
|
|
|
30
30
|
message: 'What would you like to do?',
|
|
31
31
|
choices: () => [
|
|
32
32
|
{ name: 'List phase templates', value: 'list', command: 'prlt template phase list --json' },
|
|
33
|
-
{ name: 'Apply a phase template to project', value: 'apply', command: 'prlt phase
|
|
34
|
-
{ name: 'Create a new phase template', value: 'create', command: 'prlt phase
|
|
35
|
-
{ name: 'Update a phase template', value: 'update', command: 'prlt phase
|
|
36
|
-
{ name: 'Delete a phase template', value: 'delete', command: 'prlt phase
|
|
33
|
+
{ name: 'Apply a phase template to project', value: 'apply', command: 'prlt template phase apply --json' },
|
|
34
|
+
{ name: 'Create a new phase template', value: 'create', command: 'prlt template phase create --json' },
|
|
35
|
+
{ name: 'Update a phase template', value: 'update', command: 'prlt template phase update --json' },
|
|
36
|
+
{ name: 'Delete a phase template', value: 'delete', command: 'prlt template phase delete --json' },
|
|
37
37
|
],
|
|
38
38
|
});
|
|
39
39
|
// In JSON mode, this outputs the prompt and exits
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class TemplateTicketCreate extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
name: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'title-pattern': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'description-template': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
priority: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
category: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
subtask: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
ac: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
label: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
18
|
+
};
|
|
19
|
+
run(): Promise<void>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
export default class TemplateTicketCreate extends Command {
|
|
3
|
+
static description = 'Create a new ticket template from scratch';
|
|
4
|
+
static examples = [
|
|
5
|
+
'<%= config.bin %> <%= command.id %> "Bug Report"',
|
|
6
|
+
'<%= config.bin %> <%= command.id %> "Feature Request" -d "Template for new features"',
|
|
7
|
+
'<%= config.bin %> <%= command.id %> "Task" --title-pattern "[TASK] " --priority P2',
|
|
8
|
+
'<%= config.bin %> <%= command.id %> "Onboarding" --subtask "Setup environment" --subtask "Read docs" --ac "Complete all subtasks"',
|
|
9
|
+
];
|
|
10
|
+
static args = {
|
|
11
|
+
name: Args.string({
|
|
12
|
+
description: 'Template name',
|
|
13
|
+
required: false,
|
|
14
|
+
}),
|
|
15
|
+
};
|
|
16
|
+
static flags = {
|
|
17
|
+
description: Flags.string({
|
|
18
|
+
char: 'd',
|
|
19
|
+
description: 'Template description',
|
|
20
|
+
}),
|
|
21
|
+
'title-pattern': Flags.string({
|
|
22
|
+
description: 'Default title prefix/pattern (e.g., "[BUG] ")',
|
|
23
|
+
}),
|
|
24
|
+
'description-template': Flags.string({
|
|
25
|
+
description: 'Default description template (markdown)',
|
|
26
|
+
}),
|
|
27
|
+
priority: Flags.string({
|
|
28
|
+
char: 'p',
|
|
29
|
+
description: 'Default priority (P0, P1, P2, P3)',
|
|
30
|
+
}),
|
|
31
|
+
category: Flags.string({
|
|
32
|
+
char: 'c',
|
|
33
|
+
description: 'Default category (bug, feature, etc.)',
|
|
34
|
+
}),
|
|
35
|
+
subtask: Flags.string({
|
|
36
|
+
description: 'Add a suggested subtask (can be used multiple times)',
|
|
37
|
+
multiple: true,
|
|
38
|
+
}),
|
|
39
|
+
ac: Flags.string({
|
|
40
|
+
description: 'Add an acceptance criterion pattern (can be used multiple times)',
|
|
41
|
+
multiple: true,
|
|
42
|
+
}),
|
|
43
|
+
label: Flags.string({
|
|
44
|
+
char: 'l',
|
|
45
|
+
description: 'Add a default label (can be used multiple times)',
|
|
46
|
+
multiple: true,
|
|
47
|
+
}),
|
|
48
|
+
json: Flags.boolean({
|
|
49
|
+
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
50
|
+
default: false,
|
|
51
|
+
}),
|
|
52
|
+
};
|
|
53
|
+
async run() {
|
|
54
|
+
const { args, flags } = await this.parse(TemplateTicketCreate);
|
|
55
|
+
const cmdArgs = [];
|
|
56
|
+
if (args.name)
|
|
57
|
+
cmdArgs.push(args.name);
|
|
58
|
+
if (flags.description)
|
|
59
|
+
cmdArgs.push('--description', flags.description);
|
|
60
|
+
if (flags['title-pattern'])
|
|
61
|
+
cmdArgs.push('--title-pattern', flags['title-pattern']);
|
|
62
|
+
if (flags['description-template'])
|
|
63
|
+
cmdArgs.push('--description-template', flags['description-template']);
|
|
64
|
+
if (flags.priority)
|
|
65
|
+
cmdArgs.push('--priority', flags.priority);
|
|
66
|
+
if (flags.category)
|
|
67
|
+
cmdArgs.push('--category', flags.category);
|
|
68
|
+
if (flags.subtask) {
|
|
69
|
+
for (const subtask of flags.subtask) {
|
|
70
|
+
cmdArgs.push('--subtask', subtask);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (flags.ac) {
|
|
74
|
+
for (const ac of flags.ac) {
|
|
75
|
+
cmdArgs.push('--ac', ac);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (flags.label) {
|
|
79
|
+
for (const label of flags.label) {
|
|
80
|
+
cmdArgs.push('--label', label);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (flags.json)
|
|
84
|
+
cmdArgs.push('--json');
|
|
85
|
+
await this.config.runCommand('ticket:template:create', cmdArgs);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -3,7 +3,7 @@ export default class TemplateTicketDelete extends Command {
|
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static args: {
|
|
6
|
-
id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
id: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
7
|
};
|
|
8
8
|
static flags: {
|
|
9
9
|
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
@@ -8,7 +8,7 @@ export default class TemplateTicketDelete extends Command {
|
|
|
8
8
|
static args = {
|
|
9
9
|
id: Args.string({
|
|
10
10
|
description: 'Template ID to delete',
|
|
11
|
-
required:
|
|
11
|
+
required: false,
|
|
12
12
|
}),
|
|
13
13
|
};
|
|
14
14
|
static flags = {
|
|
@@ -24,7 +24,9 @@ export default class TemplateTicketDelete extends Command {
|
|
|
24
24
|
};
|
|
25
25
|
async run() {
|
|
26
26
|
const { args, flags } = await this.parse(TemplateTicketDelete);
|
|
27
|
-
const cmdArgs = [
|
|
27
|
+
const cmdArgs = [];
|
|
28
|
+
if (args.id)
|
|
29
|
+
cmdArgs.push(args.id);
|
|
28
30
|
if (flags.force)
|
|
29
31
|
cmdArgs.push('--force');
|
|
30
32
|
if (flags.json)
|
|
@@ -7,8 +7,10 @@ export default class TemplateTicketSave extends Command {
|
|
|
7
7
|
name: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
8
|
};
|
|
9
9
|
static flags: {
|
|
10
|
+
'template-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
11
|
description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
12
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
14
|
};
|
|
13
15
|
run(): Promise<void>;
|
|
14
16
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
import { machineOutputFlags } from '../../../lib/pmo/base-command.js';
|
|
2
3
|
export default class TemplateTicketSave extends Command {
|
|
3
4
|
static description = 'Create a template from an existing ticket';
|
|
4
5
|
static examples = [
|
|
5
6
|
'<%= config.bin %> <%= command.id %> TKT-001 "Bug Report Template"',
|
|
6
7
|
'<%= config.bin %> <%= command.id %> TKT-042 "Feature Request" --description "Standard feature request template"',
|
|
8
|
+
'<%= config.bin %> <%= command.id %> TKT-001 --template-name "My Template" --json',
|
|
7
9
|
];
|
|
8
10
|
static args = {
|
|
9
11
|
ticket: Args.string({
|
|
@@ -16,6 +18,11 @@ export default class TemplateTicketSave extends Command {
|
|
|
16
18
|
}),
|
|
17
19
|
};
|
|
18
20
|
static flags = {
|
|
21
|
+
...machineOutputFlags,
|
|
22
|
+
'template-name': Flags.string({
|
|
23
|
+
char: 'n',
|
|
24
|
+
description: 'Template name (alternative to positional arg, required in non-TTY/JSON mode)',
|
|
25
|
+
}),
|
|
19
26
|
description: Flags.string({
|
|
20
27
|
char: 'd',
|
|
21
28
|
description: 'Template description',
|
|
@@ -32,10 +39,14 @@ export default class TemplateTicketSave extends Command {
|
|
|
32
39
|
cmdArgs.push(args.ticket);
|
|
33
40
|
if (args.name)
|
|
34
41
|
cmdArgs.push(args.name);
|
|
42
|
+
if (flags['template-name'])
|
|
43
|
+
cmdArgs.push('--template-name', flags['template-name']);
|
|
35
44
|
if (flags.description)
|
|
36
45
|
cmdArgs.push('--description', flags.description);
|
|
37
46
|
if (flags.json)
|
|
38
47
|
cmdArgs.push('--json');
|
|
48
|
+
if (flags.machine)
|
|
49
|
+
cmdArgs.push('--machine');
|
|
39
50
|
await this.config.runCommand('ticket:template:save', cmdArgs);
|
|
40
51
|
}
|
|
41
52
|
}
|
|
@@ -11,7 +11,7 @@ export default class TicketCreate extends PMOCommand {
|
|
|
11
11
|
static examples = [
|
|
12
12
|
'<%= config.bin %> <%= command.id %>',
|
|
13
13
|
'<%= config.bin %> <%= command.id %> --title "Fix login bug" --column Backlog',
|
|
14
|
-
'<%= config.bin %> <%= command.id %> -t "Add feature" -c "In Progress" -p
|
|
14
|
+
'<%= config.bin %> <%= command.id %> -t "Add feature" -c "In Progress" -p P1',
|
|
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',
|
|
@@ -110,6 +110,13 @@ export default class TicketCreate extends PMOCommand {
|
|
|
110
110
|
// Use FlagResolver to handle both JSON mode and interactive prompts
|
|
111
111
|
// This unifies the two code paths into one pattern
|
|
112
112
|
if (!flags.interactive) {
|
|
113
|
+
// In JSON mode, default column to first backlog status if not provided
|
|
114
|
+
// This prevents prompting for column in non-interactive mode
|
|
115
|
+
if (jsonMode && !flags.column) {
|
|
116
|
+
// Prefer "Backlog" column, fall back to first column
|
|
117
|
+
const backlogColumn = columns.find(c => c.toLowerCase() === 'backlog') || columns[0];
|
|
118
|
+
flags.column = backlogColumn;
|
|
119
|
+
}
|
|
113
120
|
const resolver = new FlagResolver({
|
|
114
121
|
commandName: 'ticket create',
|
|
115
122
|
baseCommand: 'prlt ticket create',
|
|
@@ -9,7 +9,7 @@ export default class TicketEdit extends PMOCommand {
|
|
|
9
9
|
static examples = [
|
|
10
10
|
'<%= config.bin %> <%= command.id %> TICK-001',
|
|
11
11
|
'<%= config.bin %> <%= command.id %> TICK-001 --title "New title"',
|
|
12
|
-
'<%= config.bin %> <%= command.id %> TICK-001 --priority
|
|
12
|
+
'<%= config.bin %> <%= command.id %> TICK-001 --priority P1 --category bug',
|
|
13
13
|
'<%= config.bin %> <%= command.id %> TICK-001 --add-subtask "Implement feature" --add-subtask "Write tests"',
|
|
14
14
|
'<%= config.bin %> <%= command.id %> TICK-001 --owner "john" --assignee "agent-1"',
|
|
15
15
|
'<%= config.bin %> <%= command.id %> # Interactive mode',
|
|
@@ -10,6 +10,8 @@ export default class TicketList extends Command {
|
|
|
10
10
|
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
11
|
all: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
12
|
'group-by': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
limit: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
offset: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
15
|
machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
16
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
17
|
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -10,13 +10,15 @@ export default class TicketList extends Command {
|
|
|
10
10
|
static examples = [
|
|
11
11
|
'<%= config.bin %> <%= command.id %>',
|
|
12
12
|
'<%= config.bin %> <%= command.id %> --column Backlog',
|
|
13
|
-
'<%= config.bin %> <%= command.id %> --priority
|
|
13
|
+
'<%= config.bin %> <%= command.id %> --priority P0',
|
|
14
14
|
'<%= config.bin %> <%= command.id %> --category bug',
|
|
15
15
|
'<%= config.bin %> <%= command.id %> --search "login"',
|
|
16
16
|
'<%= config.bin %> <%= command.id %> --project mobile-app',
|
|
17
17
|
'<%= config.bin %> <%= command.id %> --all',
|
|
18
18
|
'<%= config.bin %> <%= command.id %> --all --group-by priority',
|
|
19
19
|
'<%= config.bin %> <%= command.id %> -g priority',
|
|
20
|
+
'<%= config.bin %> <%= command.id %> --limit 10',
|
|
21
|
+
'<%= config.bin %> <%= command.id %> --limit 10 --offset 20',
|
|
20
22
|
];
|
|
21
23
|
static flags = {
|
|
22
24
|
...pmoBaseFlags,
|
|
@@ -53,6 +55,15 @@ export default class TicketList extends Command {
|
|
|
53
55
|
options: ['status', 'priority'],
|
|
54
56
|
default: 'status',
|
|
55
57
|
}),
|
|
58
|
+
limit: Flags.integer({
|
|
59
|
+
char: 'l',
|
|
60
|
+
description: 'Maximum number of tickets to display',
|
|
61
|
+
min: 1,
|
|
62
|
+
}),
|
|
63
|
+
offset: Flags.integer({
|
|
64
|
+
description: 'Skip first N tickets (for pagination)',
|
|
65
|
+
min: 0,
|
|
66
|
+
}),
|
|
56
67
|
};
|
|
57
68
|
async run() {
|
|
58
69
|
const { flags } = await this.parse(TicketList);
|
|
@@ -85,7 +96,33 @@ export default class TicketList extends Command {
|
|
|
85
96
|
}
|
|
86
97
|
// Determine projectId for the query
|
|
87
98
|
const projectId = flags.all ? undefined : (filter.projectId || undefined);
|
|
88
|
-
|
|
99
|
+
// Validate project if specified (not in --all mode)
|
|
100
|
+
if (flags.project && !flags.all) {
|
|
101
|
+
const project = await pmoContext.storage.getProject(flags.project);
|
|
102
|
+
if (!project) {
|
|
103
|
+
const allProjects = await pmoContext.storage.listProjectSummaries();
|
|
104
|
+
const validProjectIds = allProjects.map(p => p.id);
|
|
105
|
+
this.error(`Project "${flags.project}" not found. Valid projects: ${validProjectIds.join(', ')}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Validate column if specified (requires knowing the project)
|
|
109
|
+
if (flags.column && !flags.all) {
|
|
110
|
+
// Get the project board to validate the column
|
|
111
|
+
const targetProjectId = projectId || (await pmoContext.storage.listProjectSummaries())[0]?.id;
|
|
112
|
+
if (targetProjectId) {
|
|
113
|
+
const board = await pmoContext.storage.getBoard(targetProjectId);
|
|
114
|
+
const validColumns = board.columns.map(c => c.name);
|
|
115
|
+
if (!validColumns.includes(flags.column)) {
|
|
116
|
+
this.error(`Column "${flags.column}" not found. Valid columns: ${validColumns.join(', ')}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
let tickets = await pmoContext.storage.listTickets(projectId, filter);
|
|
121
|
+
// Apply pagination
|
|
122
|
+
if (flags.offset)
|
|
123
|
+
tickets = tickets.slice(flags.offset);
|
|
124
|
+
if (flags.limit)
|
|
125
|
+
tickets = tickets.slice(0, flags.limit);
|
|
89
126
|
if (tickets.length === 0) {
|
|
90
127
|
this.log(styles.warning('No tickets found.'));
|
|
91
128
|
return;
|
|
@@ -8,14 +8,22 @@ export default class TicketTemplateCreate extends PMOCommand {
|
|
|
8
8
|
static flags: {
|
|
9
9
|
description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
'title-pattern': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'description-template': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
12
|
priority: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
13
|
category: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
-
|
|
14
|
+
subtask: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
ac: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
label: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
17
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
18
|
+
machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
19
|
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
20
|
};
|
|
17
21
|
protected getPMOOptions(): {
|
|
18
22
|
promptIfMultiple: boolean;
|
|
19
23
|
};
|
|
20
24
|
execute(): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Check if any non-default flags were provided (indicating non-interactive intent)
|
|
27
|
+
*/
|
|
28
|
+
private hasNonDefaultFlags;
|
|
21
29
|
}
|