@proletariat/cli 0.3.24 → 0.3.26
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 +3 -3
- package/dist/commands/action/index.js +2 -2
- package/dist/commands/action/update.js +3 -3
- package/dist/commands/agent/auth.js +1 -1
- package/dist/commands/agent/cleanup.js +6 -6
- package/dist/commands/agent/discover.js +1 -1
- package/dist/commands/agent/remove.js +4 -4
- package/dist/commands/autocomplete/setup.d.ts +2 -2
- package/dist/commands/autocomplete/setup.js +5 -5
- package/dist/commands/branch/create.js +31 -30
- package/dist/commands/category/create.js +4 -5
- package/dist/commands/category/delete.js +2 -3
- package/dist/commands/category/rename.js +2 -3
- package/dist/commands/claude.d.ts +2 -8
- package/dist/commands/claude.js +26 -26
- package/dist/commands/commit.d.ts +2 -8
- package/dist/commands/commit.js +4 -26
- package/dist/commands/config/index.d.ts +2 -10
- package/dist/commands/config/index.js +8 -34
- package/dist/commands/docker/index.d.ts +2 -2
- package/dist/commands/docker/index.js +8 -8
- package/dist/commands/epic/activate.js +9 -17
- package/dist/commands/epic/archive.js +13 -24
- package/dist/commands/epic/create.js +7 -6
- package/dist/commands/epic/delete.js +4 -5
- 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/feedback/view.d.ts +15 -0
- package/dist/commands/feedback/view.js +109 -0
- package/dist/commands/gh/index.js +4 -0
- package/dist/commands/link/index.js +2 -2
- package/dist/commands/pmo/init.d.ts +2 -2
- package/dist/commands/pmo/init.js +7 -7
- package/dist/commands/project/spec.js +6 -6
- 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/health.d.ts +29 -0
- package/dist/commands/session/health.js +495 -0
- package/dist/commands/session/index.js +4 -0
- package/dist/commands/session/list.d.ts +0 -8
- package/dist/commands/session/list.js +130 -81
- package/dist/commands/spec/create.js +1 -1
- package/dist/commands/spec/edit.js +64 -35
- package/dist/commands/staff/add.d.ts +2 -2
- package/dist/commands/staff/add.js +15 -14
- package/dist/commands/staff/index.js +2 -2
- package/dist/commands/staff/remove.js +4 -4
- package/dist/commands/status/index.js +6 -7
- package/dist/commands/support/book.d.ts +10 -0
- package/dist/commands/support/book.js +54 -0
- package/dist/commands/support/discord.d.ts +10 -0
- 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/template/apply.js +10 -11
- package/dist/commands/template/create.js +18 -17
- package/dist/commands/template/index.d.ts +2 -2
- package/dist/commands/template/index.js +6 -6
- package/dist/commands/template/save.js +8 -7
- package/dist/commands/template/update.js +6 -7
- package/dist/commands/terminal/title.d.ts +2 -26
- package/dist/commands/terminal/title.js +4 -33
- package/dist/commands/theme/index.d.ts +2 -2
- package/dist/commands/theme/index.js +19 -18
- package/dist/commands/theme/set.d.ts +2 -2
- package/dist/commands/theme/set.js +5 -5
- package/dist/commands/ticket/create.js +52 -26
- package/dist/commands/ticket/delete.js +15 -13
- package/dist/commands/ticket/edit.js +59 -20
- package/dist/commands/ticket/epic.js +12 -10
- package/dist/commands/ticket/move.d.ts +7 -0
- package/dist/commands/ticket/move.js +132 -0
- package/dist/commands/ticket/project.js +11 -9
- package/dist/commands/ticket/reassign.js +23 -19
- package/dist/commands/ticket/spec.js +7 -5
- package/dist/commands/ticket/update.js +55 -53
- package/dist/commands/whoami.js +1 -0
- package/dist/commands/work/ready.js +7 -7
- package/dist/commands/work/revise.js +13 -11
- package/dist/commands/work/spawn.d.ts +1 -0
- package/dist/commands/work/spawn.js +225 -64
- package/dist/commands/work/start.d.ts +1 -0
- package/dist/commands/work/start.js +301 -173
- package/dist/hooks/init.js +4 -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/multiline-input.d.ts +63 -0
- package/dist/lib/multiline-input.js +360 -0
- package/dist/lib/pr/index.d.ts +4 -0
- package/dist/lib/pr/index.js +32 -14
- package/dist/lib/prompt-command.d.ts +3 -0
- package/dist/lib/prompt-json.d.ts +77 -6
- package/dist/lib/prompt-json.js +46 -0
- package/dist/lib/repos/git.d.ts +7 -0
- package/dist/lib/repos/git.js +20 -0
- package/oclif.manifest.json +2913 -2246
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PromptCommand } from '../lib/prompt-command.js';
|
|
2
2
|
/**
|
|
3
3
|
* Format context passed to format functions.
|
|
4
4
|
*/
|
|
@@ -50,7 +50,7 @@ export declare const COMMIT_FORMATS: {
|
|
|
50
50
|
};
|
|
51
51
|
export type CommitFormat = keyof typeof COMMIT_FORMATS;
|
|
52
52
|
export declare const DEFAULT_COMMIT_FORMAT: CommitFormat;
|
|
53
|
-
export default class Commit extends
|
|
53
|
+
export default class Commit extends PromptCommand {
|
|
54
54
|
static description: string;
|
|
55
55
|
static examples: string[];
|
|
56
56
|
static args: {
|
|
@@ -66,12 +66,6 @@ export default class Commit extends Command {
|
|
|
66
66
|
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
67
67
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
68
68
|
};
|
|
69
|
-
/**
|
|
70
|
-
* Prompt wrapper - handles both JSON mode and interactive mode.
|
|
71
|
-
* In JSON mode: outputs prompt as JSON and exits.
|
|
72
|
-
* In interactive mode: calls inquirer.prompt normally.
|
|
73
|
-
*/
|
|
74
|
-
private prompt;
|
|
75
69
|
run(): Promise<void>;
|
|
76
70
|
}
|
|
77
71
|
export {};
|
package/dist/commands/commit.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
2
|
import { execSync } from 'node:child_process';
|
|
3
|
-
import
|
|
3
|
+
import { PromptCommand } from '../lib/prompt-command.js';
|
|
4
4
|
import { validateBranchName } from '../lib/branch/index.js';
|
|
5
5
|
import { styles } from '../lib/styles.js';
|
|
6
|
-
import { shouldOutputJson,
|
|
6
|
+
import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../lib/prompt-json.js';
|
|
7
7
|
/**
|
|
8
8
|
* Commit message format presets.
|
|
9
9
|
*/
|
|
@@ -140,7 +140,7 @@ function branchTypeToCommitType(branchType) {
|
|
|
140
140
|
};
|
|
141
141
|
return mapping[branchType] || branchType;
|
|
142
142
|
}
|
|
143
|
-
export default class Commit extends
|
|
143
|
+
export default class Commit extends PromptCommand {
|
|
144
144
|
static description = 'Create a commit with ticket ID from branch name';
|
|
145
145
|
static examples = [
|
|
146
146
|
'<%= config.bin %> <%= command.id %> # interactive mode',
|
|
@@ -197,28 +197,6 @@ export default class Commit extends Command {
|
|
|
197
197
|
default: false,
|
|
198
198
|
}),
|
|
199
199
|
};
|
|
200
|
-
/**
|
|
201
|
-
* Prompt wrapper - handles both JSON mode and interactive mode.
|
|
202
|
-
* In JSON mode: outputs prompt as JSON and exits.
|
|
203
|
-
* In interactive mode: calls inquirer.prompt normally.
|
|
204
|
-
*/
|
|
205
|
-
async prompt(questions, jsonModeConfig) {
|
|
206
|
-
if (jsonModeConfig && isAgentMode(jsonModeConfig.flags)) {
|
|
207
|
-
const firstQuestion = questions[0];
|
|
208
|
-
if (firstQuestion) {
|
|
209
|
-
const choices = firstQuestion.choices ? normalizeChoices(firstQuestion.choices) : undefined;
|
|
210
|
-
outputPromptAsJson({
|
|
211
|
-
type: firstQuestion.type,
|
|
212
|
-
name: firstQuestion.name,
|
|
213
|
-
message: firstQuestion.message,
|
|
214
|
-
choices,
|
|
215
|
-
default: firstQuestion.default,
|
|
216
|
-
}, createMetadata(jsonModeConfig.commandName, jsonModeConfig.flags));
|
|
217
|
-
}
|
|
218
|
-
return {};
|
|
219
|
-
}
|
|
220
|
-
return inquirer.prompt(questions);
|
|
221
|
-
}
|
|
222
200
|
async run() {
|
|
223
201
|
const { args, flags } = await this.parse(Commit);
|
|
224
202
|
// Check if JSON output mode is active
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class Config extends
|
|
1
|
+
import { PromptCommand } from '../../lib/prompt-command.js';
|
|
2
|
+
export default class Config extends PromptCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static flags: {
|
|
@@ -8,14 +8,6 @@ export default class Config extends Command {
|
|
|
8
8
|
list: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
9
|
setting: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
};
|
|
11
|
-
/**
|
|
12
|
-
* Prompt wrapper - drop-in replacement for inquirer.prompt
|
|
13
|
-
*
|
|
14
|
-
* Works in BOTH modes:
|
|
15
|
-
* - Interactive mode: calls inquirer.prompt normally (human sees menu)
|
|
16
|
-
* - JSON/Agent mode: outputs prompt as structured JSON and exits
|
|
17
|
-
*/
|
|
18
|
-
private promptUser;
|
|
19
11
|
run(): Promise<void>;
|
|
20
12
|
/**
|
|
21
13
|
* Handle a specific setting's sub-prompt
|
|
@@ -2,12 +2,12 @@ import { Flags } from '@oclif/core';
|
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import Database from 'better-sqlite3';
|
|
4
4
|
import inquirer from 'inquirer';
|
|
5
|
-
import {
|
|
5
|
+
import { PromptCommand } from '../../lib/prompt-command.js';
|
|
6
6
|
import { styles } from '../../lib/styles.js';
|
|
7
7
|
import { getWorkspaceInfo } from '../../lib/agents/commands.js';
|
|
8
8
|
import { loadExecutionConfig, saveTerminalApp, saveTerminalOpenInBackground, saveTmuxControlMode, saveShell, } from '../../lib/execution/config.js';
|
|
9
|
-
import { shouldOutputJson,
|
|
10
|
-
export default class Config extends
|
|
9
|
+
import { shouldOutputJson, isNonTTY, outputSuccessAsJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
|
|
10
|
+
export default class Config extends PromptCommand {
|
|
11
11
|
static description = 'View and update workspace configuration';
|
|
12
12
|
static examples = [
|
|
13
13
|
'<%= config.bin %> <%= command.id %> # Interactive menu',
|
|
@@ -37,32 +37,6 @@ export default class Config extends Command {
|
|
|
37
37
|
description: 'Navigate to a specific setting prompt (for agent navigation)',
|
|
38
38
|
}),
|
|
39
39
|
};
|
|
40
|
-
/**
|
|
41
|
-
* Prompt wrapper - drop-in replacement for inquirer.prompt
|
|
42
|
-
*
|
|
43
|
-
* Works in BOTH modes:
|
|
44
|
-
* - Interactive mode: calls inquirer.prompt normally (human sees menu)
|
|
45
|
-
* - JSON/Agent mode: outputs prompt as structured JSON and exits
|
|
46
|
-
*/
|
|
47
|
-
async promptUser(questions, jsonModeConfig) {
|
|
48
|
-
if (jsonModeConfig && isAgentMode(jsonModeConfig.flags)) {
|
|
49
|
-
const firstQuestion = questions[0];
|
|
50
|
-
if (firstQuestion) {
|
|
51
|
-
const choices = firstQuestion.choices
|
|
52
|
-
? normalizeChoices(firstQuestion.choices)
|
|
53
|
-
: undefined;
|
|
54
|
-
outputPromptAsJson({
|
|
55
|
-
type: firstQuestion.type,
|
|
56
|
-
name: firstQuestion.name,
|
|
57
|
-
message: firstQuestion.message,
|
|
58
|
-
choices,
|
|
59
|
-
default: firstQuestion.default,
|
|
60
|
-
}, createMetadata(jsonModeConfig.commandName, jsonModeConfig.flags));
|
|
61
|
-
}
|
|
62
|
-
return {};
|
|
63
|
-
}
|
|
64
|
-
return inquirer.prompt(questions);
|
|
65
|
-
}
|
|
66
40
|
async run() {
|
|
67
41
|
const { flags } = await this.parse(Config);
|
|
68
42
|
const jsonMode = shouldOutputJson(flags);
|
|
@@ -163,7 +137,7 @@ export default class Config extends Command {
|
|
|
163
137
|
{ name: `Shell: ${config.shell}`, value: 'shell', command: 'prlt config --setting shell --json' },
|
|
164
138
|
{ name: `Tmux Control Mode (iTerm -CC): ${config.tmux.controlMode}`, value: 'tmux.controlMode', command: 'prlt config --setting tmux.controlMode --json' },
|
|
165
139
|
];
|
|
166
|
-
const { setting } = await this.
|
|
140
|
+
const { setting } = await this.prompt([
|
|
167
141
|
{
|
|
168
142
|
type: 'list',
|
|
169
143
|
name: 'setting',
|
|
@@ -209,7 +183,7 @@ export default class Config extends Command {
|
|
|
209
183
|
{ name: 'Warp', value: 'Warp', command: 'prlt config --set "terminal.app Warp" --json' },
|
|
210
184
|
{ name: 'tmux', value: 'tmux', command: 'prlt config --set "terminal.app tmux" --json' },
|
|
211
185
|
];
|
|
212
|
-
const { newApp } = await this.
|
|
186
|
+
const { newApp } = await this.prompt([
|
|
213
187
|
{
|
|
214
188
|
type: 'list',
|
|
215
189
|
name: 'newApp',
|
|
@@ -227,7 +201,7 @@ export default class Config extends Command {
|
|
|
227
201
|
{ name: 'Yes - Open tabs in background (don\'t steal focus)', value: 'true', command: 'prlt config --set "terminal.openInBackground true" --json' },
|
|
228
202
|
{ name: 'No - Bring terminal to foreground when opening tabs', value: 'false', command: 'prlt config --set "terminal.openInBackground false" --json' },
|
|
229
203
|
];
|
|
230
|
-
const { openInBg } = await this.
|
|
204
|
+
const { openInBg } = await this.prompt([
|
|
231
205
|
{
|
|
232
206
|
type: 'list',
|
|
233
207
|
name: 'openInBg',
|
|
@@ -246,7 +220,7 @@ export default class Config extends Command {
|
|
|
246
220
|
{ name: 'bash', value: 'bash', command: 'prlt config --set "shell bash" --json' },
|
|
247
221
|
{ name: 'fish', value: 'fish', command: 'prlt config --set "shell fish" --json' },
|
|
248
222
|
];
|
|
249
|
-
const { newShell } = await this.
|
|
223
|
+
const { newShell } = await this.prompt([
|
|
250
224
|
{
|
|
251
225
|
type: 'list',
|
|
252
226
|
name: 'newShell',
|
|
@@ -264,7 +238,7 @@ export default class Config extends Command {
|
|
|
264
238
|
{ name: 'Yes - Use tmux -CC for native iTerm integration', value: 'true', command: 'prlt config --set "tmux.controlMode true" --json' },
|
|
265
239
|
{ name: 'No - Standard tmux interface', value: 'false', command: 'prlt config --set "tmux.controlMode false" --json' },
|
|
266
240
|
];
|
|
267
|
-
const { controlMode } = await this.
|
|
241
|
+
const { controlMode } = await this.prompt([
|
|
268
242
|
{
|
|
269
243
|
type: 'list',
|
|
270
244
|
name: 'controlMode',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class Docker extends
|
|
1
|
+
import { PromptCommand } from '../../lib/prompt-command.js';
|
|
2
|
+
export default class Docker extends PromptCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static flags: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Command } from '@oclif/core';
|
|
2
1
|
import inquirer from 'inquirer';
|
|
2
|
+
import { PromptCommand } from '../../lib/prompt-command.js';
|
|
3
3
|
import { execSync } from 'node:child_process';
|
|
4
4
|
import * as path from 'node:path';
|
|
5
5
|
import Database from 'better-sqlite3';
|
|
@@ -9,7 +9,7 @@ import { ExecutionStorage, ContainerStorage } from '../../lib/execution/storage.
|
|
|
9
9
|
import { isDockerRunning } from '../../lib/execution/runners.js';
|
|
10
10
|
import { FlagResolver, shouldOutputJson } from '../../lib/flags/index.js';
|
|
11
11
|
import { machineOutputFlags } from '../../lib/pmo/base-command.js';
|
|
12
|
-
export default class Docker extends
|
|
12
|
+
export default class Docker extends PromptCommand {
|
|
13
13
|
static description = 'Manage Docker containers used by agents';
|
|
14
14
|
static examples = [
|
|
15
15
|
'<%= config.bin %> <%= command.id %>',
|
|
@@ -198,17 +198,17 @@ export default class Docker extends Command {
|
|
|
198
198
|
db.close();
|
|
199
199
|
if (choices.length <= 2) {
|
|
200
200
|
// Only manual option, just ask for input
|
|
201
|
-
const { target } = await
|
|
201
|
+
const { target } = await this.prompt([
|
|
202
202
|
{
|
|
203
203
|
type: 'input',
|
|
204
204
|
name: 'target',
|
|
205
205
|
message: 'No containers found. Enter container ID:',
|
|
206
206
|
validate: (input) => input.trim().length > 0 || 'Target is required',
|
|
207
207
|
},
|
|
208
|
-
]);
|
|
208
|
+
], null);
|
|
209
209
|
return target.trim();
|
|
210
210
|
}
|
|
211
|
-
const { target } = await
|
|
211
|
+
const { target } = await this.prompt([
|
|
212
212
|
{
|
|
213
213
|
type: 'list',
|
|
214
214
|
name: 'target',
|
|
@@ -216,19 +216,19 @@ export default class Docker extends Command {
|
|
|
216
216
|
choices,
|
|
217
217
|
pageSize: 15,
|
|
218
218
|
},
|
|
219
|
-
]);
|
|
219
|
+
], null);
|
|
220
220
|
if (target === '__cancel__') {
|
|
221
221
|
return null;
|
|
222
222
|
}
|
|
223
223
|
if (target === '__manual__') {
|
|
224
|
-
const { manualTarget } = await
|
|
224
|
+
const { manualTarget } = await this.prompt([
|
|
225
225
|
{
|
|
226
226
|
type: 'input',
|
|
227
227
|
name: 'manualTarget',
|
|
228
228
|
message: 'Enter execution ID (WORK-XXX), agent name, or container ID:',
|
|
229
229
|
validate: (input) => input.trim().length > 0 || 'Target is required',
|
|
230
230
|
},
|
|
231
|
-
]);
|
|
231
|
+
], null);
|
|
232
232
|
return manualTarget.trim();
|
|
233
233
|
}
|
|
234
234
|
return target;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
2
|
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
3
|
import { styles } from '../../lib/styles.js';
|
|
5
4
|
import { moveEpicFile, getRelativeEpicPath } from '../../lib/pmo/epic-files.js';
|
|
6
|
-
import { shouldOutputJson,
|
|
5
|
+
import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
|
|
7
6
|
export default class EpicActivate extends PMOCommand {
|
|
8
7
|
static description = 'Activate a draft or archived epic';
|
|
9
8
|
static examples = [
|
|
@@ -76,26 +75,19 @@ export default class EpicActivate extends PMOCommand {
|
|
|
76
75
|
if (epic.status === 'complete') {
|
|
77
76
|
const tickets = await this.storage.getTicketsForEpic(projectId, epicId);
|
|
78
77
|
const doneTickets = tickets.filter((t) => t.status === 'done').length;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const confirmChoices = [
|
|
82
|
-
{ name: 'No', value: 'false' },
|
|
83
|
-
{ name: 'Yes', value: 'true' },
|
|
84
|
-
];
|
|
85
|
-
outputPromptAsJson(buildPromptConfig('list', 'confirm', `This epic was previously completed (${doneTickets}/${tickets.length} tickets done). Reactivate this epic?`, confirmChoices), createMetadata('epic activate', flags));
|
|
86
|
-
return;
|
|
78
|
+
if (!jsonMode) {
|
|
79
|
+
this.log(styles.warning(`\n⚠️ This epic was previously completed (${doneTickets}/${tickets.length} tickets done)`));
|
|
87
80
|
}
|
|
88
|
-
|
|
89
|
-
const { confirm } = await
|
|
81
|
+
const jsonModeConfig = jsonMode ? { flags, commandName: 'epic activate' } : null;
|
|
82
|
+
const { confirm } = await this.prompt([{
|
|
90
83
|
type: 'list',
|
|
91
84
|
name: 'confirm',
|
|
92
|
-
message:
|
|
85
|
+
message: `This epic was previously completed (${doneTickets}/${tickets.length} tickets done). Reactivate this epic?`,
|
|
93
86
|
choices: [
|
|
94
|
-
{ name: 'No', value: false },
|
|
95
|
-
{ name: 'Yes', value: true },
|
|
87
|
+
{ name: 'No', value: false, command: '' },
|
|
88
|
+
{ name: 'Yes', value: true, command: `prlt epic activate ${epicId} --json` },
|
|
96
89
|
],
|
|
97
|
-
|
|
98
|
-
}]);
|
|
90
|
+
}], jsonModeConfig);
|
|
99
91
|
if (!confirm) {
|
|
100
92
|
this.log(styles.muted('Cancelled.'));
|
|
101
93
|
return;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
2
|
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
3
|
import { styles } from '../../lib/styles.js';
|
|
5
4
|
import { moveEpicFile, getRelativeEpicPath } from '../../lib/pmo/epic-files.js';
|
|
6
|
-
import { shouldOutputJson,
|
|
5
|
+
import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
|
|
7
6
|
export default class EpicArchive extends PMOCommand {
|
|
8
7
|
static description = 'Archive a completed epic';
|
|
9
8
|
static examples = [
|
|
@@ -64,19 +63,16 @@ export default class EpicArchive extends PMOCommand {
|
|
|
64
63
|
return {
|
|
65
64
|
name: `${e.id} ${e.title} (${e.status}) [${done}/${tickets.length} tickets complete]${complete ? ' ✅' : ''}`,
|
|
66
65
|
value: e.id,
|
|
66
|
+
command: `prlt epic archive ${e.id} --json`,
|
|
67
67
|
};
|
|
68
68
|
}));
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
outputPromptAsJson(buildPromptConfig('list', 'id', 'Select epic to archive:', choices), createMetadata('epic archive', flags));
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const { selected } = await inquirer.prompt([{
|
|
69
|
+
const jsonModeConfig = jsonMode ? { flags, commandName: 'epic archive' } : null;
|
|
70
|
+
const { selected } = await this.prompt([{
|
|
75
71
|
type: 'list',
|
|
76
72
|
name: 'selected',
|
|
77
73
|
message: 'Select epic to archive:',
|
|
78
74
|
choices,
|
|
79
|
-
}]);
|
|
75
|
+
}], jsonModeConfig);
|
|
80
76
|
epicId = selected;
|
|
81
77
|
}
|
|
82
78
|
const epic = await this.storage.getEpic(epicId);
|
|
@@ -92,26 +88,19 @@ export default class EpicArchive extends PMOCommand {
|
|
|
92
88
|
const doneTickets = tickets.filter((t) => t.status === 'done').length;
|
|
93
89
|
const allComplete = doneTickets === tickets.length;
|
|
94
90
|
if (!allComplete && !flags.force) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const confirmChoices = [
|
|
98
|
-
{ name: 'No', value: 'false' },
|
|
99
|
-
{ name: 'Yes', value: 'true' },
|
|
100
|
-
];
|
|
101
|
-
outputPromptAsJson(buildPromptConfig('list', 'confirm', `Not all tickets are complete (${doneTickets}/${tickets.length} done). Continue archiving anyway?`, confirmChoices), createMetadata('epic archive', flags));
|
|
102
|
-
return;
|
|
91
|
+
if (!jsonMode) {
|
|
92
|
+
this.log(styles.warning(`\n⚠️ Not all tickets are complete (${doneTickets}/${tickets.length} done)`));
|
|
103
93
|
}
|
|
104
|
-
|
|
105
|
-
const { confirm } = await
|
|
94
|
+
const jsonModeConfig = jsonMode ? { flags, commandName: 'epic archive' } : null;
|
|
95
|
+
const { confirm } = await this.prompt([{
|
|
106
96
|
type: 'list',
|
|
107
97
|
name: 'confirm',
|
|
108
|
-
message:
|
|
98
|
+
message: `Not all tickets are complete (${doneTickets}/${tickets.length} done). Continue archiving anyway?`,
|
|
109
99
|
choices: [
|
|
110
|
-
{ name: 'No', value: false },
|
|
111
|
-
{ name: 'Yes', value: true },
|
|
100
|
+
{ name: 'No', value: false, command: '' },
|
|
101
|
+
{ name: 'Yes', value: true, command: `prlt epic archive ${epicId} --force --json` },
|
|
112
102
|
],
|
|
113
|
-
|
|
114
|
-
}]);
|
|
103
|
+
}], jsonModeConfig);
|
|
115
104
|
if (!confirm) {
|
|
116
105
|
this.log(styles.muted('Cancelled.'));
|
|
117
106
|
return;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
2
|
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
3
|
import { styles } from '../../lib/styles.js';
|
|
5
4
|
import { createEpicFile, getRelativeEpicPath } from '../../lib/pmo/epic-files.js';
|
|
@@ -81,7 +80,7 @@ export default class EpicCreate extends PMOCommand {
|
|
|
81
80
|
if (jsonMode) {
|
|
82
81
|
outputPromptAsJson(buildFormPromptConfig(fields), createMetadata('epic create', flags));
|
|
83
82
|
}
|
|
84
|
-
epicData = await this.promptEpicData(fields, specChoices.length > 1);
|
|
83
|
+
epicData = await this.promptEpicData(fields, specChoices.length > 1, jsonMode ? { flags, commandName: 'epic create' } : null);
|
|
85
84
|
}
|
|
86
85
|
else {
|
|
87
86
|
epicData = {
|
|
@@ -157,15 +156,17 @@ export default class EpicCreate extends PMOCommand {
|
|
|
157
156
|
this.log(styles.muted(` prlt ticket create --epic ${epic.id} "Design auth flow"`));
|
|
158
157
|
this.log(styles.muted(` 3. View progress: prlt epic progress ${epic.id}`));
|
|
159
158
|
}
|
|
160
|
-
async promptEpicData(fields, hasSpecs) {
|
|
159
|
+
async promptEpicData(fields, hasSpecs, jsonModeConfig) {
|
|
161
160
|
// Build inquirer prompts from fields, adding validators and conditionals
|
|
162
|
-
const
|
|
161
|
+
const promptFields = fields
|
|
162
|
+
.filter(field => field.name !== 'specId' || hasSpecs)
|
|
163
|
+
.map(field => ({
|
|
163
164
|
...field,
|
|
164
165
|
validate: field.name === 'title'
|
|
165
166
|
? ((input) => input.trim() ? true : 'Title cannot be empty')
|
|
166
167
|
: undefined,
|
|
167
|
-
|
|
168
|
-
|
|
168
|
+
}));
|
|
169
|
+
const answers = await this.prompt(promptFields, jsonModeConfig);
|
|
169
170
|
return {
|
|
170
171
|
title: answers.title,
|
|
171
172
|
status: answers.status,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
2
|
import { autoExportToBoard, PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
3
|
import { styles } from '../../lib/styles.js';
|
|
5
4
|
import { deleteEpicFile } from '../../lib/pmo/epic-files.js';
|
|
@@ -67,12 +66,12 @@ export default class EpicDelete extends PMOCommand {
|
|
|
67
66
|
outputPromptAsJson(buildPromptConfig('list', 'id', 'Select epic to delete:', choices), createMetadata('epic delete', flags));
|
|
68
67
|
return;
|
|
69
68
|
}
|
|
70
|
-
const { selected } = await
|
|
69
|
+
const { selected } = await this.prompt([{
|
|
71
70
|
type: 'list',
|
|
72
71
|
name: 'selected',
|
|
73
72
|
message: 'Select epic to delete:',
|
|
74
73
|
choices,
|
|
75
|
-
}]);
|
|
74
|
+
}], null);
|
|
76
75
|
epicId = selected;
|
|
77
76
|
}
|
|
78
77
|
// Get the epic to show details
|
|
@@ -97,7 +96,7 @@ export default class EpicDelete extends PMOCommand {
|
|
|
97
96
|
this.log(` Title: ${epic.title}`);
|
|
98
97
|
this.log(` Status: ${epic.status}`);
|
|
99
98
|
this.log(` Tickets: ${tickets.length} (will be unlinked, not deleted)`);
|
|
100
|
-
const { confirmed } = await
|
|
99
|
+
const { confirmed } = await this.prompt([{
|
|
101
100
|
type: 'list',
|
|
102
101
|
name: 'confirmed',
|
|
103
102
|
message: `Delete epic '${epic.title}'?`,
|
|
@@ -106,7 +105,7 @@ export default class EpicDelete extends PMOCommand {
|
|
|
106
105
|
{ name: 'Yes, delete permanently', value: true },
|
|
107
106
|
],
|
|
108
107
|
default: 0,
|
|
109
|
-
}]);
|
|
108
|
+
}], null);
|
|
110
109
|
if (!confirmed) {
|
|
111
110
|
this.log(styles.muted('Deletion cancelled.'));
|
|
112
111
|
return;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
2
|
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
3
|
import { styles } from '../../lib/styles.js';
|
|
5
4
|
import { moveEpicFile, getRelativeEpicPath } from '../../lib/pmo/epic-files.js';
|
|
6
|
-
import { shouldOutputJson,
|
|
5
|
+
import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
|
|
7
6
|
const STATUS_CHOICES = [
|
|
8
7
|
{ name: 'active (currently working on)', value: 'active' },
|
|
9
8
|
{ name: 'draft (planning phase)', value: 'draft' },
|
|
@@ -75,19 +74,16 @@ export default class EpicMove extends PMOCommand {
|
|
|
75
74
|
return {
|
|
76
75
|
name: `${e.id} ${e.title} (${e.status}) [${done}/${tickets.length} complete]`,
|
|
77
76
|
value: e.id,
|
|
77
|
+
command: `prlt epic move ${e.id} --json`,
|
|
78
78
|
};
|
|
79
79
|
}));
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
outputPromptAsJson(buildPromptConfig('list', 'id', 'Select epic to move:', choices), createMetadata('epic move', flags));
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
const { selected } = await inquirer.prompt([{
|
|
80
|
+
const jsonModeConfig = jsonMode ? { flags, commandName: 'epic move' } : null;
|
|
81
|
+
const { selected } = await this.prompt([{
|
|
86
82
|
type: 'list',
|
|
87
83
|
name: 'selected',
|
|
88
84
|
message: 'Select epic to move:',
|
|
89
85
|
choices,
|
|
90
|
-
}]);
|
|
86
|
+
}], jsonModeConfig);
|
|
91
87
|
epicId = selected;
|
|
92
88
|
}
|
|
93
89
|
const epic = await this.storage.getEpic(epicId);
|
|
@@ -96,18 +92,17 @@ export default class EpicMove extends PMOCommand {
|
|
|
96
92
|
}
|
|
97
93
|
// If no status provided, prompt for selection
|
|
98
94
|
if (!targetStatus) {
|
|
99
|
-
const statusChoices = STATUS_CHOICES.filter(c => c.value !== epic.status)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
const { selected } = await inquirer.prompt([{
|
|
95
|
+
const statusChoices = STATUS_CHOICES.filter(c => c.value !== epic.status).map(c => ({
|
|
96
|
+
...c,
|
|
97
|
+
command: `prlt epic move ${epicId} ${c.value} --json`,
|
|
98
|
+
}));
|
|
99
|
+
const jsonModeConfig = jsonMode ? { flags, commandName: 'epic move' } : null;
|
|
100
|
+
const { selected } = await this.prompt([{
|
|
106
101
|
type: 'list',
|
|
107
102
|
name: 'selected',
|
|
108
103
|
message: 'Move to which status?',
|
|
109
104
|
choices: statusChoices,
|
|
110
|
-
}]);
|
|
105
|
+
}], jsonModeConfig);
|
|
111
106
|
targetStatus = selected;
|
|
112
107
|
}
|
|
113
108
|
if (targetStatus === epic.status) {
|
|
@@ -120,26 +115,19 @@ export default class EpicMove extends PMOCommand {
|
|
|
120
115
|
const allComplete = doneTickets === tickets.length;
|
|
121
116
|
// Moving to complete - check ticket completion
|
|
122
117
|
if (targetStatus === 'complete' && !allComplete && !flags.force) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const confirmChoices = [
|
|
126
|
-
{ name: 'No', value: 'false' },
|
|
127
|
-
{ name: 'Yes', value: 'true' },
|
|
128
|
-
];
|
|
129
|
-
outputPromptAsJson(buildPromptConfig('list', 'confirm', `Not all tickets are complete (${doneTickets}/${tickets.length} done). Continue moving to complete anyway?`, confirmChoices), createMetadata('epic move', flags));
|
|
130
|
-
return;
|
|
118
|
+
if (!jsonMode) {
|
|
119
|
+
this.log(styles.warning(`\n⚠️ Not all tickets are complete (${doneTickets}/${tickets.length} done)`));
|
|
131
120
|
}
|
|
132
|
-
|
|
133
|
-
const { confirm } = await
|
|
121
|
+
const jsonModeConfig = jsonMode ? { flags, commandName: 'epic move' } : null;
|
|
122
|
+
const { confirm } = await this.prompt([{
|
|
134
123
|
type: 'list',
|
|
135
124
|
name: 'confirm',
|
|
136
|
-
message:
|
|
125
|
+
message: `Not all tickets are complete (${doneTickets}/${tickets.length} done). Continue moving to complete anyway?`,
|
|
137
126
|
choices: [
|
|
138
|
-
{ name: 'No', value: false },
|
|
139
|
-
{ name: 'Yes', value: true },
|
|
127
|
+
{ name: 'No', value: false, command: '' },
|
|
128
|
+
{ name: 'Yes', value: true, command: `prlt epic move ${epicId} complete --force --json` },
|
|
140
129
|
],
|
|
141
|
-
|
|
142
|
-
}]);
|
|
130
|
+
}], jsonModeConfig);
|
|
143
131
|
if (!confirm) {
|
|
144
132
|
this.log(styles.muted('Cancelled.'));
|
|
145
133
|
return;
|
|
@@ -147,26 +135,19 @@ export default class EpicMove extends PMOCommand {
|
|
|
147
135
|
}
|
|
148
136
|
// Moving to dropped - confirm cancellation
|
|
149
137
|
if (targetStatus === 'dropped' && !flags.force) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const confirmChoices = [
|
|
153
|
-
{ name: 'No', value: 'false' },
|
|
154
|
-
{ name: 'Yes', value: 'true' },
|
|
155
|
-
];
|
|
156
|
-
outputPromptAsJson(buildPromptConfig('list', 'confirmDrop', 'This will mark the epic as dropped/cancelled. Continue?', confirmChoices), createMetadata('epic move', flags));
|
|
157
|
-
return;
|
|
138
|
+
if (!jsonMode) {
|
|
139
|
+
this.log(styles.warning('\n⚠️ This will mark the epic as dropped/cancelled'));
|
|
158
140
|
}
|
|
159
|
-
|
|
160
|
-
const { confirm } = await
|
|
141
|
+
const jsonModeConfig = jsonMode ? { flags, commandName: 'epic move' } : null;
|
|
142
|
+
const { confirm } = await this.prompt([{
|
|
161
143
|
type: 'list',
|
|
162
144
|
name: 'confirm',
|
|
163
|
-
message: 'Continue?',
|
|
145
|
+
message: 'This will mark the epic as dropped/cancelled. Continue?',
|
|
164
146
|
choices: [
|
|
165
|
-
{ name: 'No', value: false },
|
|
166
|
-
{ name: 'Yes', value: true },
|
|
147
|
+
{ name: 'No', value: false, command: '' },
|
|
148
|
+
{ name: 'Yes', value: true, command: `prlt epic move ${epicId} dropped --force --json` },
|
|
167
149
|
],
|
|
168
|
-
|
|
169
|
-
}]);
|
|
150
|
+
}], jsonModeConfig);
|
|
170
151
|
if (!confirm) {
|
|
171
152
|
this.log(styles.muted('Cancelled.'));
|
|
172
153
|
return;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
2
|
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
4
3
|
import { styles } from '../../lib/styles.js';
|
|
5
4
|
import { getRelativeEpicPath } from '../../lib/pmo/epic-files.js';
|
|
6
|
-
import { shouldOutputJson,
|
|
5
|
+
import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
|
|
7
6
|
// Progress bar helper
|
|
8
7
|
function progressBar(percent, width = 20) {
|
|
9
8
|
const filled = Math.round((percent / 100) * width);
|
|
@@ -57,21 +56,18 @@ export default class EpicProgress extends PMOCommand {
|
|
|
57
56
|
this.log(styles.muted('\nNo epics found.'));
|
|
58
57
|
return;
|
|
59
58
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
const { selected } = await
|
|
59
|
+
const epicChoices = epics.map(e => ({
|
|
60
|
+
name: `${e.id} ${e.title} (${e.status})`,
|
|
61
|
+
value: e.id,
|
|
62
|
+
command: `prlt epic progress ${e.id} --json`,
|
|
63
|
+
}));
|
|
64
|
+
const jsonModeConfig = jsonMode ? { flags, commandName: 'epic progress' } : null;
|
|
65
|
+
const { selected } = await this.prompt([{
|
|
67
66
|
type: 'list',
|
|
68
67
|
name: 'selected',
|
|
69
68
|
message: 'Select epic to view progress:',
|
|
70
|
-
choices:
|
|
71
|
-
|
|
72
|
-
value: e.id,
|
|
73
|
-
})),
|
|
74
|
-
}]);
|
|
69
|
+
choices: epicChoices,
|
|
70
|
+
}], jsonModeConfig);
|
|
75
71
|
epicId = selected;
|
|
76
72
|
}
|
|
77
73
|
await this.showSingleProgress(projectId, epicId);
|