@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,104 +0,0 @@
|
|
|
1
|
-
import { Flags, Args } from '@oclif/core';
|
|
2
|
-
import { PMOCommand, pmoBaseFlags } from '../../../lib/pmo/index.js';
|
|
3
|
-
import { styles } from '../../../lib/styles.js';
|
|
4
|
-
import { shouldOutputJson, outputSuccessAsJson, createMetadata } from '../../../lib/prompt-json.js';
|
|
5
|
-
import { FlagResolver } from '../../../lib/flags/index.js';
|
|
6
|
-
export default class PhaseTemplateCreate extends PMOCommand {
|
|
7
|
-
static description = 'Create a new phase template from current workspace phases';
|
|
8
|
-
static examples = [
|
|
9
|
-
'<%= config.bin %> <%= command.id %> "My Custom Phases"',
|
|
10
|
-
'<%= config.bin %> <%= command.id %> "Enterprise" --description "Enterprise project lifecycle"',
|
|
11
|
-
'<%= config.bin %> <%= command.id %> "My Phases" --description "Custom phases" --json',
|
|
12
|
-
];
|
|
13
|
-
static args = {
|
|
14
|
-
name: Args.string({
|
|
15
|
-
description: 'Name for the new template',
|
|
16
|
-
required: false,
|
|
17
|
-
}),
|
|
18
|
-
};
|
|
19
|
-
static flags = {
|
|
20
|
-
...pmoBaseFlags,
|
|
21
|
-
description: Flags.string({
|
|
22
|
-
char: 'd',
|
|
23
|
-
description: 'Template description',
|
|
24
|
-
}),
|
|
25
|
-
};
|
|
26
|
-
getPMOOptions() {
|
|
27
|
-
return { promptIfMultiple: false };
|
|
28
|
-
}
|
|
29
|
-
async execute() {
|
|
30
|
-
const { args, flags } = await this.parse(PhaseTemplateCreate);
|
|
31
|
-
// Check if JSON output mode is active
|
|
32
|
-
const jsonMode = shouldOutputJson(flags);
|
|
33
|
-
// Build base command with positional arg if name provided
|
|
34
|
-
const baseCmd = args.name
|
|
35
|
-
? `prlt template phase create "${args.name}"`
|
|
36
|
-
: 'prlt template phase create';
|
|
37
|
-
// Use FlagResolver for unified JSON mode and interactive handling
|
|
38
|
-
const resolver = new FlagResolver({
|
|
39
|
-
commandName: 'phase template create',
|
|
40
|
-
baseCommand: baseCmd,
|
|
41
|
-
jsonMode,
|
|
42
|
-
flags: {
|
|
43
|
-
description: flags.description,
|
|
44
|
-
json: flags.json,
|
|
45
|
-
},
|
|
46
|
-
args: { name: args.name },
|
|
47
|
-
});
|
|
48
|
-
// Name prompt - required (only if not provided as positional arg)
|
|
49
|
-
if (!args.name) {
|
|
50
|
-
resolver.addPrompt({
|
|
51
|
-
flagName: 'name',
|
|
52
|
-
type: 'input',
|
|
53
|
-
message: 'Template name:',
|
|
54
|
-
validate: (value) => value.length > 0 || 'Name is required',
|
|
55
|
-
context: {
|
|
56
|
-
hint: 'Provide name with: prlt template phase create "Template Name"',
|
|
57
|
-
example: 'prlt template phase create "My Phases" --description "Custom phases"',
|
|
58
|
-
},
|
|
59
|
-
// For input prompts, the agent will re-run with the positional arg
|
|
60
|
-
getCommand: (value) => `prlt template phase create "${value}" --json`,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
// Description prompt - optional (only in interactive mode without --json)
|
|
64
|
-
if (!jsonMode && args.name && flags.description === undefined) {
|
|
65
|
-
resolver.addPrompt({
|
|
66
|
-
flagName: 'description',
|
|
67
|
-
type: 'input',
|
|
68
|
-
message: 'Description (optional):',
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
// Resolve missing flags
|
|
72
|
-
const resolved = await resolver.resolve();
|
|
73
|
-
// Get name from args or resolved (for interactive mode)
|
|
74
|
-
const templateName = args.name || resolved.name;
|
|
75
|
-
// Validate required fields
|
|
76
|
-
if (!templateName) {
|
|
77
|
-
this.error('Name is required. Provide as positional argument: prlt template phase create "Template Name"');
|
|
78
|
-
}
|
|
79
|
-
// Get description from flags or resolved
|
|
80
|
-
const description = flags.description ?? resolved.description ?? undefined;
|
|
81
|
-
const template = await this.storage.savePhaseTemplate(templateName, description);
|
|
82
|
-
// Output as JSON in machine mode
|
|
83
|
-
if (jsonMode) {
|
|
84
|
-
outputSuccessAsJson({
|
|
85
|
-
id: template.id,
|
|
86
|
-
name: template.name,
|
|
87
|
-
description: template.description,
|
|
88
|
-
phasesCount: template.phases.length,
|
|
89
|
-
phases: template.phases.map(p => ({
|
|
90
|
-
name: p.name,
|
|
91
|
-
category: p.category,
|
|
92
|
-
isDefault: p.isDefault,
|
|
93
|
-
})),
|
|
94
|
-
}, createMetadata('phase template create', flags));
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
this.log(styles.success(`\nCreated phase template "${styles.emphasis(template.name)}" (${template.id})`));
|
|
98
|
-
this.log(styles.muted(`Saved ${template.phases.length} phases:`));
|
|
99
|
-
for (const phase of template.phases) {
|
|
100
|
-
const defaultBadge = phase.isDefault ? ' (default)' : '';
|
|
101
|
-
this.log(styles.muted(` • ${phase.name} [${phase.category}]${defaultBadge}`));
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { PMOCommand } from '../../../lib/pmo/index.js';
|
|
2
|
-
export default class PhaseTemplateDelete extends PMOCommand {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static args: {
|
|
6
|
-
id: 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,100 +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 PhaseTemplateDelete extends PMOCommand {
|
|
7
|
-
static description = 'Delete a phase template';
|
|
8
|
-
static examples = [
|
|
9
|
-
'<%= config.bin %> <%= command.id %> my-custom-template',
|
|
10
|
-
'<%= config.bin %> <%= command.id %> my-template --force',
|
|
11
|
-
];
|
|
12
|
-
static args = {
|
|
13
|
-
id: Args.string({
|
|
14
|
-
description: 'Template ID to delete',
|
|
15
|
-
required: false,
|
|
16
|
-
}),
|
|
17
|
-
};
|
|
18
|
-
static flags = {
|
|
19
|
-
...pmoBaseFlags,
|
|
20
|
-
force: Flags.boolean({
|
|
21
|
-
char: 'f',
|
|
22
|
-
description: 'Skip confirmation',
|
|
23
|
-
default: false,
|
|
24
|
-
}),
|
|
25
|
-
json: Flags.boolean({
|
|
26
|
-
char: 'm',
|
|
27
|
-
aliases: ['machine'],
|
|
28
|
-
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
29
|
-
default: false,
|
|
30
|
-
}),
|
|
31
|
-
};
|
|
32
|
-
getPMOOptions() {
|
|
33
|
-
return { promptIfMultiple: false };
|
|
34
|
-
}
|
|
35
|
-
async execute() {
|
|
36
|
-
const { args, flags } = await this.parse(PhaseTemplateDelete);
|
|
37
|
-
// Check if JSON output mode is active
|
|
38
|
-
const jsonMode = shouldOutputJson(flags);
|
|
39
|
-
// Helper to handle errors in JSON mode
|
|
40
|
-
const handleError = (code, message) => {
|
|
41
|
-
if (jsonMode) {
|
|
42
|
-
outputErrorAsJson(code, message, createMetadata('phase template delete', flags));
|
|
43
|
-
this.exit(1);
|
|
44
|
-
}
|
|
45
|
-
this.error(message);
|
|
46
|
-
};
|
|
47
|
-
// Get template - prompt for selection if not provided
|
|
48
|
-
let templateId = args.id;
|
|
49
|
-
if (!templateId) {
|
|
50
|
-
const templates = await this.storage.listPhaseTemplates();
|
|
51
|
-
const deletableTemplates = templates.filter(t => !t.isBuiltin);
|
|
52
|
-
if (deletableTemplates.length === 0) {
|
|
53
|
-
return handleError('NO_TEMPLATES', `No deletable phase templates found (built-in templates cannot be deleted).`);
|
|
54
|
-
}
|
|
55
|
-
const { selectedTemplate } = await inquirer.prompt([{
|
|
56
|
-
type: 'list',
|
|
57
|
-
name: 'selectedTemplate',
|
|
58
|
-
message: 'Select a template to delete:',
|
|
59
|
-
choices: deletableTemplates.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}`);
|
|
70
|
-
}
|
|
71
|
-
if (template.isBuiltin) {
|
|
72
|
-
return handleError('CANNOT_DELETE_BUILTIN', 'Cannot delete built-in templates');
|
|
73
|
-
}
|
|
74
|
-
if (!flags.force) {
|
|
75
|
-
// In JSON mode, output confirmation prompt
|
|
76
|
-
if (jsonMode) {
|
|
77
|
-
const confirmChoices = [
|
|
78
|
-
{ name: 'No', value: 'false' },
|
|
79
|
-
{ name: 'Yes', value: 'true' },
|
|
80
|
-
];
|
|
81
|
-
outputPromptAsJson(buildPromptConfig('list', 'confirmed', `Delete phase template "${template.name}"?`, confirmChoices), createMetadata('phase template delete', flags));
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
const { confirm } = await inquirer.prompt([
|
|
85
|
-
{
|
|
86
|
-
type: 'confirm',
|
|
87
|
-
name: 'confirm',
|
|
88
|
-
message: `Delete phase template "${template.name}"?`,
|
|
89
|
-
default: false,
|
|
90
|
-
},
|
|
91
|
-
]);
|
|
92
|
-
if (!confirm) {
|
|
93
|
-
this.log(styles.muted('Cancelled'));
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
await this.storage.deletePhaseTemplate(templateId);
|
|
98
|
-
this.log(styles.success(`\nDeleted phase template "${template.name}"`));
|
|
99
|
-
}
|
|
100
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { PMOCommand } from '../../../lib/pmo/index.js';
|
|
2
|
-
export default class PhaseTemplateMenu extends PMOCommand {
|
|
3
|
-
static description: string;
|
|
4
|
-
static aliases: string[];
|
|
5
|
-
static examples: string[];
|
|
6
|
-
static flags: {
|
|
7
|
-
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
-
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
-
};
|
|
10
|
-
protected getPMOOptions(): {
|
|
11
|
-
promptIfMultiple: boolean;
|
|
12
|
-
};
|
|
13
|
-
execute(): Promise<void>;
|
|
14
|
-
private selectTemplate;
|
|
15
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { Flags } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
|
-
import { PMOCommand, pmoBaseFlags } from '../../../lib/pmo/index.js';
|
|
4
|
-
import { shouldOutputJson, outputPromptAsJson, createMetadata, buildPromptConfig, } from '../../../lib/prompt-json.js';
|
|
5
|
-
export default class PhaseTemplateMenu extends PMOCommand {
|
|
6
|
-
static description = 'Interactive menu for project phase template operations';
|
|
7
|
-
static aliases = ['phase:templates'];
|
|
8
|
-
static examples = [
|
|
9
|
-
'<%= config.bin %> <%= command.id %>',
|
|
10
|
-
];
|
|
11
|
-
static flags = {
|
|
12
|
-
...pmoBaseFlags,
|
|
13
|
-
json: Flags.boolean({
|
|
14
|
-
char: 'm',
|
|
15
|
-
aliases: ['machine'],
|
|
16
|
-
description: 'Output prompt configuration as JSON (for AI agents/scripts)',
|
|
17
|
-
default: false,
|
|
18
|
-
}),
|
|
19
|
-
};
|
|
20
|
-
getPMOOptions() {
|
|
21
|
-
return { promptIfMultiple: false };
|
|
22
|
-
}
|
|
23
|
-
async execute() {
|
|
24
|
-
const { flags } = await this.parse(PhaseTemplateMenu);
|
|
25
|
-
// Check if JSON output mode is active
|
|
26
|
-
const jsonMode = shouldOutputJson(flags);
|
|
27
|
-
// Define choices once, use for both JSON and interactive modes
|
|
28
|
-
const menuChoices = [
|
|
29
|
-
{ name: 'List available templates', value: 'list' },
|
|
30
|
-
{ name: 'Apply template to workspace', value: 'apply' },
|
|
31
|
-
{ name: 'Save current phases as template', value: 'create' },
|
|
32
|
-
{ name: 'Update template', value: 'update' },
|
|
33
|
-
{ name: 'Delete template', value: 'delete' },
|
|
34
|
-
{ name: 'Cancel', value: 'cancel' },
|
|
35
|
-
];
|
|
36
|
-
const message = 'Phase Templates - What would you like to do?';
|
|
37
|
-
// In JSON mode, output menu prompt
|
|
38
|
-
if (jsonMode) {
|
|
39
|
-
outputPromptAsJson(buildPromptConfig('list', 'action', message, menuChoices), createMetadata('phase template', flags));
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
{
|
|
43
|
-
// Show interactive menu
|
|
44
|
-
const { action } = await inquirer.prompt([{
|
|
45
|
-
type: 'list',
|
|
46
|
-
name: 'action',
|
|
47
|
-
message: '📊 ' + message,
|
|
48
|
-
choices: [
|
|
49
|
-
...menuChoices.slice(0, 3),
|
|
50
|
-
new inquirer.Separator('──────────────'),
|
|
51
|
-
...menuChoices.slice(3),
|
|
52
|
-
],
|
|
53
|
-
}]);
|
|
54
|
-
if (action === 'cancel') {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
// Run the selected subcommand
|
|
58
|
-
switch (action) {
|
|
59
|
-
case 'list':
|
|
60
|
-
await this.config.runCommand('phase:template:list', []);
|
|
61
|
-
break;
|
|
62
|
-
case 'apply': {
|
|
63
|
-
const templateId = await this.selectTemplate(this.storage, 'Select template to apply:');
|
|
64
|
-
if (templateId) {
|
|
65
|
-
await this.config.runCommand('phase:template:apply', [templateId]);
|
|
66
|
-
}
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
|
-
case 'create': {
|
|
70
|
-
const { name } = await inquirer.prompt([{
|
|
71
|
-
type: 'input',
|
|
72
|
-
name: 'name',
|
|
73
|
-
message: 'Template name:',
|
|
74
|
-
validate: (input) => input.length > 0 || 'Name is required',
|
|
75
|
-
}]);
|
|
76
|
-
await this.config.runCommand('phase:template:create', [name]);
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
case 'update': {
|
|
80
|
-
const customTemplates = (await this.storage.listPhaseTemplates()).filter(t => !t.isBuiltin);
|
|
81
|
-
if (customTemplates.length === 0) {
|
|
82
|
-
this.log('No custom templates to update. Built-in templates cannot be modified.');
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
const templateId = await this.selectTemplate(this.storage, 'Select template to update:', true);
|
|
86
|
-
if (templateId) {
|
|
87
|
-
await this.config.runCommand('phase:template:update', [templateId]);
|
|
88
|
-
}
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
case 'delete': {
|
|
92
|
-
const customTemplates = (await this.storage.listPhaseTemplates()).filter(t => !t.isBuiltin);
|
|
93
|
-
if (customTemplates.length === 0) {
|
|
94
|
-
this.log('No custom templates to delete. Built-in templates cannot be deleted.');
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
const templateId = await this.selectTemplate(this.storage, 'Select template to delete:', true);
|
|
98
|
-
if (templateId) {
|
|
99
|
-
await this.config.runCommand('phase:template:delete', [templateId]);
|
|
100
|
-
}
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
async selectTemplate(storage, message, customOnly = false) {
|
|
107
|
-
let templates = await storage.listPhaseTemplates();
|
|
108
|
-
if (customOnly) {
|
|
109
|
-
templates = templates.filter(t => !t.isBuiltin);
|
|
110
|
-
}
|
|
111
|
-
if (templates.length === 0) {
|
|
112
|
-
this.log('No templates found.');
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
const { selected } = await inquirer.prompt([{
|
|
116
|
-
type: 'list',
|
|
117
|
-
name: 'selected',
|
|
118
|
-
message,
|
|
119
|
-
choices: [
|
|
120
|
-
...templates.map(t => ({
|
|
121
|
-
name: `${t.name} (${t.id})${t.isBuiltin ? '' : ' [custom]'}`,
|
|
122
|
-
value: t.id,
|
|
123
|
-
})),
|
|
124
|
-
new inquirer.Separator(),
|
|
125
|
-
{ name: 'Cancel', value: null },
|
|
126
|
-
],
|
|
127
|
-
}]);
|
|
128
|
-
return selected;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { PMOCommand } from '../../../lib/pmo/index.js';
|
|
2
|
-
export default class PhaseTemplateList extends PMOCommand {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static flags: {
|
|
6
|
-
builtin: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
-
custom: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
-
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
-
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
-
};
|
|
11
|
-
protected getPMOOptions(): {
|
|
12
|
-
promptIfMultiple: boolean;
|
|
13
|
-
};
|
|
14
|
-
execute(): Promise<void>;
|
|
15
|
-
private printTemplate;
|
|
16
|
-
}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { Flags } from '@oclif/core';
|
|
2
|
-
import { PMOCommand, pmoBaseFlags } from '../../../lib/pmo/index.js';
|
|
3
|
-
import { styles } from '../../../lib/styles.js';
|
|
4
|
-
export default class PhaseTemplateList extends PMOCommand {
|
|
5
|
-
static description = 'List available phase templates';
|
|
6
|
-
static examples = [
|
|
7
|
-
'<%= config.bin %> <%= command.id %>',
|
|
8
|
-
'<%= config.bin %> <%= command.id %> --builtin # Only built-in templates',
|
|
9
|
-
'<%= config.bin %> <%= command.id %> --custom # Only custom templates',
|
|
10
|
-
];
|
|
11
|
-
static flags = {
|
|
12
|
-
...pmoBaseFlags,
|
|
13
|
-
builtin: Flags.boolean({
|
|
14
|
-
description: 'Show only built-in templates',
|
|
15
|
-
exclusive: ['custom'],
|
|
16
|
-
}),
|
|
17
|
-
custom: Flags.boolean({
|
|
18
|
-
description: 'Show only custom templates',
|
|
19
|
-
exclusive: ['builtin'],
|
|
20
|
-
}),
|
|
21
|
-
json: Flags.boolean({
|
|
22
|
-
char: 'm',
|
|
23
|
-
aliases: ['machine'],
|
|
24
|
-
description: 'Output as JSON',
|
|
25
|
-
default: false,
|
|
26
|
-
}),
|
|
27
|
-
};
|
|
28
|
-
getPMOOptions() {
|
|
29
|
-
return { promptIfMultiple: false };
|
|
30
|
-
}
|
|
31
|
-
async execute() {
|
|
32
|
-
const { flags } = await this.parse(PhaseTemplateList);
|
|
33
|
-
let filter;
|
|
34
|
-
if (flags.builtin)
|
|
35
|
-
filter = { isBuiltin: true };
|
|
36
|
-
if (flags.custom)
|
|
37
|
-
filter = { isBuiltin: false };
|
|
38
|
-
const templates = await this.storage.listPhaseTemplates(filter);
|
|
39
|
-
if (flags.json) {
|
|
40
|
-
this.log(JSON.stringify(templates, null, 2));
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
if (templates.length === 0) {
|
|
44
|
-
this.log(styles.muted('\nNo phase templates found.'));
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
this.log(`\n📋 ${styles.emphasis('Phase Templates')}`);
|
|
48
|
-
this.log('═'.repeat(60));
|
|
49
|
-
// Group by builtin vs custom
|
|
50
|
-
const builtinTemplates = templates.filter(t => t.isBuiltin);
|
|
51
|
-
const customTemplates = templates.filter(t => !t.isBuiltin);
|
|
52
|
-
if (builtinTemplates.length > 0 && !flags.custom) {
|
|
53
|
-
this.log(`\n${styles.emphasis('Built-in Templates')}`);
|
|
54
|
-
this.log('─'.repeat(40));
|
|
55
|
-
for (const template of builtinTemplates) {
|
|
56
|
-
this.printTemplate(template);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
if (customTemplates.length > 0 && !flags.builtin) {
|
|
60
|
-
this.log(`\n${styles.emphasis('Custom Templates')}`);
|
|
61
|
-
this.log('─'.repeat(40));
|
|
62
|
-
for (const template of customTemplates) {
|
|
63
|
-
this.printTemplate(template);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
this.log('');
|
|
67
|
-
this.log(styles.muted('Apply a template: prlt template phase apply <template-id>'));
|
|
68
|
-
this.log('');
|
|
69
|
-
}
|
|
70
|
-
printTemplate(template) {
|
|
71
|
-
this.log(`\n ${styles.emphasis(template.name)} ${styles.muted(`(${template.id})`)}`);
|
|
72
|
-
if (template.description) {
|
|
73
|
-
this.log(` ${styles.muted(template.description)}`);
|
|
74
|
-
}
|
|
75
|
-
// Group phases by category for display
|
|
76
|
-
const categoryEmoji = {
|
|
77
|
-
triage: '📬',
|
|
78
|
-
backlog: '📥',
|
|
79
|
-
unstarted: '📋',
|
|
80
|
-
started: '🚀',
|
|
81
|
-
completed: '✅',
|
|
82
|
-
canceled: '🚫',
|
|
83
|
-
};
|
|
84
|
-
const phasesByCategory = new Map();
|
|
85
|
-
for (const phase of template.phases) {
|
|
86
|
-
const existing = phasesByCategory.get(phase.category) || [];
|
|
87
|
-
existing.push(phase.name);
|
|
88
|
-
phasesByCategory.set(phase.category, existing);
|
|
89
|
-
}
|
|
90
|
-
const phaseParts = [];
|
|
91
|
-
for (const [category, names] of phasesByCategory) {
|
|
92
|
-
const emoji = categoryEmoji[category];
|
|
93
|
-
phaseParts.push(`${emoji} ${names.join(', ')}`);
|
|
94
|
-
}
|
|
95
|
-
this.log(` ${styles.muted(phaseParts.join(' → '))}`);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
@@ -1,89 +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
|
-
export default class PhaseTemplateUpdate extends PMOCommand {
|
|
6
|
-
static description = 'Update a phase template';
|
|
7
|
-
static examples = [
|
|
8
|
-
'<%= config.bin %> <%= command.id %> my-template --name "New Name"',
|
|
9
|
-
'<%= config.bin %> <%= command.id %> my-template --description "Updated description"',
|
|
10
|
-
];
|
|
11
|
-
static args = {
|
|
12
|
-
id: Args.string({
|
|
13
|
-
description: 'Template ID to update',
|
|
14
|
-
required: false,
|
|
15
|
-
}),
|
|
16
|
-
};
|
|
17
|
-
static flags = {
|
|
18
|
-
...pmoBaseFlags,
|
|
19
|
-
name: Flags.string({
|
|
20
|
-
char: 'n',
|
|
21
|
-
description: 'New template name',
|
|
22
|
-
}),
|
|
23
|
-
description: Flags.string({
|
|
24
|
-
char: 'd',
|
|
25
|
-
description: 'New template description',
|
|
26
|
-
}),
|
|
27
|
-
};
|
|
28
|
-
getPMOOptions() {
|
|
29
|
-
return { promptIfMultiple: false };
|
|
30
|
-
}
|
|
31
|
-
async execute() {
|
|
32
|
-
const { args, flags } = await this.parse(PhaseTemplateUpdate);
|
|
33
|
-
// Get template ID - prompt for selection if not provided
|
|
34
|
-
let templateId = args.id;
|
|
35
|
-
if (!templateId) {
|
|
36
|
-
const templates = await this.storage.listPhaseTemplates();
|
|
37
|
-
const editableTemplates = templates.filter(t => !t.isBuiltin);
|
|
38
|
-
if (editableTemplates.length === 0) {
|
|
39
|
-
this.error('No editable phase templates found (built-in templates cannot be updated).');
|
|
40
|
-
}
|
|
41
|
-
const { selectedTemplate } = await inquirer.prompt([{
|
|
42
|
-
type: 'list',
|
|
43
|
-
name: 'selectedTemplate',
|
|
44
|
-
message: 'Select a template to update:',
|
|
45
|
-
choices: editableTemplates.map(t => ({
|
|
46
|
-
name: `${t.name}${t.description ? ` - ${t.description}` : ''}`,
|
|
47
|
-
value: t.id,
|
|
48
|
-
})),
|
|
49
|
-
}]);
|
|
50
|
-
templateId = selectedTemplate;
|
|
51
|
-
}
|
|
52
|
-
// If no flags provided, prompt for what to update
|
|
53
|
-
let newName = flags.name;
|
|
54
|
-
let newDescription = flags.description;
|
|
55
|
-
if (!newName && newDescription === undefined) {
|
|
56
|
-
const { updateName } = await inquirer.prompt([{
|
|
57
|
-
type: 'input',
|
|
58
|
-
name: 'updateName',
|
|
59
|
-
message: 'New name (leave empty to keep current):',
|
|
60
|
-
}]);
|
|
61
|
-
if (updateName)
|
|
62
|
-
newName = updateName;
|
|
63
|
-
const { updateDesc } = await inquirer.prompt([{
|
|
64
|
-
type: 'input',
|
|
65
|
-
name: 'updateDesc',
|
|
66
|
-
message: 'New description (leave empty to keep current):',
|
|
67
|
-
}]);
|
|
68
|
-
if (updateDesc)
|
|
69
|
-
newDescription = updateDesc;
|
|
70
|
-
if (!newName && !newDescription) {
|
|
71
|
-
this.log(styles.muted('No changes made.'));
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const changes = {};
|
|
76
|
-
if (newName)
|
|
77
|
-
changes.name = newName;
|
|
78
|
-
if (newDescription !== undefined)
|
|
79
|
-
changes.description = newDescription;
|
|
80
|
-
const template = await this.storage.updatePhaseTemplate(templateId, changes);
|
|
81
|
-
this.log(styles.success(`\nUpdated phase template "${styles.emphasis(template.name)}"`));
|
|
82
|
-
if (flags.name) {
|
|
83
|
-
this.log(styles.muted(` Name: ${template.name}`));
|
|
84
|
-
}
|
|
85
|
-
if (flags.description !== undefined) {
|
|
86
|
-
this.log(styles.muted(` Description: ${template.description || '(none)'}`));
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { PMOCommand } from '../../../lib/pmo/index.js';
|
|
2
|
-
export default class SpecLinkDepends extends PMOCommand {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static args: {
|
|
6
|
-
id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
-
target: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
|
-
};
|
|
9
|
-
static flags: {
|
|
10
|
-
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
-
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
};
|
|
13
|
-
execute(): Promise<void>;
|
|
14
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { 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 SpecLinkDepends extends PMOCommand {
|
|
7
|
-
static description = 'Add a depends_on dependency (spec requires another to be completed first)';
|
|
8
|
-
static examples = ['<%= config.bin %> <%= command.id %> my-feature other-spec'];
|
|
9
|
-
static args = {
|
|
10
|
-
id: Args.string({ description: 'Spec ID that depends on another', required: true }),
|
|
11
|
-
target: Args.string({ description: 'Spec ID that this spec depends on', required: false }),
|
|
12
|
-
};
|
|
13
|
-
static flags = {
|
|
14
|
-
...pmoBaseFlags,
|
|
15
|
-
};
|
|
16
|
-
async execute() {
|
|
17
|
-
const { args, flags } = await this.parse(SpecLinkDepends);
|
|
18
|
-
// Check if JSON output mode is active
|
|
19
|
-
const jsonMode = shouldOutputJson(flags);
|
|
20
|
-
// Helper to handle errors in JSON mode
|
|
21
|
-
const handleError = (code, message) => {
|
|
22
|
-
if (jsonMode) {
|
|
23
|
-
outputErrorAsJson(code, message, createMetadata('spec link depends', flags));
|
|
24
|
-
this.exit(1);
|
|
25
|
-
}
|
|
26
|
-
this.error(message);
|
|
27
|
-
};
|
|
28
|
-
const spec = await this.storage.getSpec(args.id);
|
|
29
|
-
if (!spec)
|
|
30
|
-
return handleError('SPEC_NOT_FOUND', `Spec not found: ${args.id}`);
|
|
31
|
-
let targetId = args.target;
|
|
32
|
-
if (!targetId) {
|
|
33
|
-
const allSpecs = await this.storage.listSpecs();
|
|
34
|
-
const otherSpecs = allSpecs.filter(s => s.id !== args.id);
|
|
35
|
-
if (otherSpecs.length === 0) {
|
|
36
|
-
if (jsonMode) {
|
|
37
|
-
outputErrorAsJson('NO_OTHER_SPECS', 'No other specs.', createMetadata('spec link depends', flags));
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
this.log(styles.muted('\nNo other specs.'));
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
// In JSON mode, output spec selection prompt
|
|
44
|
-
if (jsonMode) {
|
|
45
|
-
const specChoices = otherSpecs.map(s => ({
|
|
46
|
-
name: `${s.id} - ${s.title}`,
|
|
47
|
-
value: s.id,
|
|
48
|
-
command: `prlt spec link depends ${args.id} ${s.id} --json`,
|
|
49
|
-
}));
|
|
50
|
-
outputPromptAsJson(buildPromptConfig('list', 'target', `Select spec that ${args.id} depends on:`, specChoices), createMetadata('spec link depends', flags));
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
const { selected } = await inquirer.prompt([{ type: 'list', name: 'selected', message: `Select spec that ${args.id} depends on:`,
|
|
54
|
-
choices: otherSpecs.map(s => ({ name: `${s.id} - ${s.title}`, value: s.id })) }]);
|
|
55
|
-
targetId = selected;
|
|
56
|
-
}
|
|
57
|
-
const targetSpec = await this.storage.getSpec(targetId);
|
|
58
|
-
if (!targetSpec)
|
|
59
|
-
this.error(`Spec not found: ${targetId}`);
|
|
60
|
-
await this.storage.createSpecDependency(args.id, targetId, 'depends_on');
|
|
61
|
-
this.log(styles.success(`\n✅ ${styles.emphasis(args.id)} depends on ${styles.emphasis(targetId)}`));
|
|
62
|
-
this.log(styles.muted(` ${spec.title} depends on: ${targetSpec.title}`));
|
|
63
|
-
}
|
|
64
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { PMOCommand } from '../../../lib/pmo/index.js';
|
|
2
|
-
export default class SpecLinkDuplicates extends PMOCommand {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static args: {
|
|
6
|
-
id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
-
original: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
|
-
};
|
|
9
|
-
static flags: {
|
|
10
|
-
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
-
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
};
|
|
13
|
-
execute(): Promise<void>;
|
|
14
|
-
}
|