@proletariat/cli 0.3.23 → 0.3.25
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/action/create.js +4 -4
- package/dist/commands/action/update.js +3 -3
- 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/activate.js +9 -17
- package/dist/commands/epic/archive.js +13 -24
- package/dist/commands/epic/create.d.ts +1 -0
- package/dist/commands/epic/create.js +46 -8
- package/dist/commands/epic/index.js +2 -2
- package/dist/commands/epic/move.js +28 -47
- package/dist/commands/epic/progress.js +10 -14
- package/dist/commands/epic/project.js +42 -59
- package/dist/commands/epic/reorder.js +25 -30
- package/dist/commands/epic/spec.d.ts +1 -0
- package/dist/commands/epic/spec.js +39 -40
- package/dist/commands/epic/ticket.d.ts +2 -0
- package/dist/commands/epic/ticket.js +63 -37
- package/dist/commands/feedback/index.d.ts +10 -0
- package/dist/commands/feedback/index.js +60 -0
- package/dist/commands/feedback/list.d.ts +12 -0
- package/dist/commands/feedback/list.js +126 -0
- package/dist/commands/feedback/submit.d.ts +16 -0
- package/dist/commands/feedback/submit.js +220 -0
- package/dist/commands/{template/phase/delete.d.ts → feedback/view.d.ts} +7 -5
- package/dist/commands/feedback/view.js +109 -0
- package/dist/commands/gh/index.js +4 -0
- 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/repo/create.d.ts +38 -0
- package/dist/commands/repo/create.js +283 -0
- package/dist/commands/repo/index.js +7 -0
- package/dist/commands/roadmap/add-project.js +9 -22
- package/dist/commands/roadmap/create.d.ts +0 -1
- package/dist/commands/roadmap/create.js +46 -40
- package/dist/commands/roadmap/delete.js +10 -24
- package/dist/commands/roadmap/generate.d.ts +1 -0
- package/dist/commands/roadmap/generate.js +21 -22
- package/dist/commands/roadmap/remove-project.js +14 -34
- package/dist/commands/roadmap/reorder.js +19 -26
- package/dist/commands/roadmap/update.js +27 -26
- package/dist/commands/roadmap/view.js +5 -12
- package/dist/commands/session/attach.d.ts +1 -8
- package/dist/commands/session/attach.js +93 -59
- package/dist/commands/session/list.d.ts +0 -8
- package/dist/commands/session/list.js +130 -81
- package/dist/commands/spec/create.d.ts +1 -0
- package/dist/commands/spec/create.js +44 -3
- package/dist/commands/spec/edit.js +63 -33
- 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/{template/phase/index.d.ts → support/book.d.ts} +2 -2
- package/dist/commands/support/book.js +54 -0
- package/dist/commands/{template/ticket/index.d.ts → support/discord.d.ts} +2 -2
- package/dist/commands/support/discord.js +54 -0
- package/dist/commands/support/docs.d.ts +10 -0
- package/dist/commands/support/docs.js +54 -0
- package/dist/commands/support/index.d.ts +19 -0
- package/dist/commands/support/index.js +81 -0
- package/dist/commands/support/issues.d.ts +11 -0
- package/dist/commands/support/issues.js +77 -0
- package/dist/commands/support/logs.d.ts +18 -0
- package/dist/commands/support/logs.js +247 -0
- 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 +75 -15
- package/dist/commands/ticket/edit.js +44 -13
- package/dist/commands/ticket/index.js +6 -6
- package/dist/commands/ticket/move.d.ts +7 -0
- package/dist/commands/ticket/move.js +132 -0
- package/dist/commands/work/spawn.d.ts +1 -0
- package/dist/commands/work/spawn.js +72 -8
- package/dist/commands/work/start.js +6 -0
- package/dist/lib/execution/runners.js +21 -17
- package/dist/lib/execution/session-utils.d.ts +60 -0
- package/dist/lib/execution/session-utils.js +162 -0
- package/dist/lib/execution/spawner.d.ts +2 -0
- package/dist/lib/execution/spawner.js +42 -0
- package/dist/lib/flags/resolver.d.ts +2 -2
- package/dist/lib/flags/resolver.js +15 -0
- package/dist/lib/init/index.js +18 -0
- 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/multiline-input.d.ts +63 -0
- package/dist/lib/multiline-input.js +360 -0
- package/dist/lib/prompt-json.d.ts +57 -6
- package/dist/lib/prompt-json.js +45 -0
- package/dist/lib/repos/git.d.ts +7 -0
- package/dist/lib/repos/git.js +20 -0
- package/oclif.manifest.json +3690 -4995
- package/package.json +6 -4
- 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.js +0 -36
- 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.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
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
|
-
import { PMOCommand, pmoBaseFlags, autoExportToBoard } from '../../../lib/pmo/index.js';
|
|
4
|
-
import { styles } from '../../../lib/styles.js';
|
|
5
|
-
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../../lib/prompt-json.js';
|
|
6
|
-
export default class EpicLink extends PMOCommand {
|
|
7
|
-
static description = 'Manage epic dependencies (links)';
|
|
8
|
-
static examples = [
|
|
9
|
-
'<%= config.bin %> <%= command.id %> EPIC-001 # List dependencies',
|
|
10
|
-
'<%= config.bin %> <%= command.id %> EPIC-001 --blocks EPIC-002 # EPIC-001 is blocked by EPIC-002',
|
|
11
|
-
'<%= config.bin %> <%= command.id %> EPIC-001 --relates EPIC-002 # EPIC-001 relates to EPIC-002',
|
|
12
|
-
'<%= config.bin %> <%= command.id %> EPIC-001 --duplicates EPIC-002',
|
|
13
|
-
'<%= config.bin %> <%= command.id %> EPIC-001 --all # Show all links',
|
|
14
|
-
];
|
|
15
|
-
static args = {
|
|
16
|
-
id: Args.string({
|
|
17
|
-
description: 'Epic ID',
|
|
18
|
-
required: false,
|
|
19
|
-
}),
|
|
20
|
-
};
|
|
21
|
-
static flags = {
|
|
22
|
-
...pmoBaseFlags,
|
|
23
|
-
project: Flags.string({
|
|
24
|
-
char: 'P',
|
|
25
|
-
description: 'Project ID (default: "default")',
|
|
26
|
-
}),
|
|
27
|
-
blocks: Flags.string({
|
|
28
|
-
char: 'b',
|
|
29
|
-
description: 'Add blocking dependency: this epic is blocked by TARGET',
|
|
30
|
-
}),
|
|
31
|
-
relates: Flags.string({
|
|
32
|
-
char: 'r',
|
|
33
|
-
description: 'Add relates_to dependency',
|
|
34
|
-
}),
|
|
35
|
-
duplicates: Flags.string({
|
|
36
|
-
char: 'd',
|
|
37
|
-
description: 'Add duplicates dependency',
|
|
38
|
-
}),
|
|
39
|
-
all: Flags.boolean({
|
|
40
|
-
char: 'a',
|
|
41
|
-
description: 'Show all dependencies (blockers and blocking)',
|
|
42
|
-
default: false,
|
|
43
|
-
}),
|
|
44
|
-
json: Flags.boolean({
|
|
45
|
-
char: 'm',
|
|
46
|
-
aliases: ['machine'],
|
|
47
|
-
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
48
|
-
default: false,
|
|
49
|
-
}),
|
|
50
|
-
};
|
|
51
|
-
async execute() {
|
|
52
|
-
const { args, flags } = await this.parse(EpicLink);
|
|
53
|
-
// Check if JSON output mode is active
|
|
54
|
-
const jsonMode = shouldOutputJson(flags);
|
|
55
|
-
// Helper to handle errors in JSON mode
|
|
56
|
-
const handleError = (code, message) => {
|
|
57
|
-
if (jsonMode) {
|
|
58
|
-
outputErrorAsJson(code, message, createMetadata('epic link', flags));
|
|
59
|
-
this.exit(1);
|
|
60
|
-
}
|
|
61
|
-
this.error(message);
|
|
62
|
-
};
|
|
63
|
-
const projectId = await this.requireProject();
|
|
64
|
-
let epicId = args.id;
|
|
65
|
-
if (!epicId) {
|
|
66
|
-
const epics = await this.storage.listEpics(projectId);
|
|
67
|
-
if (epics.length === 0) {
|
|
68
|
-
if (jsonMode) {
|
|
69
|
-
outputErrorAsJson('NO_EPICS', 'No epics found.', createMetadata('epic link', flags));
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
this.log(styles.muted('\nNo epics found.'));
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
// In JSON mode, output epic selection prompt
|
|
76
|
-
if (jsonMode) {
|
|
77
|
-
const epicChoices = epics.map(e => ({ name: `${e.id} - ${e.title}`, value: e.id }));
|
|
78
|
-
outputPromptAsJson(buildPromptConfig('list', 'id', 'Select epic to manage dependencies:', epicChoices), createMetadata('epic link', flags));
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
const { selected } = await inquirer.prompt([{
|
|
82
|
-
type: 'list',
|
|
83
|
-
name: 'selected',
|
|
84
|
-
message: 'Select epic to manage dependencies:',
|
|
85
|
-
choices: epics.map(e => ({ name: `${e.id} - ${e.title}`, value: e.id })),
|
|
86
|
-
}]);
|
|
87
|
-
epicId = selected;
|
|
88
|
-
}
|
|
89
|
-
const epic = await this.storage.getEpic(epicId);
|
|
90
|
-
if (!epic) {
|
|
91
|
-
return handleError('EPIC_NOT_FOUND', `Epic not found: ${epicId}`);
|
|
92
|
-
}
|
|
93
|
-
// If a dependency flag is provided, add the dependency directly
|
|
94
|
-
if (flags.blocks || flags.relates || flags.duplicates) {
|
|
95
|
-
const targetId = flags.blocks || flags.relates || flags.duplicates;
|
|
96
|
-
const dependencyType = flags.blocks ? 'blocks' :
|
|
97
|
-
flags.relates ? 'relates_to' : 'duplicates';
|
|
98
|
-
await this.addDependency(epicId, targetId, dependencyType, epic.title);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
// Interactive mode: show menu in a loop
|
|
102
|
-
// In JSON mode, output the interactive menu config instead of prompting
|
|
103
|
-
if (jsonMode) {
|
|
104
|
-
const menuChoices = [
|
|
105
|
-
{ name: 'View dependencies', value: 'view' },
|
|
106
|
-
{ name: 'Add blocking dependency (blocked by...)', value: 'blocks' },
|
|
107
|
-
{ name: 'Add relates_to dependency', value: 'relates_to' },
|
|
108
|
-
{ name: 'Add duplicates dependency', value: 'duplicates' },
|
|
109
|
-
{ name: 'Remove dependency', value: 'remove' },
|
|
110
|
-
{ name: 'Done', value: 'done' },
|
|
111
|
-
];
|
|
112
|
-
outputPromptAsJson(buildPromptConfig('list', 'action', `Dependencies for ${epicId}:`, menuChoices), createMetadata('epic link', flags));
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
// Check for TTY before showing interactive menu
|
|
116
|
-
if (!process.stdin.isTTY) {
|
|
117
|
-
this.error('Interactive mode requires a TTY. Use --json for scripted usage or provide flags like --blocks, --relates, or --duplicates.');
|
|
118
|
-
}
|
|
119
|
-
let continueLoop = true;
|
|
120
|
-
while (continueLoop) {
|
|
121
|
-
// eslint-disable-next-line no-await-in-loop -- Interactive user loop
|
|
122
|
-
const allEpics = await this.storage.listEpics(projectId);
|
|
123
|
-
const otherEpics = allEpics.filter(e => e.id !== epicId);
|
|
124
|
-
// eslint-disable-next-line no-await-in-loop -- Interactive user prompt
|
|
125
|
-
const { action } = await inquirer.prompt([{
|
|
126
|
-
type: 'list',
|
|
127
|
-
name: 'action',
|
|
128
|
-
message: `Dependencies for ${epic.id}:`,
|
|
129
|
-
choices: [
|
|
130
|
-
{ name: 'View dependencies', value: 'view' },
|
|
131
|
-
{ name: 'Add blocking dependency (blocked by...)', value: 'blocks' },
|
|
132
|
-
{ name: 'Add relates_to dependency', value: 'relates_to' },
|
|
133
|
-
{ name: 'Add duplicates dependency', value: 'duplicates' },
|
|
134
|
-
new inquirer.Separator(),
|
|
135
|
-
{ name: 'Remove dependency', value: 'remove' },
|
|
136
|
-
{ name: 'Done', value: 'done' },
|
|
137
|
-
],
|
|
138
|
-
}]);
|
|
139
|
-
if (action === 'done') {
|
|
140
|
-
continueLoop = false;
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
if (action === 'view') {
|
|
144
|
-
// eslint-disable-next-line no-await-in-loop -- User action handling
|
|
145
|
-
await this.viewDependencies(epicId, epic, flags.all);
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
-
if (action === 'remove') {
|
|
149
|
-
// eslint-disable-next-line no-await-in-loop -- User action handling
|
|
150
|
-
const dependencies = await this.storage.listEpicDependencies(epicId);
|
|
151
|
-
if (dependencies.length === 0) {
|
|
152
|
-
this.log(styles.muted('\nNo dependencies to remove.'));
|
|
153
|
-
continue;
|
|
154
|
-
}
|
|
155
|
-
// eslint-disable-next-line no-await-in-loop -- Building choices for current interaction
|
|
156
|
-
const choices = await Promise.all(dependencies.map(async (dep) => {
|
|
157
|
-
const depEpic = await this.storage.getEpic(dep.dependsOnEpicId);
|
|
158
|
-
return {
|
|
159
|
-
name: `${dep.dependsOnEpicId} - ${depEpic?.title || 'Unknown'} (${dep.dependencyType})`,
|
|
160
|
-
value: { targetId: dep.dependsOnEpicId, type: dep.dependencyType }
|
|
161
|
-
};
|
|
162
|
-
}));
|
|
163
|
-
// eslint-disable-next-line no-await-in-loop -- User selection prompt
|
|
164
|
-
const { selected } = await inquirer.prompt([{
|
|
165
|
-
type: 'list',
|
|
166
|
-
name: 'selected',
|
|
167
|
-
message: 'Select dependency to remove:',
|
|
168
|
-
choices,
|
|
169
|
-
}]);
|
|
170
|
-
// eslint-disable-next-line no-await-in-loop -- Action after user selection
|
|
171
|
-
await this.storage.deleteEpicDependency(epicId, selected.targetId, selected.type);
|
|
172
|
-
// eslint-disable-next-line no-await-in-loop
|
|
173
|
-
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
174
|
-
this.log(styles.success(`\n✅ Removed dependency: ${epicId} → ${selected.targetId}`));
|
|
175
|
-
continue;
|
|
176
|
-
}
|
|
177
|
-
// Add dependency
|
|
178
|
-
if (otherEpics.length === 0) {
|
|
179
|
-
this.log(styles.muted('\nNo other epics to link to.'));
|
|
180
|
-
continue;
|
|
181
|
-
}
|
|
182
|
-
// eslint-disable-next-line no-await-in-loop -- User selection prompt
|
|
183
|
-
const { targetId } = await inquirer.prompt([{
|
|
184
|
-
type: 'list',
|
|
185
|
-
name: 'targetId',
|
|
186
|
-
message: `Select epic that ${epicId} ${action === 'blocks' ? 'is blocked by' : action === 'relates_to' ? 'relates to' : 'duplicates'}:`,
|
|
187
|
-
choices: otherEpics.map(e => ({ name: `${e.id} - ${e.title}`, value: e.id })),
|
|
188
|
-
}]);
|
|
189
|
-
// eslint-disable-next-line no-await-in-loop -- Action after user selection
|
|
190
|
-
await this.addDependency(epicId, targetId, action, epic.title);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
async addDependency(epicId, targetId, dependencyType, epicTitle) {
|
|
194
|
-
const targetEpic = await this.storage.getEpic(targetId);
|
|
195
|
-
if (!targetEpic) {
|
|
196
|
-
this.error(`Epic not found: ${targetId}`);
|
|
197
|
-
}
|
|
198
|
-
try {
|
|
199
|
-
await this.storage.createEpicDependency(epicId, targetId, dependencyType);
|
|
200
|
-
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
201
|
-
const typeLabel = dependencyType === 'blocks' ? 'is blocked by' :
|
|
202
|
-
dependencyType === 'relates_to' ? 'relates to' : 'duplicates';
|
|
203
|
-
this.log(styles.success(`\n✅ ${styles.emphasis(epicId)} ${typeLabel} ${styles.emphasis(targetId)}`));
|
|
204
|
-
this.log(styles.muted(` ${epicTitle}`));
|
|
205
|
-
this.log(styles.muted(` ${typeLabel} ${targetEpic.title}`));
|
|
206
|
-
}
|
|
207
|
-
catch (error) {
|
|
208
|
-
if (error instanceof Error) {
|
|
209
|
-
if (error.message.includes('already exists')) {
|
|
210
|
-
this.error('Dependency already exists');
|
|
211
|
-
}
|
|
212
|
-
if (error.message.includes('self-dependency')) {
|
|
213
|
-
this.error('Cannot create self-dependency');
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
throw error;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
async viewDependencies(epicId, epic, showAll) {
|
|
220
|
-
const dependencies = await this.storage.listEpicDependencies(epicId);
|
|
221
|
-
const isBlocked = await this.storage.isEpicBlocked(epicId);
|
|
222
|
-
this.log(`\n${styles.emphasis(epic.id)}: ${epic.title}`);
|
|
223
|
-
if (isBlocked) {
|
|
224
|
-
this.log(styles.warning(' Status: BLOCKED'));
|
|
225
|
-
}
|
|
226
|
-
const blockers = dependencies.filter(d => d.dependencyType === 'blocks');
|
|
227
|
-
if (blockers.length > 0) {
|
|
228
|
-
this.log(styles.muted('\n Blocked by:'));
|
|
229
|
-
// Fetch all blocker epics in parallel
|
|
230
|
-
const blockerEpics = await Promise.all(blockers.map(dep => this.storage.getEpic(dep.dependsOnEpicId)));
|
|
231
|
-
for (const blockerEpic of blockerEpics) {
|
|
232
|
-
if (blockerEpic) {
|
|
233
|
-
const status = blockerEpic.status === 'complete' ? styles.success('complete') : styles.warning(blockerEpic.status);
|
|
234
|
-
this.log(` - ${blockerEpic.id}: ${blockerEpic.title} (${status})`);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
const otherDeps = dependencies.filter(d => d.dependencyType !== 'blocks');
|
|
239
|
-
if (otherDeps.length > 0) {
|
|
240
|
-
this.log(styles.muted('\n Related:'));
|
|
241
|
-
// Fetch all related epics in parallel
|
|
242
|
-
const relatedEpics = await Promise.all(otherDeps.map(async (dep) => ({ dep, epic: await this.storage.getEpic(dep.dependsOnEpicId) })));
|
|
243
|
-
for (const { dep, epic: relatedEpic } of relatedEpics) {
|
|
244
|
-
if (relatedEpic) {
|
|
245
|
-
this.log(` - ${dep.dependencyType}: ${relatedEpic.id} - ${relatedEpic.title}`);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
if (showAll) {
|
|
250
|
-
const allEpics = await this.storage.listEpics(epic.projectId);
|
|
251
|
-
// Find all epics that depend on this epic in parallel
|
|
252
|
-
const blockingResults = await Promise.all(allEpics
|
|
253
|
-
.filter(otherEpic => otherEpic.id !== epicId)
|
|
254
|
-
.map(async (otherEpic) => {
|
|
255
|
-
const otherDeps = await this.storage.listEpicDependencies(otherEpic.id);
|
|
256
|
-
const blockingDep = otherDeps.find(d => d.dependsOnEpicId === epicId);
|
|
257
|
-
return blockingDep ? { epic: otherEpic, type: blockingDep.dependencyType } : null;
|
|
258
|
-
}));
|
|
259
|
-
const blocking = blockingResults.filter((b) => b !== null);
|
|
260
|
-
if (blocking.length > 0) {
|
|
261
|
-
this.log(styles.muted('\n Blocking:'));
|
|
262
|
-
for (const item of blocking) {
|
|
263
|
-
this.log(` - ${item.epic.id}: ${item.epic.title} (${item.type})`);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
if (dependencies.length === 0) {
|
|
268
|
-
this.log(styles.muted('\n No dependencies.'));
|
|
269
|
-
}
|
|
270
|
-
this.log('');
|
|
271
|
-
}
|
|
272
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
|
-
import { PMOCommand, pmoBaseFlags, autoExportToBoard } from '../../../lib/pmo/index.js';
|
|
4
|
-
import { styles } from '../../../lib/styles.js';
|
|
5
|
-
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../../lib/prompt-json.js';
|
|
6
|
-
export default class EpicLinkRelates extends PMOCommand {
|
|
7
|
-
static description = 'Add a relates_to dependency (informational link)';
|
|
8
|
-
static examples = ['<%= config.bin %> <%= command.id %> EPIC-001 EPIC-002'];
|
|
9
|
-
static args = {
|
|
10
|
-
id: Args.string({ description: 'Epic ID', required: true }),
|
|
11
|
-
target: Args.string({ description: 'Related epic ID', required: false }),
|
|
12
|
-
};
|
|
13
|
-
static flags = {
|
|
14
|
-
...pmoBaseFlags,
|
|
15
|
-
project: Flags.string({ char: 'P', description: 'Project ID' }),
|
|
16
|
-
json: Flags.boolean({
|
|
17
|
-
char: 'm',
|
|
18
|
-
aliases: ['machine'],
|
|
19
|
-
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
20
|
-
default: false,
|
|
21
|
-
}),
|
|
22
|
-
};
|
|
23
|
-
async execute() {
|
|
24
|
-
const { args, flags } = await this.parse(EpicLinkRelates);
|
|
25
|
-
// Check if JSON output mode is active
|
|
26
|
-
const jsonMode = shouldOutputJson(flags);
|
|
27
|
-
// Helper to handle errors in JSON mode
|
|
28
|
-
const handleError = (code, message) => {
|
|
29
|
-
if (jsonMode) {
|
|
30
|
-
outputErrorAsJson(code, message, createMetadata('epic link relates', flags));
|
|
31
|
-
this.exit(1);
|
|
32
|
-
}
|
|
33
|
-
this.error(message);
|
|
34
|
-
};
|
|
35
|
-
const epic = await this.storage.getEpic(args.id);
|
|
36
|
-
if (!epic)
|
|
37
|
-
return handleError('EPIC_NOT_FOUND', `Epic not found: ${args.id}`);
|
|
38
|
-
const projectId = epic.projectId;
|
|
39
|
-
let targetId = args.target;
|
|
40
|
-
if (!targetId) {
|
|
41
|
-
const allEpics = await this.storage.listEpics(projectId);
|
|
42
|
-
const otherEpics = allEpics.filter(e => e.id !== args.id);
|
|
43
|
-
if (otherEpics.length === 0) {
|
|
44
|
-
if (jsonMode) {
|
|
45
|
-
outputErrorAsJson('NO_OTHER_EPICS', 'No other epics.', createMetadata('epic link relates', flags));
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
this.log(styles.muted('\nNo other epics.'));
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
// In JSON mode, output target epic selection prompt
|
|
52
|
-
if (jsonMode) {
|
|
53
|
-
const epicChoices = otherEpics.map(e => ({ name: `${e.id} - ${e.title}`, value: e.id }));
|
|
54
|
-
outputPromptAsJson(buildPromptConfig('list', 'target', `Select epic that ${args.id} relates to:`, epicChoices), createMetadata('epic link relates', flags));
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
const { selected } = await inquirer.prompt([{ type: 'list', name: 'selected', message: `Select epic that ${args.id} relates to:`,
|
|
58
|
-
choices: otherEpics.map(e => ({ name: `${e.id} - ${e.title}`, value: e.id })) }]);
|
|
59
|
-
targetId = selected;
|
|
60
|
-
}
|
|
61
|
-
const targetEpic = await this.storage.getEpic(targetId);
|
|
62
|
-
if (!targetEpic)
|
|
63
|
-
return handleError('TARGET_EPIC_NOT_FOUND', `Epic not found: ${targetId}`);
|
|
64
|
-
await this.storage.createEpicDependency(args.id, targetId, 'relates_to');
|
|
65
|
-
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
66
|
-
this.log(styles.success(`\n✅ ${styles.emphasis(args.id)} relates to ${styles.emphasis(targetId)}`));
|
|
67
|
-
}
|
|
68
|
-
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
|
-
import { PMOCommand, pmoBaseFlags, autoExportToBoard } from '../../../lib/pmo/index.js';
|
|
4
|
-
import { styles } from '../../../lib/styles.js';
|
|
5
|
-
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../../lib/prompt-json.js';
|
|
6
|
-
export default class EpicLinkRemove extends PMOCommand {
|
|
7
|
-
static description = 'Remove a dependency from an epic';
|
|
8
|
-
static examples = [
|
|
9
|
-
'<%= config.bin %> <%= command.id %> EPIC-001 EPIC-002',
|
|
10
|
-
'<%= config.bin %> <%= command.id %> EPIC-001 --all',
|
|
11
|
-
];
|
|
12
|
-
static args = {
|
|
13
|
-
id: Args.string({ description: 'Epic ID', required: true }),
|
|
14
|
-
target: Args.string({ description: 'Target epic ID to unlink', required: false }),
|
|
15
|
-
};
|
|
16
|
-
static flags = {
|
|
17
|
-
...pmoBaseFlags,
|
|
18
|
-
project: Flags.string({ char: 'P', description: 'Project ID' }),
|
|
19
|
-
type: Flags.string({ char: 't', description: 'Dependency type', options: ['blocks', 'relates_to', 'duplicates'] }),
|
|
20
|
-
all: Flags.boolean({ char: 'a', description: 'Remove all dependencies', default: false }),
|
|
21
|
-
json: Flags.boolean({
|
|
22
|
-
char: 'm',
|
|
23
|
-
aliases: ['machine'],
|
|
24
|
-
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
25
|
-
default: false,
|
|
26
|
-
}),
|
|
27
|
-
};
|
|
28
|
-
async execute() {
|
|
29
|
-
const { args, flags } = await this.parse(EpicLinkRemove);
|
|
30
|
-
// Check if JSON output mode is active
|
|
31
|
-
const jsonMode = shouldOutputJson(flags);
|
|
32
|
-
// Helper to handle errors in JSON mode
|
|
33
|
-
const handleError = (code, message) => {
|
|
34
|
-
if (jsonMode) {
|
|
35
|
-
outputErrorAsJson(code, message, createMetadata('epic link remove', flags));
|
|
36
|
-
this.exit(1);
|
|
37
|
-
}
|
|
38
|
-
this.error(message);
|
|
39
|
-
};
|
|
40
|
-
const epic = await this.storage.getEpic(args.id);
|
|
41
|
-
if (!epic)
|
|
42
|
-
return handleError('EPIC_NOT_FOUND', `Epic not found: ${args.id}`);
|
|
43
|
-
const dependencies = await this.storage.listEpicDependencies(args.id);
|
|
44
|
-
if (dependencies.length === 0) {
|
|
45
|
-
if (jsonMode) {
|
|
46
|
-
outputErrorAsJson('NO_DEPENDENCIES', `Epic ${args.id} has no dependencies.`, createMetadata('epic link remove', flags));
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
this.log(styles.muted(`\nEpic ${args.id} has no dependencies.`));
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (flags.all) {
|
|
53
|
-
// In JSON mode, output confirmation prompt
|
|
54
|
-
if (jsonMode) {
|
|
55
|
-
const confirmChoices = [
|
|
56
|
-
{ name: 'No', value: 'false' },
|
|
57
|
-
{ name: 'Yes', value: 'true' },
|
|
58
|
-
];
|
|
59
|
-
outputPromptAsJson(buildPromptConfig('list', 'confirmed', `Remove all ${dependencies.length} dependencies?`, confirmChoices), createMetadata('epic link remove', flags));
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
const { confirmed } = await inquirer.prompt([{ type: 'confirm', name: 'confirmed', message: `Remove all ${dependencies.length} dependencies?`, default: false }]);
|
|
63
|
-
if (!confirmed) {
|
|
64
|
-
this.log(styles.muted('\nCancelled.'));
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
// Delete sequentially to maintain data integrity
|
|
68
|
-
// eslint-disable-next-line no-await-in-loop
|
|
69
|
-
for (const dep of dependencies)
|
|
70
|
-
await this.storage.deleteEpicDependency(args.id, dep.dependsOnEpicId, dep.dependencyType);
|
|
71
|
-
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
72
|
-
this.log(styles.success(`\n✅ Removed ${dependencies.length} dependencies from ${args.id}`));
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
let targetId = args.target;
|
|
76
|
-
if (!targetId) {
|
|
77
|
-
const choices = await Promise.all(dependencies.map(async (dep) => {
|
|
78
|
-
const depEpic = await this.storage.getEpic(dep.dependsOnEpicId);
|
|
79
|
-
return { name: `${dep.dependsOnEpicId} - ${depEpic?.title || 'Unknown'} (${dep.dependencyType})`, value: dep.dependsOnEpicId };
|
|
80
|
-
}));
|
|
81
|
-
// In JSON mode, output dependency selection prompt
|
|
82
|
-
if (jsonMode) {
|
|
83
|
-
outputPromptAsJson(buildPromptConfig('list', 'target', 'Select dependency to remove:', choices), createMetadata('epic link remove', flags));
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
const { selected } = await inquirer.prompt([{ type: 'list', name: 'selected', message: 'Select dependency to remove:', choices }]);
|
|
87
|
-
targetId = selected;
|
|
88
|
-
}
|
|
89
|
-
await this.storage.deleteEpicDependency(args.id, targetId, flags.type);
|
|
90
|
-
await autoExportToBoard(this.pmoPath, this.storage, (msg) => this.log(styles.muted(msg)));
|
|
91
|
-
this.log(styles.success(`\n✅ Removed dependency: ${args.id} → ${targetId}`));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { PMOCommand } from '../../../lib/pmo/index.js';
|
|
2
|
-
export default class PhaseTemplateApply extends PMOCommand {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static args: {
|
|
6
|
-
template: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
|
-
};
|
|
8
|
-
static flags: {
|
|
9
|
-
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
-
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
-
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
};
|
|
13
|
-
protected getPMOOptions(): {
|
|
14
|
-
promptIfMultiple: boolean;
|
|
15
|
-
};
|
|
16
|
-
execute(): Promise<void>;
|
|
17
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
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, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../../lib/prompt-json.js';
|
|
6
|
-
export default class PhaseTemplateApply extends PMOCommand {
|
|
7
|
-
static description = 'Apply a phase template to the workspace';
|
|
8
|
-
static examples = [
|
|
9
|
-
'<%= config.bin %> <%= command.id %> default',
|
|
10
|
-
'<%= config.bin %> <%= command.id %> agile',
|
|
11
|
-
'<%= config.bin %> <%= command.id %> product --force # Skip confirmation',
|
|
12
|
-
];
|
|
13
|
-
static args = {
|
|
14
|
-
template: Args.string({
|
|
15
|
-
description: 'Phase template ID to apply',
|
|
16
|
-
required: false,
|
|
17
|
-
}),
|
|
18
|
-
};
|
|
19
|
-
static flags = {
|
|
20
|
-
...pmoBaseFlags,
|
|
21
|
-
force: Flags.boolean({
|
|
22
|
-
char: 'f',
|
|
23
|
-
description: 'Skip confirmation prompt (will replace existing phases)',
|
|
24
|
-
default: false,
|
|
25
|
-
}),
|
|
26
|
-
json: Flags.boolean({
|
|
27
|
-
char: 'm',
|
|
28
|
-
aliases: ['machine'],
|
|
29
|
-
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
30
|
-
default: false,
|
|
31
|
-
}),
|
|
32
|
-
};
|
|
33
|
-
getPMOOptions() {
|
|
34
|
-
return { promptIfMultiple: false };
|
|
35
|
-
}
|
|
36
|
-
async execute() {
|
|
37
|
-
const { args, flags } = await this.parse(PhaseTemplateApply);
|
|
38
|
-
// Check if JSON output mode is active
|
|
39
|
-
const jsonMode = shouldOutputJson(flags);
|
|
40
|
-
// Helper to handle errors in JSON mode
|
|
41
|
-
const handleError = (code, message) => {
|
|
42
|
-
if (jsonMode) {
|
|
43
|
-
outputErrorAsJson(code, message, createMetadata('phase template apply', flags));
|
|
44
|
-
this.exit(1);
|
|
45
|
-
}
|
|
46
|
-
this.error(message);
|
|
47
|
-
};
|
|
48
|
-
// Get template - prompt for selection if not provided
|
|
49
|
-
let templateId = args.template;
|
|
50
|
-
if (!templateId) {
|
|
51
|
-
const templates = await this.storage.listPhaseTemplates();
|
|
52
|
-
if (templates.length === 0) {
|
|
53
|
-
return handleError('NO_TEMPLATES', `No phase templates found.\nCreate one with: prlt template phase create "Template Name"`);
|
|
54
|
-
}
|
|
55
|
-
const { selectedTemplate } = await inquirer.prompt([{
|
|
56
|
-
type: 'list',
|
|
57
|
-
name: 'selectedTemplate',
|
|
58
|
-
message: 'Select a phase template:',
|
|
59
|
-
choices: templates.map(t => ({
|
|
60
|
-
name: `${t.name}${t.description ? ` - ${t.description}` : ''}`,
|
|
61
|
-
value: t.id,
|
|
62
|
-
})),
|
|
63
|
-
}]);
|
|
64
|
-
templateId = selectedTemplate;
|
|
65
|
-
}
|
|
66
|
-
// Verify template exists
|
|
67
|
-
const template = await this.storage.getPhaseTemplate(templateId);
|
|
68
|
-
if (!template) {
|
|
69
|
-
return handleError('TEMPLATE_NOT_FOUND', `Phase template not found: ${templateId}. Run 'prlt template phase list' to see available templates.`);
|
|
70
|
-
}
|
|
71
|
-
// Check if workspace has existing phases
|
|
72
|
-
const existingPhases = await this.storage.listPhases();
|
|
73
|
-
if (existingPhases.length > 0 && !flags.force) {
|
|
74
|
-
// In JSON mode, output confirmation prompt
|
|
75
|
-
if (jsonMode) {
|
|
76
|
-
const confirmChoices = [
|
|
77
|
-
{ name: 'No', value: 'false' },
|
|
78
|
-
{ name: 'Yes', value: 'true' },
|
|
79
|
-
];
|
|
80
|
-
outputPromptAsJson(buildPromptConfig('list', 'confirmed', `Workspace has ${existingPhases.length} existing phase(s). Applying will REPLACE all. Apply template "${template.name}"?`, confirmChoices), createMetadata('phase template apply', flags));
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
this.log(styles.warning(`\nWorkspace has ${existingPhases.length} existing phase(s).`));
|
|
84
|
-
this.log(styles.warning('Applying a template will REPLACE all existing phases.'));
|
|
85
|
-
this.log('');
|
|
86
|
-
const { confirm } = await inquirer.prompt([
|
|
87
|
-
{
|
|
88
|
-
type: 'confirm',
|
|
89
|
-
name: 'confirm',
|
|
90
|
-
message: `Apply template "${template.name}" and replace existing phases?`,
|
|
91
|
-
default: false,
|
|
92
|
-
},
|
|
93
|
-
]);
|
|
94
|
-
if (!confirm) {
|
|
95
|
-
this.log(styles.muted('Cancelled'));
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
// Apply template
|
|
100
|
-
const phases = await this.storage.applyPhaseTemplate(templateId);
|
|
101
|
-
this.log(styles.success(`\nApplied phase template "${styles.emphasis(template.name)}"`));
|
|
102
|
-
this.log(styles.muted(`Created ${phases.length} phases:`));
|
|
103
|
-
for (const phase of phases) {
|
|
104
|
-
const defaultBadge = phase.isDefault ? ' (default)' : '';
|
|
105
|
-
this.log(styles.muted(` • ${phase.name} [${phase.category}]${defaultBadge}`));
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { PMOCommand } from '../../../lib/pmo/index.js';
|
|
2
|
-
export default class PhaseTemplateCreate extends PMOCommand {
|
|
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
|
-
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
-
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
};
|
|
13
|
-
protected getPMOOptions(): {
|
|
14
|
-
promptIfMultiple: boolean;
|
|
15
|
-
};
|
|
16
|
-
execute(): Promise<void>;
|
|
17
|
-
}
|