@proletariat/cli 0.3.46 → 0.3.48

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 (58) hide show
  1. package/bin/validate-better-sqlite3.cjs +55 -0
  2. package/dist/commands/caffeinate/index.d.ts +10 -0
  3. package/dist/commands/caffeinate/index.js +64 -0
  4. package/dist/commands/caffeinate/start.d.ts +14 -0
  5. package/dist/commands/caffeinate/start.js +86 -0
  6. package/dist/commands/caffeinate/status.d.ts +10 -0
  7. package/dist/commands/caffeinate/status.js +55 -0
  8. package/dist/commands/caffeinate/stop.d.ts +10 -0
  9. package/dist/commands/caffeinate/stop.js +47 -0
  10. package/dist/commands/commit.js +10 -8
  11. package/dist/commands/config/index.js +2 -3
  12. package/dist/commands/init.js +9 -1
  13. package/dist/commands/orchestrator/attach.d.ts +1 -0
  14. package/dist/commands/orchestrator/attach.js +104 -24
  15. package/dist/commands/orchestrator/index.js +2 -2
  16. package/dist/commands/orchestrator/start.d.ts +13 -1
  17. package/dist/commands/orchestrator/start.js +115 -34
  18. package/dist/commands/orchestrator/status.d.ts +1 -0
  19. package/dist/commands/orchestrator/status.js +68 -22
  20. package/dist/commands/orchestrator/stop.d.ts +1 -0
  21. package/dist/commands/orchestrator/stop.js +50 -13
  22. package/dist/commands/session/attach.js +55 -9
  23. package/dist/commands/session/poke.js +1 -1
  24. package/dist/commands/work/index.js +8 -0
  25. package/dist/commands/work/linear.d.ts +24 -0
  26. package/dist/commands/work/linear.js +195 -0
  27. package/dist/commands/work/review.d.ts +45 -0
  28. package/dist/commands/work/review.js +401 -0
  29. package/dist/commands/work/spawn.js +28 -19
  30. package/dist/commands/work/start.js +12 -2
  31. package/dist/hooks/init.js +26 -5
  32. package/dist/lib/caffeinate.d.ts +64 -0
  33. package/dist/lib/caffeinate.js +146 -0
  34. package/dist/lib/database/native-validation.d.ts +21 -0
  35. package/dist/lib/database/native-validation.js +49 -0
  36. package/dist/lib/execution/codex-adapter.d.ts +96 -0
  37. package/dist/lib/execution/codex-adapter.js +148 -0
  38. package/dist/lib/execution/index.d.ts +1 -0
  39. package/dist/lib/execution/index.js +1 -0
  40. package/dist/lib/execution/runners.js +56 -6
  41. package/dist/lib/external-issues/index.d.ts +1 -1
  42. package/dist/lib/external-issues/index.js +1 -1
  43. package/dist/lib/external-issues/linear.d.ts +37 -0
  44. package/dist/lib/external-issues/linear.js +198 -0
  45. package/dist/lib/external-issues/types.d.ts +67 -0
  46. package/dist/lib/external-issues/types.js +41 -0
  47. package/dist/lib/init/index.d.ts +4 -0
  48. package/dist/lib/init/index.js +11 -1
  49. package/dist/lib/machine-config.d.ts +1 -0
  50. package/dist/lib/machine-config.js +6 -3
  51. package/dist/lib/mcp/tools/work.js +36 -0
  52. package/dist/lib/pmo/storage/actions.js +3 -3
  53. package/dist/lib/pmo/storage/base.js +85 -6
  54. package/dist/lib/pmo/storage/epics.js +1 -1
  55. package/dist/lib/pmo/storage/tickets.js +2 -2
  56. package/dist/lib/pmo/storage/types.d.ts +2 -1
  57. package/oclif.manifest.json +4158 -3651
  58. package/package.json +2 -2
@@ -6,7 +6,8 @@ import * as os from 'node:os';
6
6
  import Database from 'better-sqlite3';
