@proletariat/cli 0.3.34 → 0.3.35

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.
Files changed (118) hide show
  1. package/dist/commands/agent/auth.d.ts +3 -1
  2. package/dist/commands/agent/auth.js +8 -11
  3. package/dist/commands/agent/index.js +11 -2
  4. package/dist/commands/agent/staff/add.d.ts +1 -0
  5. package/dist/commands/agent/staff/add.js +1 -0
  6. package/dist/commands/agent/staff/index.d.ts +15 -0
  7. package/dist/commands/agent/staff/index.js +83 -0
  8. package/dist/commands/agent/staff/list.d.ts +1 -0
  9. package/dist/commands/agent/staff/list.js +1 -0
  10. package/dist/commands/agent/staff/remove.d.ts +1 -0
  11. package/dist/commands/agent/staff/remove.js +1 -0
  12. package/dist/commands/agent/themes/add-names.d.ts +1 -0
  13. package/dist/commands/agent/themes/add-names.js +1 -0
  14. package/dist/commands/agent/themes/create.d.ts +1 -0
  15. package/dist/commands/agent/themes/create.js +1 -0
  16. package/dist/commands/agent/themes/index.d.ts +10 -0
  17. package/dist/commands/agent/themes/index.js +144 -0
  18. package/dist/commands/agent/themes/list.d.ts +1 -0
  19. package/dist/commands/agent/themes/list.js +1 -0
  20. package/dist/commands/agent/themes/set.d.ts +1 -0
  21. package/dist/commands/agent/themes/set.js +1 -0
  22. package/dist/commands/agents/themes/add-names.d.ts +1 -0
  23. package/dist/commands/agents/themes/add-names.js +1 -0
  24. package/dist/commands/agents/themes/create.d.ts +1 -0
  25. package/dist/commands/agents/themes/create.js +1 -0
  26. package/dist/commands/agents/themes/list.d.ts +1 -0
  27. package/dist/commands/agents/themes/list.js +1 -0
  28. package/dist/commands/category/list.js +1 -1
  29. package/dist/commands/label/create.d.ts +20 -0
  30. package/dist/commands/label/create.js +56 -0
  31. package/dist/commands/label/delete.d.ts +17 -0
  32. package/dist/commands/label/delete.js +31 -0
  33. package/dist/commands/label/group/create.d.ts +20 -0
  34. package/dist/commands/label/group/create.js +54 -0
  35. package/dist/commands/label/group/list.d.ts +14 -0
  36. package/dist/commands/label/group/list.js +51 -0
  37. package/dist/commands/label/index.d.ts +15 -0
  38. package/dist/commands/label/index.js +58 -0
  39. package/dist/commands/label/list.d.ts +16 -0
  40. package/dist/commands/label/list.js +82 -0
  41. package/dist/commands/link/list.js +3 -2
  42. package/dist/commands/mcp-server.js +2 -1
  43. package/dist/commands/phase/template/apply.d.ts +26 -0
  44. package/dist/commands/phase/template/apply.js +14 -0
  45. package/dist/commands/phase/template/create.d.ts +23 -0
  46. package/dist/commands/phase/template/create.js +14 -0
  47. package/dist/commands/phase/template/delete.d.ts +18 -0
  48. package/dist/commands/phase/template/delete.js +61 -0
  49. package/dist/commands/phase/template/list.d.ts +17 -0
  50. package/dist/commands/phase/template/list.js +88 -0
  51. package/dist/commands/phase/template/update.d.ts +1 -0
  52. package/dist/commands/phase/template/update.js +1 -0
  53. package/dist/commands/priority/add.js +1 -1
  54. package/dist/commands/project/update.js +0 -2
  55. package/dist/commands/roadmap/generate.js +1 -2
  56. package/dist/commands/session/health.js +1 -1
  57. package/dist/commands/spec/link/depends.d.ts +18 -0
  58. package/dist/commands/spec/link/depends.js +86 -0
  59. package/dist/commands/spec/link/index.d.ts +17 -0
  60. package/dist/commands/spec/link/index.js +92 -0
  61. package/dist/commands/spec/link/remove.d.ts +18 -0
  62. package/dist/commands/spec/link/remove.js +90 -0
  63. package/dist/commands/support/logs.js +2 -2
  64. package/dist/commands/template/apply.js +5 -4
  65. package/dist/commands/template/create.js +1 -1
  66. package/dist/commands/ticket/link/block.d.ts +15 -0
  67. package/dist/commands/ticket/link/block.js +95 -0
  68. package/dist/commands/ticket/link/index.d.ts +14 -0
  69. package/dist/commands/ticket/link/index.js +96 -0
  70. package/dist/commands/ticket/list.d.ts +1 -0
  71. package/dist/commands/ticket/list.js +6 -0
  72. package/dist/commands/ticket/resolve.js +1 -1
  73. package/dist/commands/ticket/template/apply.d.ts +26 -0
  74. package/dist/commands/ticket/template/apply.js +14 -0
  75. package/dist/commands/ticket/template/delete.d.ts +18 -0
  76. package/dist/commands/ticket/template/delete.js +61 -0
  77. package/dist/commands/ticket/template/list.d.ts +17 -0
  78. package/dist/commands/ticket/template/list.js +77 -0
  79. package/dist/commands/ticket/template/save.d.ts +17 -0
  80. package/dist/commands/ticket/template/save.js +97 -0
  81. package/dist/commands/ticket/view.d.ts +1 -0
  82. package/dist/commands/ticket/view.js +1 -0
  83. package/dist/commands/work/ready.js +17 -0
  84. package/dist/commands/work/resolve.js +1 -1
  85. package/dist/commands/work/spawn.js +4 -4
  86. package/dist/commands/work/start.d.ts +1 -0
  87. package/dist/commands/work/start.js +52 -17
  88. package/dist/lib/database/index.d.ts +1 -1
  89. package/dist/lib/database/index.js +20 -0
  90. package/dist/lib/execution/devcontainer.js +3 -1
  91. package/dist/lib/execution/runners.d.ts +7 -2
  92. package/dist/lib/execution/runners.js +18 -10
  93. package/dist/lib/execution/types.d.ts +1 -0
  94. package/dist/lib/flags/resolver.js +1 -0
  95. package/dist/lib/mcp/helpers.d.ts +1 -2
  96. package/dist/lib/mcp/tools/diet.js +1 -0
  97. package/dist/lib/mcp/tools/index.d.ts +1 -0
  98. package/dist/lib/mcp/tools/index.js +1 -0
  99. package/dist/lib/mcp/tools/label.d.ts +6 -0
  100. package/dist/lib/mcp/tools/label.js +338 -0
  101. package/dist/lib/mcp/tools/ticket.js +53 -17
  102. package/dist/lib/multiline-input.js +6 -18
  103. package/dist/lib/pmo/base-command.d.ts +0 -1
  104. package/dist/lib/pmo/base-command.js +0 -1
  105. package/dist/lib/pmo/schema.d.ts +6 -0
  106. package/dist/lib/pmo/schema.js +44 -0
  107. package/dist/lib/pmo/storage/base.d.ts +6 -0
  108. package/dist/lib/pmo/storage/base.js +116 -2
  109. package/dist/lib/pmo/storage/index.d.ts +23 -1
  110. package/dist/lib/pmo/storage/index.js +59 -1
  111. package/dist/lib/pmo/storage/labels.d.ts +55 -0
  112. package/dist/lib/pmo/storage/labels.js +346 -0
  113. package/dist/lib/pmo/storage/tickets.js +17 -0
  114. package/dist/lib/pmo/storage/types.d.ts +24 -0
  115. package/dist/lib/pmo/types.d.ts +44 -0
  116. package/dist/lib/pmo/utils.js +1 -1
  117. package/oclif.manifest.json +5702 -3660
  118. package/package.json +1 -1