7
7
  import { styles } from '../../lib/styles.js';
8
8
  import { getWorkspaceInfo } from '../../lib/agents/commands.js';
9
- import { ExecutionStorage } from '../../lib/execution/index.js';
9
+ import { ExecutionStorage, loadExecutionConfig, shouldUseControlMode, buildTmuxAttachCommand } from '../../lib/execution/index.js';
10
+ import { detectTerminalApp } from '../orchestrator/attach.js';
10
11
  import { parseSessionName, getHostTmuxSessionNames, getContainerTmuxSessionMap, flattenContainerSessions, findContainerSessionsByPrefix, findSessionForExecution, } from '../../lib/execution/session-utils.js';
11
12
  import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
12
13
  import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
@@ -106,12 +107,32 @@ export default class SessionAttach extends PMOCommand {
106
107
  // Attach to the session
107
108
  this.log('');
108
109
  this.log(styles.info(`Attaching to session: ${selectedSession.sessionId}`));
110
+ // Determine if we should use tmux control mode (-u -CC) for iTerm
111
+ let useControlMode = false;
112
+ try {
113
+ const workspaceInfo = getWorkspaceInfo();
114
+ const dbPath = path.join(workspaceInfo.path, '.proletariat', 'workspace.db');
115
+ const db = new Database(dbPath);
116
+ try {
117
+ const config = loadExecutionConfig(db);
118
+ const termApp = detectTerminalApp();
119
+ if (termApp === 'iTerm') {
120
+ useControlMode = shouldUseControlMode('iTerm', config.tmux.controlMode);
121
+ }
122
+ }
123
+ finally {
124
+ db.close();
125
+ }
126
+ }
127
+ catch {
128
+ // Not in a workspace or DB not available - fall back to no control mode
129
+ }
109
130
  // Default to new tab unless --current-terminal is specified
110
131
  if (flags['current-terminal']) {
111
- await this.attachInCurrentTerminal(selectedSession);
132
+ await this.attachInCurrentTerminal(selectedSession, useControlMode);
112
133
  }
113
134
  else {
114
- await this.attachInNewTab(selectedSession, flags.terminal);
135
+ await this.attachInNewTab(selectedSession, flags.terminal, useControlMode);
115
136
  }
116
137
  }
117
138
  /**
@@ -247,13 +268,29 @@ export default class SessionAttach extends PMOCommand {
247
268
  /**
248
269
  * Attach to session in current terminal
249
270
  */
250
- async attachInCurrentTerminal(session) {
271
+ async attachInCurrentTerminal(session, useControlMode) {
251
272
  try {
273
+ // Set mouse mode based on attach type:
274
+ // - Plain terminal: mouse on (enables scroll in tmux; hold Shift/Option to bypass)
275
+ // - iTerm -CC: mouse off (iTerm handles scrolling natively)
276
+ const mouseMode = useControlMode ? 'off' : 'on';
277
+ try {
278
+ if (session.type === 'container' && session.containerId) {
279
+ execSync(`docker exec ${session.containerId} tmux set-option -t "${session.sessionId}" mouse ${mouseMode}`, { stdio: 'pipe' });
280
+ }
281
+ else {
282
+ execSync(`tmux set-option -t "${session.sessionId}" mouse ${mouseMode}`, { stdio: 'pipe' });
283
+ }
284
+ }
285
+ catch {
286
+ // Non-fatal: mouse mode is a convenience, don't block attach
287
+ }
288
+ const tmuxAttach = buildTmuxAttachCommand(useControlMode, session.type === 'container');
252
289
  if (session.type === 'container' && session.containerId) {
253
- execSync(`docker exec -it ${session.containerId} tmux attach -t "${session.sessionId}"`, { stdio: 'inherit' });
290
+ execSync(`docker exec -it ${session.containerId} ${tmuxAttach} -t "${session.sessionId}"`, { stdio: 'inherit' });
254
291
  }
255
292
  else {
256
- execSync(`tmux attach -t "${session.sessionId}"`, { stdio: 'inherit' });
293
+ execSync(`${tmuxAttach} -t "${session.sessionId}"`, { stdio: 'inherit' });
257
294
  }
258
295
  }
259
296
  catch {
@@ -263,7 +300,7 @@ export default class SessionAttach extends PMOCommand {
263
300
  /**
264
301
  * Attach to session in a new terminal tab
265
302
  */
266
- async attachInNewTab(session, terminalApp) {
303
+ async attachInNewTab(session, terminalApp, useControlMode) {
267
304
  // Build a readable title for the tab
268
305
  const title = `${session.ticketId} (${session.agentName})`;
269
306
  // Create a script that sets tab title and attaches to tmux
@@ -271,14 +308,23 @@ export default class SessionAttach extends PMOCommand {
271
308
  fs.mkdirSync(baseDir, { recursive: true });
272
309
  const scriptPath = path.join(baseDir, `attach-${Date.now()}.sh`);
273
310
  // Different attach command for container vs host sessions
311
+ const tmuxAttach = buildTmuxAttachCommand(useControlMode, session.type === 'container');
274
312
  const attachCmd = session.type === 'container' && session.containerId
275
- ? `docker exec -it ${session.containerId} tmux -u attach -t "${session.sessionId}"`
276
- : `tmux attach -t "${session.sessionId}"`;
313
+ ? `docker exec -it ${session.containerId} ${tmuxAttach} -t "${session.sessionId}"`
314
+ : `${tmuxAttach} -t "${session.sessionId}"`;
315
+ // Set mouse mode based on attach type
316
+ const mouseMode = useControlMode ? 'off' : 'on';
317
+ const mouseCmd = session.type === 'container' && session.containerId
318
+ ? `docker exec ${session.containerId} tmux set-option -t "${session.sessionId}" mouse ${mouseMode} 2>/dev/null || true`
319
+ : `tmux set-option -t "${session.sessionId}" mouse ${mouseMode} 2>/dev/null || true`;
277
320
  const script = `#!/bin/bash
278
321
  # Set terminal tab title
279
322
  echo -ne "\\033]0;${title}\\007"
280
323
  echo -ne "\\033]1;${title}\\007"
281
324
 
325
+ # Set mouse mode before attaching
326
+ ${mouseCmd}
327
+
282
328
  echo "Attaching to: ${session.sessionId} (${session.type})"
283
329
  ${attachCmd}
284
330
 
@@ -176,7 +176,7 @@ export default class SessionPoke extends PMOCommand {
176
176
  * Resolve the tmux session for a specific execution record.
177
177
  */
178
178
  resolveSessionForExecution(exec, jsonMode, flags) {
179
- const isContainer = exec.environment === 'devcontainer';
179
+ const isContainer = !!exec.containerId;
180
180
  let actualSessionId = exec.sessionId;
181
181
  let containerId = isContainer ? exec.containerId : undefined;
182
182
  // If sessionId is NULL, try to discover it from tmux
@@ -24,9 +24,11 @@ export default class Work extends PMOCommand {
24
24
  const menuChoices = [
25
25
  { id: 'status', name: 'View work status (in-progress tickets)', command: `prlt work status -P ${projectId} --json` },
26
26
  { id: 'start', name: 'Start work (launch single agent)', command: `prlt work start -P ${projectId} --json` },
27
+ { id: 'linear', name: 'Spawn from Linear issue', command: `prlt work linear -P ${projectId} --json` },
27
28
  { id: 'resolve', name: 'Resolve questions (agent-assisted)', command: `prlt work resolve -P ${projectId} --json` },
28
29
  { id: 'spawn', name: 'Spawn work (batch by column)', command: `prlt work spawn -P ${projectId} --json` },
29
30
  { id: 'watch', name: 'Watch column (auto-spawn)', command: `prlt work watch -P ${projectId} --json` },
31
+ { id: 'review', name: 'Review pipeline (review → fix → re-review)', command: `prlt work review -P ${projectId} --json` },
30
32
  { id: 'ready', name: 'Mark work ready for review', command: `prlt work ready -P ${projectId} --json` },
31
33
  { id: 'complete', name: 'Mark work complete', command: `prlt work complete -P ${projectId} --json` },
32
34
  { id: 'cancel', name: 'Cancel', command: '' },
@@ -53,6 +55,9 @@ export default class Work extends PMOCommand {
53
55
  case 'start':
54
56
  await this.config.runCommand('work:start', projectArgs);
55
57
  break;
58
+ case 'linear':
59
+ await this.config.runCommand('work:linear', projectArgs);
60
+ break;
56
61
  case 'resolve':
57
62
  await this.config.runCommand('work:resolve', projectArgs);
58
63
  break;
@@ -62,6 +67,9 @@ export default class Work extends PMOCommand {
62
67
  case 'watch':
63
68
  await this.config.runCommand('work:watch', projectArgs);
64
69
  break;
70
+ case 'review':
71
+ await this.config.runCommand('work:review', projectArgs);
72
+ break;
65
73
  case 'ready':
66
74
  await this.config.runCommand('work:ready', projectArgs);
67
75
  break;
@@ -0,0 +1,24 @@
1
+ import { PMOCommand } from '../../lib/pmo/index.js';
2
+ export default class WorkLinear extends PMOCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ team: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ issue: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
9
+ executor: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ display: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ action: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
12
+ message: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ 'run-on-host': import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ 'skip-permissions': import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
+ 'create-pr': import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
+ yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
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
+ private findLinkedTicket;
22
+ private createOrUpdateLinkedTicket;
23
+ execute(): Promise<void>;
24
+ }
@@ -0,0 +1,195 @@
1
+ import { Flags } from '@oclif/core';
2
+ import { PMOCommand, pmoBaseFlags, autoExportToBoard, } from '../../lib/pmo/index.js';
3
+ import { shouldOutputJson, } from '../../lib/prompt-json.js';
4
+ import { ExternalIssueAdapterError, } from '../../lib/external-issues/types.js';
5
+ import { listLinearIssues, buildLinearIssueChoiceCommand, buildLinearTicketDescription, buildLinearMetadata, buildLinearSpawnContextMessage, } from '../../lib/external-issues/linear.js';
6
+ function buildWorkStartArgs(options) {
7
+ const args = [options.ticketId, '--project', options.projectId, '--ephemeral'];
8
+ if (options.executor)
9
+ args.push('--executor', options.executor);
10
+ if (options.display)
11
+ args.push('--display', options.display);
12
+ if (options.runOnHost)
13
+ args.push('--run-on-host');
14
+ if (options.skipPermissions)
15
+ args.push('--skip-permissions');
16
+ if (options.createPr)
17
+ args.push('--create-pr');
18
+ if (options.action)
19
+ args.push('--action', options.action);
20
+ if (options.message)
21
+ args.push('--message', options.message);
22
+ if (options.json)
23
+ args.push('--json');
24
+ if (options.machine)
25
+ args.push('--machine');
26
+ if (options.yes)
27
+ args.push('--yes');
28
+ return args;
29
+ }
30
+ export default class WorkLinear extends PMOCommand {
31
+ static description = 'List/select Linear issues and spawn work using the existing work-start flow';
32
+ static examples = [
33
+ '<%= config.bin %> <%= command.id %> --team ENG',
34
+ '<%= config.bin %> <%= command.id %> --team ENG --issue ENG-123',
35
+ '<%= config.bin %> <%= command.id %> --team ENG --issue ENG-123 --yes --skip-permissions --display terminal',
36
+ ];
37
+ static flags = {
38
+ ...pmoBaseFlags,
39
+ team: Flags.string({
40
+ description: 'Linear team key (fallback: PRLT_LINEAR_TEAM)',
41
+ }),
42
+ issue: Flags.string({
43
+ description: 'Linear issue identifier (for example: ENG-123)',
44
+ }),
45
+ limit: Flags.integer({
46
+ char: 'l',
47
+ description: 'Maximum number of Linear issues to fetch',
48
+ default: 20,
49
+ min: 1,
50
+ max: 100,
51
+ }),
52
+ executor: Flags.string({
53
+ char: 'e',
54
+ description: 'Override executor',
55
+ options: ['claude-code', 'codex', 'aider', 'custom'],
56
+ }),
57
+ display: Flags.string({
58
+ char: 'd',
59
+ description: 'Display mode',
60
+ options: ['terminal', 'background', 'foreground'],
61
+ }),
62
+ action: Flags.string({
63
+ char: 'A',
64
+ description: 'Action to run in work start (default: implement)',
65
+ default: 'implement',
66
+ }),
67
+ message: Flags.string({
68
+ description: 'Additional instructions appended to spawn context',
69
+ }),
70
+ 'run-on-host': Flags.boolean({
71
+ description: 'Run on host even if devcontainer exists',
72
+ default: false,
73
+ }),
74
+ 'skip-permissions': Flags.boolean({
75
+ description: 'Skip permission prompts (danger mode)',
76
+ default: false,
77
+ }),
78
+ 'create-pr': Flags.boolean({
79
+ description: 'Create PR when work is ready',
80
+ default: false,
81
+ }),
82
+ yes: Flags.boolean({
83
+ char: 'y',
84
+ description: 'Skip confirmation prompts in downstream work start',
85
+ default: false,
86
+ }),
87
+ };
88
+ async findLinkedTicket(projectId, envelope) {
89
+ const tickets = await this.storage.listTickets(projectId);
90
+ return tickets.find((ticket) => {
91
+ const source = ticket.metadata?.external_source;
92
+ const key = ticket.metadata?.external_key;
93
+ const id = ticket.metadata?.external_id;
94
+ return source === 'linear'
95
+ && (key === envelope.source.externalKey || id === envelope.source.externalId);
96
+ });
97
+ }
98
+ async createOrUpdateLinkedTicket(projectId, envelope) {
99
+ const existing = await this.findLinkedTicket(projectId, envelope);
100
+ const description = buildLinearTicketDescription(envelope);
101
+ const metadata = buildLinearMetadata(envelope);
102
+ if (existing) {
103
+ const updated = await this.storage.updateTicket(existing.id, {
104
+ title: envelope.title,
105
+ description,
106
+ priority: envelope.priority ?? undefined,
107
+ category: envelope.category ?? undefined,
108
+ labels: envelope.labels,
109
+ metadata: {
110
+ ...existing.metadata,
111
+ ...metadata,
112
+ },
113
+ });
114
+ return updated;
115
+ }
116
+ return this.storage.createTicket(projectId, {
117
+ title: envelope.title,
118
+ description,
119
+ priority: envelope.priority ?? undefined,
120
+ category: envelope.category ?? undefined,
121
+ labels: envelope.labels,
122
+ metadata,
123
+ });
124
+ }
125
+ async execute() {
126
+ const { flags } = await this.parse(WorkLinear);
127
+ const jsonMode = shouldOutputJson(flags);
128
+ const projectId = await this.requireProject({
129
+ jsonMode: {
130
+ flags,
131
+ commandName: 'work linear',
132
+ baseCommand: 'prlt work linear',
133
+ },
134
+ });
135
+ const team = flags.team || process.env.PRLT_LINEAR_TEAM;
136
+ let issues;
137
+ try {
138
+ issues = await listLinearIssues({
139
+ team,
140
+ }, { limit: flags.limit });
141
+ }
142
+ catch (error) {
143
+ if (error instanceof ExternalIssueAdapterError) {
144
+ return this.handleError(error.code, error.message, { jsonMode, commandName: 'work linear', flags });
145
+ }
146
+ const msg = error instanceof Error ? error.message : 'Failed to fetch Linear issues.';
147
+ return this.handleError('LINEAR_REQUEST_FAILED', msg, { jsonMode, commandName: 'work linear', flags });
148
+ }
149
+ if (issues.length === 0) {
150
+ return this.handleError('NO_LINEAR_ISSUES', 'No active Linear issues found for the configured team.', { jsonMode, commandName: 'work linear', flags });
151
+ }
152
+ let selectedIssue = issues.find(issue => issue.source.externalKey === flags.issue);
153
+ if (!selectedIssue) {
154
+ if (flags.issue) {
155
+ return this.handleError('LINEAR_ISSUE_NOT_FOUND', `Linear issue "${flags.issue}" was not found.`, { jsonMode, commandName: 'work linear', flags });
156
+ }
157
+ const selectedKey = await this.selectFromList({
158
+ message: 'Select Linear issue to spawn:',
159
+ items: issues,
160
+ getName: (issue) => {
161
+ const priority = issue.priority || 'None';
162
+ return `[${priority}] ${issue.source.externalKey} - ${issue.title}`;
163
+ },
164
+ getValue: issue => issue.source.externalKey,
165
+ getCommand: issue => buildLinearIssueChoiceCommand(issue.source.externalKey, projectId),
166
+ jsonMode: jsonMode ? { flags, commandName: 'work linear' } : null,
167
+ });
168
+ if (!selectedKey) {
169
+ return;
170
+ }
171
+ selectedIssue = issues.find(issue => issue.source.externalKey === selectedKey);
172
+ if (!selectedIssue) {
173
+ return this.handleError('LINEAR_ISSUE_NOT_FOUND', `Linear issue "${selectedKey}" was not found.`, { jsonMode, commandName: 'work linear', flags });
174
+ }
175
+ }
176
+ const ticket = await this.createOrUpdateLinkedTicket(projectId, selectedIssue);
177
+ await autoExportToBoard(this.pmoPath, this.storage);
178
+ const contextMessage = buildLinearSpawnContextMessage(selectedIssue, flags.message);
179
+ const args = buildWorkStartArgs({
180
+ ticketId: ticket.id,
181
+ projectId,
182
+ executor: flags.executor,
183
+ display: flags.display,
184
+ runOnHost: flags['run-on-host'],
185
+ skipPermissions: flags['skip-permissions'],
186
+ createPr: flags['create-pr'],
187
+ action: flags.action,
188
+ message: contextMessage,
189
+ json: flags.json,
190
+ machine: flags.machine,
191
+ yes: flags.yes,
192
+ });
193
+ await this.config.runCommand('work:start', args);
194
+ }
195
+ }
@@ -0,0 +1,45 @@
1
+ import { PMOCommand } from '../../lib/pmo/index.js';
2
+ export default class WorkReview extends PMOCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ ticketId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ 'max-cycles': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
10
+ auto: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ executor: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ 'run-on-host': import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
+ 'skip-permissions': import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ display: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
15
+ session: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
16
+ 'poll-interval': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
17
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
19
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
20
+ project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
21
+ };
22
+ execute(): Promise<void>;
23
+ /**
24
+ * Build args for `work:start` command.
25
+ */
26
+ private buildStartArgs;
27
+ /**
28
+ * Run the fix phase: spawn review-fix agent and wait for completion.
29
+ */
30
+ private runFixPhase;
31
+ /**
32
+ * Wait for the most recent execution on a ticket to complete.
33
+ * Polls the execution storage and checks tmux session existence.
34
+ */
35
+ private waitForAgentCompletion;
36
+ /**
37
+ * Check if a tmux session exists.
38
+ */
39
+ private checkTmuxSession;
40
+ /**
41
+ * Get the review verdict from PR feedback.
42
+ */
43
+ private getReviewVerdict;
44
+ private sleep;
45
+ }