@@ -0,0 +1,14 @@
1
+ import { PMOCommand } from '../../../lib/pmo/index.js';
2
+ export default class LabelGroupList extends PMOCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ machine: 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
+ }
@@ -0,0 +1,51 @@
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 LabelGroupList extends PMOCommand {
5
+ static description = 'List label groups';
6
+ static examples = [
7
+ '<%= config.bin %> <%= command.id %>',
8
+ '<%= config.bin %> <%= command.id %> --json',
9
+ ];
10
+ static flags = {
11
+ ...pmoBaseFlags,
12
+ json: Flags.boolean({
13
+ description: 'Output as JSON',
14
+ default: false,
15
+ }),
16
+ };
17
+ getPMOOptions() {
18
+ return { promptIfMultiple: false };
19
+ }
20
+ async execute() {
21
+ const { flags } = await this.parse(LabelGroupList);
22
+ const groups = await this.storage.listLabelGroups();
23
+ if (flags.json || flags.machine) {
24
+ this.log(JSON.stringify(groups, null, 2));
25
+ return;
26
+ }
27
+ if (groups.length === 0) {
28
+ this.log(styles.muted('\nNo label groups found.'));
29
+ this.log(styles.muted('Create one: prlt label group create <name>'));
30
+ return;
31
+ }
32
+ this.log(`\n${styles.emphasis('Label Groups')}`);
33
+ this.log('═'.repeat(60));
34
+ for (const group of groups) {
35
+ const exclusive = group.isExclusive ? 'exclusive' : 'non-exclusive';
36
+ const required = group.isRequired ? ', required' : '';
37
+ this.log(`\n ${styles.emphasis(group.name)} ${styles.muted(`(${group.id})`)}`);
38
+ this.log(` ${styles.muted(`${exclusive}${required}`)}`);
39
+ if (group.description) {
40
+ this.log(` ${styles.muted(group.description)}`);
41
+ }
42
+ // Show labels in this group
43
+ const labels = await this.storage.listLabels({ groupId: group.id });
44
+ if (labels.length > 0) {
45
+ const labelNames = labels.map(l => l.name).join(', ');
46
+ this.log(` Labels: ${labelNames}`);
47
+ }
48
+ }
49
+ this.log('');
50
+ }
51
+ }
@@ -0,0 +1,15 @@
1
+ import { PMOCommand } from '../../lib/pmo/index.js';
2
+ export default class LabelIndex 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
+ machine: 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
+ }
@@ -0,0 +1,58 @@
1
+ import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
2
+ import { shouldOutputJson } from '../../lib/prompt-json.js';
3
+ export default class LabelIndex extends PMOCommand {
4
+ static description = 'Manage labels and label groups';
5
+ static aliases = ['labels'];
6
+ static examples = [
7
+ '<%= config.bin %> <%= command.id %>',
8
+ '<%= config.bin %> label list',
9
+ '<%= config.bin %> label create my-label',
10
+ '<%= config.bin %> label group list',
11
+ ];
12
+ static flags = {
13
+ ...pmoBaseFlags,
14
+ };
15
+ getPMOOptions() {
16
+ return { promptIfMultiple: false };
17
+ }
18
+ async execute() {
19
+ const { flags } = await this.parse(LabelIndex);
20
+ const jsonMode = shouldOutputJson(flags);
21
+ const menuChoices = [
22
+ { id: 'list', name: 'List all labels', command: 'prlt label list' },
23
+ { id: 'create', name: 'Create new label', command: 'prlt label create' },
24
+ { id: 'delete', name: 'Delete label', command: 'prlt label delete' },
25
+ { id: 'groups', name: 'List label groups', command: 'prlt label group list' },
26
+ { id: 'create-group', name: 'Create label group', command: 'prlt label group create' },
27
+ { id: 'cancel', name: 'Cancel', command: '' },
28
+ ];
29
+ const action = await this.selectFromList({
30
+ message: 'Labels - What would you like to do?',
31
+ items: menuChoices,
32
+ getName: (c) => c.name,
33
+ getValue: (c) => c.id,
34
+ getCommand: (c) => c.command,
35
+ jsonMode: jsonMode ? { flags, commandName: 'label' } : null,
36
+ });
37
+ if (action === 'cancel' || !action) {
38
+ return;
39
+ }
40
+ switch (action) {
41
+ case 'list':
42
+ await this.config.runCommand('label:list');
43
+ break;
44
+ case 'create':
45
+ await this.config.runCommand('label:create');
46
+ break;
47
+ case 'delete':
48
+ await this.config.runCommand('label:delete');
49
+ break;
50
+ case 'groups':
51
+ await this.config.runCommand('label:group:list');
52
+ break;
53
+ case 'create-group':
54
+ await this.config.runCommand('label:group:create');
55
+ break;
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,16 @@
1
+ import { PMOCommand } from '../../lib/pmo/index.js';
2
+ export default class LabelList extends PMOCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ group: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ machine: 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 printLabel;
16
+ }
@@ -0,0 +1,82 @@
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 LabelList extends PMOCommand {
5
+ static description = 'List labels, optionally filtered by group';
6
+ static examples = [
7
+ '<%= config.bin %> <%= command.id %>',
8
+ '<%= config.bin %> <%= command.id %> --group function',
9
+ '<%= config.bin %> <%= command.id %> --json',
10
+ ];
11
+ static flags = {
12
+ ...pmoBaseFlags,
13
+ group: Flags.string({
14
+ char: 'g',
15
+ description: 'Filter by group ID',
16
+ }),
17
+ json: Flags.boolean({
18
+ description: 'Output as JSON',
19
+ default: false,
20
+ }),
21
+ };
22
+ getPMOOptions() {
23
+ return { promptIfMultiple: false };
24
+ }
25
+ async execute() {
26
+ const { flags } = await this.parse(LabelList);
27
+ const labels = await this.storage.listLabels({
28
+ groupId: flags.group,
29
+ });
30
+ if (flags.json || flags.machine) {
31
+ this.log(JSON.stringify(labels, null, 2));
32
+ return;
33
+ }
34
+ if (labels.length === 0) {
35
+ this.log(styles.muted('\nNo labels found.'));
36
+ this.log(styles.muted('Create one: prlt label create <name>'));
37
+ return;
38
+ }
39
+ this.log(`\n${styles.emphasis('Labels')}`);
40
+ this.log('═'.repeat(60));
41
+ // Group labels by group
42
+ const grouped = new Map();
43
+ const ungrouped = [];
44
+ for (const label of labels) {
45
+ if (label.groupName) {
46
+ const group = grouped.get(label.groupName) || [];
47
+ group.push(label);
48
+ grouped.set(label.groupName, group);
49
+ }
50
+ else {
51
+ ungrouped.push(label);
52
+ }
53
+ }
54
+ for (const [groupName, groupLabels] of grouped) {
55
+ // Look up group info
56
+ const group = await this.storage.getLabelGroupByName(groupName);
57
+ const exclusive = group?.isExclusive ? ' (exclusive)' : '';
58
+ const required = group?.isRequired ? ' (required)' : '';
59
+ this.log(`\n${styles.emphasis(groupName)}${styles.muted(exclusive + required)}`);
60
+ this.log('─'.repeat(40));
61
+ for (const label of groupLabels) {
62
+ this.printLabel(label);
63
+ }
64
+ }
65
+ if (ungrouped.length > 0) {
66
+ this.log(`\n${styles.emphasis('Ungrouped')}`);
67
+ this.log('─'.repeat(40));
68
+ for (const label of ungrouped) {
69
+ this.printLabel(label);
70
+ }
71
+ }
72
+ this.log('');
73
+ }
74
+ printLabel(label) {
75
+ const colorDot = label.color ? `${label.color} ` : '';
76
+ const builtinBadge = label.isBuiltin ? '' : ' [custom]';
77
+ this.log(` ${colorDot}${styles.emphasis(label.name)} ${styles.muted(`(${label.id})`)}${builtinBadge}`);
78
+ if (label.description) {
79
+ this.log(` ${styles.muted(label.description)}`);
80
+ }
81
+ }
82
+ }
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-await-in-loop */
1
2
  import { Args, Flags } from '@oclif/core';
2
3
  import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
3
4
  import { styles } from '../../lib/styles.js';
@@ -107,7 +108,7 @@ export default class LinkList extends PMOCommand {
107
108
  }
108
109
  this.log('');
109
110
  }
110
- async listSpecLinks(specId, showAll) {
111
+ async listSpecLinks(specId, _showAll) {
111
112
  const spec = await this.storage.getSpec(specId);
112
113
  if (!spec) {
113
114
  this.error(`Spec not found: ${specId}`);
@@ -137,7 +138,7 @@ export default class LinkList extends PMOCommand {
137
138
  }
138
139
  this.log('');
139
140
  }
140
- async listEpicLinks(epicId, showAll) {
141
+ async listEpicLinks(epicId, _showAll) {
141
142
  const epic = await this.storage.getEpic(epicId);
142
143
  if (!epic) {
143
144
  this.error(`Epic not found: ${epicId}`);
@@ -19,7 +19,7 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
19
19
  import { execSync } from 'node:child_process';
20
20
  import * as path from 'node:path';
21
21
  import { getPMOContext } from '../lib/pmo/pmo-context.js';
22
- import { registerTicketTools, registerProjectTools, registerBoardTools, registerSpecTools, registerEpicTools, registerWorkTools, registerWorkflowTools, registerStatusTools, registerPhaseTools, registerActionTools, registerRoadmapTools, registerCategoryTools, registerTemplateTools, registerViewTools, registerDietTools, registerAgentTools, registerDockerTools, registerRepoTools, registerBranchTools, registerGitHubTools, registerInitTools, registerUtilityTools, } from '../lib/mcp/index.js';
22
+ import { registerTicketTools, registerProjectTools, registerBoardTools, registerSpecTools, registerEpicTools, registerWorkTools, registerWorkflowTools, registerStatusTools, registerPhaseTools, registerActionTools, registerRoadmapTools, registerCategoryTools, registerTemplateTools, registerViewTools, registerDietTools, registerLabelTools, registerAgentTools, registerDockerTools, registerRepoTools, registerBranchTools, registerGitHubTools, registerInitTools, registerUtilityTools, } from '../lib/mcp/index.js';
23
23
  export default class McpServerCommand extends Command {
24
24
  static description = 'Start MCP server for AI agent integration (exposes all prlt commands as tools)';
25
25
  static hidden = true;
@@ -85,6 +85,7 @@ export default class McpServerCommand extends Command {
85
85
  registerTemplateTools(server, ctx);
86
86
  registerViewTools(server, ctx);
87
87
  registerDietTools(server, ctx);
88
+ registerLabelTools(server, ctx);
88
89
  registerAgentTools(server, ctx);
89
90
  registerDockerTools(server, ctx);
90
91
  registerRepoTools(server, ctx);
@@ -0,0 +1,26 @@
1
+ import TemplateApply from '../../template/apply.js';
2
+ export default class PhaseTemplateApply extends TemplateApply {
3
+ static description: string;
4
+ static args: {
5
+ template: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
6
+ };
7
+ static flags: {
8
+ type: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ title: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ column: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ priority: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ category: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ assignee: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
+ owner: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
15
+ description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
16
+ epic: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
+ 'no-subtasks': import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
+ interactive: import("@oclif/core/interfaces").BooleanFlag<boolean>;
19
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
20
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
21
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
22
+ project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
23
+ };
24
+ static examples: string[];
25
+ run(): Promise<void>;
26
+ }
@@ -0,0 +1,14 @@
1
+ import TemplateApply from '../../template/apply.js';
2
+ export default class PhaseTemplateApply extends TemplateApply {
3
+ static description = 'Apply a phase template to the workspace';
4
+ static args = TemplateApply.args;
5
+ static flags = TemplateApply.flags;
6
+ static examples = TemplateApply.examples;
7
+ async run() {
8
+ const argv = this.argv;
9
+ if (!argv.includes('--type') && !argv.includes('-t')) {
10
+ argv.push('--type', 'phase');
11
+ }
12
+ return super.run();
13
+ }
14
+ }
@@ -0,0 +1,23 @@
1
+ import TemplateCreate from '../../template/create.js';
2
+ export default class PhaseTemplateCreate extends TemplateCreate {
3
+ static description: string;
4
+ static args: {
5
+ name: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
6
+ };
7
+ static flags: {
8
+ type: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ 'title-pattern': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ 'description-template': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ priority: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ category: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
+ subtask: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
15
+ ac: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
16
+ label: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
19
+ project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
+ };
21
+ static examples: string[];
22
+ run(): Promise<void>;
23
+ }
@@ -0,0 +1,14 @@
1
+ import TemplateCreate from '../../template/create.js';
2
+ export default class PhaseTemplateCreate extends TemplateCreate {
3
+ static description = 'Create a phase template from current workspace phases';
4
+ static args = TemplateCreate.args;
5
+ static flags = TemplateCreate.flags;
6
+ static examples = TemplateCreate.examples;
7
+ async run() {
8
+ const argv = this.argv;
9
+ if (!argv.includes('--type') && !argv.includes('-t')) {
10
+ argv.push('--type', 'phase');
11
+ }
12
+ return super.run();
13
+ }
14
+ }
@@ -0,0 +1,18 @@
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, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ };
14
+ protected getPMOOptions(): {
15
+ promptIfMultiple: boolean;
16
+ };
17
+ execute(): Promise<void>;
18
+ }
@@ -0,0 +1,61 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { PMOCommand, pmoBaseFlags } from '../../../lib/pmo/index.js';
3
+ import { styles } from '../../../lib/styles.js';
4
+ import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../../lib/prompt-json.js';
5
+ export default class PhaseTemplateDelete extends PMOCommand {
6
+ static description = 'Delete a phase template';
7
+ static examples = [
8
+ '<%= config.bin %> <%= command.id %> my-template --force',
9
+ ];
10
+ static args = {
11
+ id: Args.string({
12
+ description: 'Template ID to delete',
13
+ required: true,
14
+ }),
15
+ };
16
+ static flags = {
17
+ ...pmoBaseFlags,
18
+ force: Flags.boolean({
19
+ char: 'f',
20
+ description: 'Skip confirmation',
21
+ default: false,
22
+ }),
23
+ };
24
+ getPMOOptions() {
25
+ return { promptIfMultiple: false };
26
+ }
27
+ async execute() {
28
+ const { args, flags } = await this.parse(PhaseTemplateDelete);
29
+ const jsonMode = shouldOutputJson(flags);
30
+ const handleError = (code, message) => {
31
+ if (jsonMode) {
32
+ outputErrorAsJson(code, message, createMetadata('phase template delete', flags));
33
+ }
34
+ this.error(message);
35
+ };
36
+ const template = await this.storage.getPhaseTemplate(args.id);
37
+ if (!template) {
38
+ return handleError('NOT_FOUND', `Phase template not found: ${args.id}`);
39
+ }
40
+ if (template.isBuiltin) {
41
+ return handleError('BUILTIN', `Cannot delete built-in template "${template.name}".`);
42
+ }
43
+ if (!flags.force) {
44
+ const { confirm } = await this.prompt([{
45
+ type: 'list',
46
+ name: 'confirm',
47
+ message: `Delete phase template "${template.name}"?`,
48
+ choices: [
49
+ { name: 'No', value: false },
50
+ { name: 'Yes', value: true },
51
+ ],
52
+ }], jsonMode ? { flags, commandName: 'phase template delete' } : null);
53
+ if (!confirm) {
54
+ this.log(styles.muted('Cancelled.'));
55
+ return;
56
+ }
57
+ }
58
+ await this.storage.deletePhaseTemplate(args.id);
59
+ this.log(styles.success(`\nDeleted phase template "${template.name}"`));
60
+ }
61
+ }
@@ -0,0 +1,17 @@
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
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ };
12
+ protected getPMOOptions(): {
13
+ promptIfMultiple: boolean;
14
+ };
15
+ execute(): Promise<void>;
16
+ private printTemplate;
17
+ }
@@ -0,0 +1,88 @@
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 phase templates';
6
+ static examples = [
7
+ '<%= config.bin %> <%= command.id %>',
8
+ '<%= config.bin %> <%= command.id %> --builtin',
9
+ '<%= config.bin %> <%= command.id %> --json',
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
+ };
22
+ getPMOOptions() {
23
+ return { promptIfMultiple: false };
24
+ }
25
+ async execute() {
26
+ const { flags } = await this.parse(PhaseTemplateList);
27
+ let builtinFilter;
28
+ if (flags.builtin)
29
+ builtinFilter = { isBuiltin: true };
30
+ if (flags.custom)
31
+ builtinFilter = { isBuiltin: false };
32
+ const templates = await this.storage.listPhaseTemplates(builtinFilter);
33
+ if (flags.json) {
34
+ this.log(JSON.stringify(templates, null, 2));
35
+ return;
36
+ }
37
+ if (templates.length === 0) {
38
+ this.log(styles.muted('\nNo phase templates found.'));
39
+ return;
40
+ }
41
+ this.log(`\n${styles.emphasis('Phase Templates')}`);
42
+ this.log('═'.repeat(60));
43
+ const builtinTemplates = templates.filter(t => t.isBuiltin);
44
+ const customTemplates = templates.filter(t => !t.isBuiltin);
45
+ if (builtinTemplates.length > 0 && !flags.custom) {
46
+ this.log(`\n${styles.emphasis('Built-in Templates')}`);
47
+ this.log('─'.repeat(40));
48
+ for (const template of builtinTemplates) {
49
+ this.printTemplate(template);
50
+ }
51
+ }
52
+ if (customTemplates.length > 0 && !flags.builtin) {
53
+ this.log(`\n${styles.emphasis('Custom Templates')}`);
54
+ this.log('─'.repeat(40));
55
+ for (const template of customTemplates) {
56
+ this.printTemplate(template);
57
+ }
58
+ }
59
+ this.log('');
60
+ }
61
+ printTemplate(template) {
62
+ const categoryEmoji = {
63
+ triage: '📬',
64
+ backlog: '📥',
65
+ unstarted: '📋',
66
+ started: '🚀',
67
+ completed: '✅',
68
+ canceled: '🚫',
69
+ };
70
+ this.log(` ${styles.emphasis(template.name)} ${styles.muted(`(${template.id})`)}`);
71
+ if (template.description) {
72
+ this.log(` ${styles.muted(template.description)}`);
73
+ }
74
+ if (template.phases && template.phases.length > 0) {
75
+ const phasesByCategory = new Map();
76
+ for (const phase of template.phases) {
77
+ const existing = phasesByCategory.get(phase.category) || [];
78
+ existing.push(phase.name);
79
+ phasesByCategory.set(phase.category, existing);
80
+ }
81
+ const phaseParts = [];
82
+ for (const [category, names] of phasesByCategory) {
83
+ phaseParts.push(`${categoryEmoji[category]} ${names.join(', ')}`);
84
+ }
85
+ this.log(` ${styles.muted(phaseParts.join(' → '))}`);
86
+ }
87
+ }
88
+ }
@@ -0,0 +1 @@
1
+ export { default } from '../../template/update.js';
@@ -0,0 +1 @@
1
+ export { default } from '../../template/update.js';
@@ -46,7 +46,7 @@ export default class PriorityAdd extends PMOCommand {
46
46
  }
47
47
  else if (flags.after) {
48
48
  const afterIndex = priorities.indexOf(flags.after);
49
- if (afterIndex < 0) {
49
+ if (afterIndex === -1) {
50
50
  if (jsonMode) {
51
51
  outputErrorAsJson('PRIORITY_NOT_FOUND', `Priority "${flags.after}" not found`, createMetadata('priority add', flags));
52
52
  this.exit(1);
@@ -43,8 +43,6 @@ export default class ProjectUpdate extends PMOCommand {
43
43
  }
44
44
  this.error(message);
45
45
  };
46
- // Agent mode config for prompts
47
- const agentConfig = jsonMode ? { flags, commandName: 'project update' } : null;
48
46
  // Get project ID - from args or prompt
49
47
  let projectId = args.id;
50
48
  if (!projectId) {
@@ -3,9 +3,8 @@ import * as fs from 'node:fs';
3
3
  import * as path from 'node:path';
4
4
  import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
5
5
  import { styles } from '../../lib/styles.js';
6
- import { slugify } from '../../lib/pmo/utils.js';
6
+ import { slugify, getWorkspacePriorities } from '../../lib/pmo/utils.js';
7
7
  import { normalizePriority } from '../../lib/pmo/types.js';
8
- import { getWorkspacePriorities } from '../../lib/pmo/utils.js';
9
8
  import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
10
9
  export default class RoadmapGenerate extends PMOCommand {
11
10
  static description = 'Generate roadmap markdown file';
@@ -60,7 +60,7 @@ function detectState(paneContent) {
60
60
  }
61
61
  // IDLE: shell prompt visible (agent has finished or is waiting)
62
62
  // Match common prompt patterns at end of last non-empty line
63
- const lastNonEmpty = lines.filter(l => l.trim().length > 0).pop() || '';
63
+ const lastNonEmpty = [...lines].reverse().find((l) => l.trim().length > 0) || '';
64
64
  if (/[$❯#>]\s*$/.test(lastNonEmpty) || /^\s*\$\s*$/.test(lastNonEmpty)) {
65
65
  return 'IDLE';
66
66
  }
@@ -0,0 +1,18 @@
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
+ spec: 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
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ };
14
+ protected getPMOOptions(): {
15
+ promptIfMultiple: boolean;
16
+ };
17
+ execute(): Promise<void>;
18
+ }