@proletariat/cli 0.3.36 → 0.3.40
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/README.md +37 -2
- package/bin/dev.js +0 -0
- package/dist/commands/branch/where.js +6 -17
- package/dist/commands/epic/ticket.js +7 -24
- package/dist/commands/execution/config.js +4 -14
- package/dist/commands/execution/logs.js +6 -0
- package/dist/commands/execution/view.js +8 -0
- package/dist/commands/mcp-server.js +2 -1
- package/dist/commands/pmo/init.js +12 -40
- package/dist/commands/qa/index.d.ts +54 -0
- package/dist/commands/qa/index.js +762 -0
- package/dist/commands/repo/view.js +2 -8
- package/dist/commands/session/attach.js +4 -4
- package/dist/commands/session/health.js +4 -4
- package/dist/commands/session/list.js +1 -19
- package/dist/commands/session/peek.js +6 -6
- package/dist/commands/session/poke.js +2 -2
- package/dist/commands/ticket/epic.js +17 -43
- package/dist/commands/work/spawn-all.js +1 -1
- package/dist/commands/work/spawn.js +15 -4
- package/dist/commands/work/start.js +17 -9
- package/dist/commands/work/watch.js +1 -1
- package/dist/commands/workspace/prune.js +3 -3
- package/dist/hooks/init.js +10 -2
- package/dist/lib/agents/commands.d.ts +5 -0
- package/dist/lib/agents/commands.js +143 -97
- package/dist/lib/database/drizzle-schema.d.ts +465 -0
- package/dist/lib/database/drizzle-schema.js +53 -0
- package/dist/lib/database/index.d.ts +47 -1
- package/dist/lib/database/index.js +138 -20
- package/dist/lib/execution/runners.d.ts +34 -0
- package/dist/lib/execution/runners.js +134 -7
- package/dist/lib/execution/session-utils.d.ts +5 -0
- package/dist/lib/execution/session-utils.js +45 -3
- package/dist/lib/execution/spawner.js +15 -2
- package/dist/lib/execution/storage.d.ts +1 -1
- package/dist/lib/execution/storage.js +17 -2
- package/dist/lib/execution/types.d.ts +1 -0
- package/dist/lib/mcp/tools/index.d.ts +1 -0
- package/dist/lib/mcp/tools/index.js +1 -0
- package/dist/lib/mcp/tools/tmux.d.ts +16 -0
- package/dist/lib/mcp/tools/tmux.js +182 -0
- package/dist/lib/mcp/tools/work.js +52 -0
- package/dist/lib/pmo/schema.d.ts +1 -1
- package/dist/lib/pmo/schema.js +1 -0
- package/dist/lib/pmo/storage/base.js +207 -0
- package/dist/lib/pmo/storage/dependencies.d.ts +1 -0
- package/dist/lib/pmo/storage/dependencies.js +11 -3
- package/dist/lib/pmo/storage/epics.js +1 -1
- package/dist/lib/pmo/storage/helpers.d.ts +4 -4
- package/dist/lib/pmo/storage/helpers.js +36 -26
- package/dist/lib/pmo/storage/projects.d.ts +2 -0
- package/dist/lib/pmo/storage/projects.js +207 -119
- package/dist/lib/pmo/storage/specs.d.ts +2 -0
- package/dist/lib/pmo/storage/specs.js +274 -188
- package/dist/lib/pmo/storage/tickets.d.ts +2 -0
- package/dist/lib/pmo/storage/tickets.js +350 -290
- package/dist/lib/pmo/storage/views.d.ts +2 -0
- package/dist/lib/pmo/storage/views.js +183 -130
- package/dist/lib/prompt-json.d.ts +5 -0
- package/dist/lib/prompt-json.js +9 -0
- package/oclif.manifest.json +3922 -3819
- package/package.json +11 -6
- package/LICENSE +0 -190
package/README.md
CHANGED
|
@@ -24,7 +24,10 @@
|
|
|
24
24
|
**prlt** is an agent orchestration platform for AI labor. Spin up workers on demand, coordinate multi-agent development from one CLI. Isolated workspaces, secure containers, persistent state.
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
|
|
27
|
+
brew install chrismcdermut/proletariat/prlt # macOS (Homebrew)
|
|
28
|
+
# or
|
|
29
|
+
npm install -g @proletariat/cli # any platform (npm)
|
|
30
|
+
|
|
28
31
|
prlt init
|
|
29
32
|
prlt ticket create --title "Add OAuth" --category feature
|
|
30
33
|
prlt work spawn # Interactive: select tickets, environment, action
|
|
@@ -48,7 +51,10 @@ Agent spawns in its own branch, writes code, opens PR. You review and merge.
|
|
|
48
51
|
# Quick Start
|
|
49
52
|
|
|
50
53
|
```bash
|
|
51
|
-
npm install -g @proletariat/cli # Install
|
|
54
|
+
npm install -g @proletariat/cli # Install (npm)
|
|
55
|
+
# or
|
|
56
|
+
brew install chrismcdermut/proletariat/prlt # Install (Homebrew, macOS)
|
|
57
|
+
|
|
52
58
|
prlt init # Create HQ, add repos, choose theme
|
|
53
59
|
prlt ticket create --title "Add OAuth" --category feature
|
|
54
60
|
prlt work spawn # Interactive: select tickets, environment, action
|
|
@@ -117,6 +123,35 @@ Select tickets to spawn, grouped by priority:
|
|
|
117
123
|
| Starting agents is heavyweight | **Ephemeral** - Spawn on demand, they work, they PR, they're done |
|
|
118
124
|
| Context lost between agent runs | **Persistent** - Tickets accumulate context, hand off between agents |
|
|
119
125
|
|
|
126
|
+
### Installation
|
|
127
|
+
|
|
128
|
+
#### Homebrew (macOS)
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
brew install chrismcdermut/proletariat/prlt
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Works on both Apple Silicon (arm64) and Intel (x86_64) Macs.
|
|
135
|
+
|
|
136
|
+
**Upgrade:**
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
brew update
|
|
140
|
+
brew upgrade prlt
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Verify:**
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
prlt --version
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### npm (all platforms)
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
npm install -g @proletariat/cli
|
|
153
|
+
```
|
|
154
|
+
|
|
120
155
|
### Data Model
|
|
121
156
|
|
|
122
157
|
```
|
package/bin/dev.js
CHANGED
|
File without changes
|
|
@@ -5,7 +5,7 @@ import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
|
5
5
|
import { shouldOutputJson } from '../../lib/prompt-json.js';
|
|
6
6
|
import { styles } from '../../lib/styles.js';
|
|
7
7
|
import { isGitRepo, isTicketId } from '../../lib/branch/index.js';
|
|
8
|
-
import {
|
|
8
|
+
import { findWorktreesByBranch as findDbWorktreesByBranch } from '../../lib/database/index.js';
|
|
9
9
|
export default class BranchWhere extends PMOCommand {
|
|
10
10
|
static description = 'Find which directory a branch is checked out in';
|
|
11
11
|
static examples = [
|
|
@@ -148,24 +148,13 @@ export default class BranchWhere extends PMOCommand {
|
|
|
148
148
|
const workspacePath = this.getWorkspacePath();
|
|
149
149
|
if (!workspacePath)
|
|
150
150
|
return [];
|
|
151
|
-
const db = openWorkspaceDatabase(workspacePath);
|
|
152
151
|
const searchLower = search.toLowerCase();
|
|
153
152
|
const isTicket = isTicketId(search);
|
|
154
|
-
//
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
query = 'SELECT * FROM agent_worktrees WHERE LOWER(branch) LIKE ?';
|
|
160
|
-
params = [`${searchLower}/%`];
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
// Match branches containing the search term
|
|
164
|
-
query = 'SELECT * FROM agent_worktrees WHERE LOWER(branch) LIKE ?';
|
|
165
|
-
params = [`%${searchLower}%`];
|
|
166
|
-
}
|
|
167
|
-
const rows = db.prepare(query).all(...params);
|
|
168
|
-
db.close();
|
|
153
|
+
// Build LIKE pattern based on search type
|
|
154
|
+
const branchPattern = isTicket
|
|
155
|
+
? `${searchLower}/%` // Match branches starting with ticket ID
|
|
156
|
+
: `%${searchLower}%`; // Match branches containing the search term
|
|
157
|
+
const rows = findDbWorktreesByBranch(workspacePath, branchPattern);
|
|
169
158
|
return rows.map(row => ({
|
|
170
159
|
path: path.join(workspacePath, row.worktree_path),
|
|
171
160
|
branch: row.branch,
|
|
@@ -81,11 +81,10 @@ export default class EpicTicket extends PMOCommand {
|
|
|
81
81
|
this.log(styles.muted('\nNo tickets found.'));
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
|
-
//
|
|
85
|
-
const db = this.storage.db;
|
|
84
|
+
// Helper to get ticket's epic ID from the loaded ticket list
|
|
86
85
|
const getTicketEpicId = (ticketId) => {
|
|
87
|
-
const
|
|
88
|
-
return
|
|
86
|
+
const ticket = allTickets.find((t) => t.id === ticketId);
|
|
87
|
+
return ticket?.epicId ?? null;
|
|
89
88
|
};
|
|
90
89
|
let epicId = args.id;
|
|
91
90
|
// If no epic ID provided, prompt for selection
|
|
@@ -201,11 +200,7 @@ export default class EpicTicket extends PMOCommand {
|
|
|
201
200
|
this.log(styles.muted(` ${ticketId} is not linked to ${epicId}, skipping`));
|
|
202
201
|
continue;
|
|
203
202
|
}
|
|
204
|
-
|
|
205
|
-
UPDATE pmo_tickets
|
|
206
|
-
SET epic_id = NULL, updated_at = ?
|
|
207
|
-
WHERE id = ?
|
|
208
|
-
`).run(Date.now(), ticketId);
|
|
203
|
+
await this.storage.unlinkTicketFromEpic(ticketId);
|
|
209
204
|
}
|
|
210
205
|
else {
|
|
211
206
|
// Link: check if already linked to same epic
|
|
@@ -253,11 +248,7 @@ export default class EpicTicket extends PMOCommand {
|
|
|
253
248
|
}
|
|
254
249
|
if (action === 'use_epic') {
|
|
255
250
|
// Update ticket to use epic's spec
|
|
256
|
-
|
|
257
|
-
UPDATE pmo_tickets
|
|
258
|
-
SET spec_id = ?, updated_at = ?
|
|
259
|
-
WHERE id = ?
|
|
260
|
-
`).run(epicSpecId, Date.now(), ticketId);
|
|
251
|
+
await this.storage.updateTicket(ticketId, { specId: epicSpecId });
|
|
261
252
|
this.log(styles.muted(` Updated ${ticketId} to use spec "${epicSpecId}"`));
|
|
262
253
|
}
|
|
263
254
|
}
|
|
@@ -284,19 +275,11 @@ export default class EpicTicket extends PMOCommand {
|
|
|
284
275
|
inherit = result.inherit;
|
|
285
276
|
}
|
|
286
277
|
if (inherit) {
|
|
287
|
-
|
|
288
|
-
UPDATE pmo_tickets
|
|
289
|
-
SET spec_id = ?, updated_at = ?
|
|
290
|
-
WHERE id = ?
|
|
291
|
-
`).run(epicSpecId, Date.now(), ticketId);
|
|
278
|
+
await this.storage.updateTicket(ticketId, { specId: epicSpecId });
|
|
292
279
|
this.log(styles.muted(` Assigned spec "${epicSpecId}" to ${ticketId}`));
|
|
293
280
|
}
|
|
294
281
|
}
|
|
295
|
-
|
|
296
|
-
UPDATE pmo_tickets
|
|
297
|
-
SET epic_id = ?, updated_at = ?
|
|
298
|
-
WHERE id = ?
|
|
299
|
-
`).run(epicId, Date.now(), ticketId);
|
|
282
|
+
await this.storage.linkTicketToEpic(ticketId, epicId);
|
|
300
283
|
}
|
|
301
284
|
linkedTickets.push(`${ticketId}: ${ticket.title}`);
|
|
302
285
|
successCount++;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import Database from 'better-sqlite3';
|
|
4
2
|
import inquirer from 'inquirer';
|
|
5
3
|
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
6
4
|
import { styles } from '../../lib/styles.js';
|
|
7
5
|
import { getWorkspaceInfo } from '../../lib/agents/commands.js';
|
|
6
|
+
import { openWorkspaceDatabase } from '../../lib/database/index.js';
|
|
8
7
|
import { loadExecutionConfig, saveTerminalApp, saveTerminalOpenInBackground, saveTmuxControlMode, saveShell, saveExecutionSetting, } from '../../lib/execution/config.js';
|
|
9
8
|
import { shouldOutputJson, outputSuccessAsJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
|
|
10
9
|
export default class ExecutionConfig extends PMOCommand {
|
|
@@ -54,8 +53,7 @@ export default class ExecutionConfig extends PMOCommand {
|
|
|
54
53
|
this.error('Not in a workspace. Run "prlt init" first.');
|
|
55
54
|
}
|
|
56
55
|
// Open database
|
|
57
|
-
const
|
|
58
|
-
const db = new Database(dbPath);
|
|
56
|
+
const db = openWorkspaceDatabase(workspaceInfo.path);
|
|
59
57
|
try {
|
|
60
58
|
// Load current config
|
|
61
59
|
const config = loadExecutionConfig(db);
|
|
@@ -388,20 +386,12 @@ export default class ExecutionConfig extends PMOCommand {
|
|
|
388
386
|
* Save output mode to workspace settings
|
|
389
387
|
*/
|
|
390
388
|
setOutputMode(db, mode) {
|
|
391
|
-
db
|
|
392
|
-
INSERT INTO workspace_settings (key, value)
|
|
393
|
-
VALUES (?, ?)
|
|
394
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value
|
|
395
|
-
`).run('execution.output_mode', mode);
|
|
389
|
+
saveExecutionSetting(db, 'outputMode', mode);
|
|
396
390
|
}
|
|
397
391
|
/**
|
|
398
392
|
* Save sandboxed preference to workspace settings
|
|
399
393
|
*/
|
|
400
394
|
setSandboxed(db, sandboxed) {
|
|
401
|
-
db.
|
|
402
|
-
INSERT INTO workspace_settings (key, value)
|
|
403
|
-
VALUES (?, ?)
|
|
404
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value
|
|
405
|
-
`).run('execution.sandboxed', sandboxed.toString());
|
|
395
|
+
saveExecutionSetting(db, 'sandboxed', sandboxed.toString());
|
|
406
396
|
}
|
|
407
397
|
}
|
|
@@ -90,6 +90,12 @@ export default class ExecutionLogs extends PMOCommand {
|
|
|
90
90
|
if (!execution.logPath) {
|
|
91
91
|
this.log(styles.muted(`\nNo log file for execution ${execId}`));
|
|
92
92
|
this.log(styles.muted(`Environment: ${execution.environment}`));
|
|
93
|
+
// Show error message if available (TKT-1082)
|
|
94
|
+
if (execution.errorMessage) {
|
|
95
|
+
this.log('');
|
|
96
|
+
this.log(styles.error('Error:'));
|
|
97
|
+
this.log(styles.error(` ${execution.errorMessage}`));
|
|
98
|
+
}
|
|
93
99
|
if (execution.sessionId) {
|
|
94
100
|
this.log('');
|
|
95
101
|
this.log(styles.muted('View in tmux:'));
|
|
@@ -104,6 +104,7 @@ export default class ExecutionView extends PMOCommand {
|
|
|
104
104
|
startedAt: execution.startedAt.toISOString(),
|
|
105
105
|
completedAt: execution.completedAt?.toISOString() || null,
|
|
106
106
|
exitCode: execution.exitCode ?? null,
|
|
107
|
+
errorMessage: execution.errorMessage || null,
|
|
107
108
|
}, createMetadata('execution view', flags));
|
|
108
109
|
}
|
|
109
110
|
// Display execution details
|
|
@@ -160,6 +161,13 @@ export default class ExecutionView extends PMOCommand {
|
|
|
160
161
|
this.log(`${styles.muted('Exit Code:')} ${exitStyle(execution.exitCode.toString())}`);
|
|
161
162
|
}
|
|
162
163
|
this.log('');
|
|
164
|
+
// Error details (TKT-1082)
|
|
165
|
+
if (execution.errorMessage) {
|
|
166
|
+
this.log(styles.header('Error'));
|
|
167
|
+
this.log('─'.repeat(40));
|
|
168
|
+
this.log(styles.error(execution.errorMessage));
|
|
169
|
+
this.log('');
|
|
170
|
+
}
|
|
163
171
|
// Logs summary
|
|
164
172
|
if (execution.logPath) {
|
|
165
173
|
this.log(styles.header('Logs'));
|
|
@@ -22,7 +22,7 @@ import Database from 'better-sqlite3';
|
|
|
22
22
|
import { getPMOContext } from '../lib/pmo/pmo-context.js';
|
|
23
23
|
import { getWorkspaceInfo } from '../lib/agents/commands.js';
|
|
24
24
|
import { ExecutionStorage } from '../lib/execution/storage.js';
|
|
25
|
-
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';
|
|
25
|
+
import { registerTicketTools, registerProjectTools, registerBoardTools, registerSpecTools, registerEpicTools, registerWorkTools, registerWorkflowTools, registerStatusTools, registerPhaseTools, registerActionTools, registerRoadmapTools, registerCategoryTools, registerTemplateTools, registerViewTools, registerDietTools, registerLabelTools, registerTmuxTools, registerAgentTools, registerDockerTools, registerRepoTools, registerBranchTools, registerGitHubTools, registerInitTools, registerUtilityTools, } from '../lib/mcp/index.js';
|
|
26
26
|
export default class McpServerCommand extends Command {
|
|
27
27
|
static description = 'Start MCP server for AI agent integration (exposes all prlt commands as tools)';
|
|
28
28
|
static hidden = true;
|
|
@@ -111,6 +111,7 @@ export default class McpServerCommand extends Command {
|
|
|
111
111
|
registerViewTools(server, ctx);
|
|
112
112
|
registerDietTools(server, ctx);
|
|
113
113
|
registerLabelTools(server, ctx);
|
|
114
|
+
registerTmuxTools(server, ctx);
|
|
114
115
|
registerAgentTools(server, ctx);
|
|
115
116
|
registerDockerTools(server, ctx);
|
|
116
117
|
registerRepoTools(server, ctx);
|
|
@@ -4,7 +4,7 @@ import * as path from 'node:path';
|
|
|
4
4
|
import { execSync } from 'node:child_process';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import { PromptCommand } from '../../lib/prompt-command.js';
|
|
7
|
-
import
|
|
7
|
+
import { checkPMOExists, getPMOSetting, dropPMOTables } from '../../lib/database/index.js';
|
|
8
8
|
import { SQLiteStorage, getColumnsForTemplate, createPMO, promptForPMOLocation, promptForBoardTemplate, promptForBoardName, promptForCustomColumns, determinePMOPath, getPickerTemplates, machineOutputFlags, } from '../../lib/pmo/index.js';
|
|
9
9
|
import { styles } from '../../lib/styles.js';
|
|
10
10
|
import { isGHInstalled, isGHAuthenticated, getGHUsername, isGHTokenInEnv } from '../../lib/pr/index.js';
|
|
@@ -56,17 +56,10 @@ export default class PMOInit extends PromptCommand {
|
|
|
56
56
|
const dbPath = path.join(hqRoot, '.proletariat', 'workspace.db');
|
|
57
57
|
if (fs.existsSync(dbPath)) {
|
|
58
58
|
try {
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
// Get counts
|
|
64
|
-
const projectCountResult = db.prepare('SELECT COUNT(*) as count FROM pmo_projects').get();
|
|
65
|
-
const ticketCountResult = db.prepare('SELECT COUNT(*) as count FROM pmo_tickets').get();
|
|
66
|
-
projectCount = projectCountResult.count;
|
|
67
|
-
ticketCount = ticketCountResult.count;
|
|
68
|
-
}
|
|
69
|
-
db.close();
|
|
59
|
+
const pmoStatus = checkPMOExists(dbPath);
|
|
60
|
+
existingPMO = pmoStatus.exists;
|
|
61
|
+
projectCount = pmoStatus.projectCount;
|
|
62
|
+
ticketCount = pmoStatus.ticketCount;
|
|
70
63
|
}
|
|
71
64
|
catch (error) {
|
|
72
65
|
// Log error for debugging
|
|
@@ -243,16 +236,9 @@ export default class PMOInit extends PromptCommand {
|
|
|
243
236
|
// Find PMO location from database
|
|
244
237
|
const dbPath = path.join(hqRoot, '.proletariat', 'workspace.db');
|
|
245
238
|
let pmoPath = path.join(hqRoot, 'pmo'); // Default fallback
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
if (result) {
|
|
250
|
-
pmoPath = result.value;
|
|
251
|
-
}
|
|
252
|
-
db.close();
|
|
253
|
-
}
|
|
254
|
-
catch {
|
|
255
|
-
// Use default if table doesn't exist
|
|
239
|
+
const savedPmoPath = getPMOSetting(dbPath, 'pmo_path');
|
|
240
|
+
if (savedPmoPath) {
|
|
241
|
+
pmoPath = savedPmoPath;
|
|
256
242
|
}
|
|
257
243
|
// Define choices once, use for both JSON and interactive modes
|
|
258
244
|
const actionChoices = [
|
|
@@ -336,30 +322,16 @@ export default class PMOInit extends PromptCommand {
|
|
|
336
322
|
const dbPath = path.join(hqRoot, '.proletariat', 'workspace.db');
|
|
337
323
|
let pmoPath = path.join(hqRoot, 'pmo'); // Default fallback
|
|
338
324
|
if (fs.existsSync(dbPath)) {
|
|
339
|
-
const db = new Database(dbPath);
|
|
340
325
|
// Get PMO path from database before deleting
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
pmoPath = result.value;
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
catch {
|
|
348
|
-
// Ignore - table might not exist, use default
|
|
326
|
+
const savedPmoPath = getPMOSetting(dbPath, 'pmo_path');
|
|
327
|
+
if (savedPmoPath) {
|
|
328
|
+
pmoPath = savedPmoPath;
|
|
349
329
|
}
|
|
350
330
|
// Drop all pmo_* tables
|
|
351
331
|
const tables = ['pmo_ticket_specs', 'pmo_ticket_metadata', 'pmo_subtasks', 'pmo_tickets',
|
|
352
332
|
'pmo_columns', 'pmo_specs', 'pmo_epics', 'pmo_projects',
|
|
353
333
|
'pmo_initiatives', 'pmo_ticket_assignments', 'pmo_cache_metadata', 'pmo_settings'];
|
|
354
|
-
|
|
355
|
-
try {
|
|
356
|
-
db.prepare(`DROP TABLE IF EXISTS ${table}`).run();
|
|
357
|
-
}
|
|
358
|
-
catch {
|
|
359
|
-
// Ignore errors - table might not exist
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
db.close();
|
|
334
|
+
dropPMOTables(dbPath, tables);
|
|
363
335
|
this.log(chalk.green(' ✓ Dropped database tables'));
|
|
364
336
|
}
|
|
365
337
|
// Delete pmo/ directory (using path from database or default)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { PromptCommand } from '../../lib/prompt-command.js';
|
|
2
|
+
export default class QA extends PromptCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static aliases: string[];
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
seed: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
watch: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
environment: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'display-mode': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'permission-mode': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
prompt: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Load the explore-cli action prompt from PMO storage.
|
|
19
|
+
*/
|
|
20
|
+
private getExploreCLIPrompt;
|
|
21
|
+
/**
|
|
22
|
+
* Run seed-explore-data.mjs to pre-populate test data.
|
|
23
|
+
*/
|
|
24
|
+
private runSeedData;
|
|
25
|
+
/**
|
|
26
|
+
* Run in tracked mode - inside an HQ
|
|
27
|
+
* Creates an ephemeral QA agent with full tracking
|
|
28
|
+
*/
|
|
29
|
+
private runTracked;
|
|
30
|
+
/**
|
|
31
|
+
* Run in yolo mode - outside any HQ
|
|
32
|
+
*/
|
|
33
|
+
private runYolo;
|
|
34
|
+
/**
|
|
35
|
+
* Resolve execution environment (devcontainer vs host).
|
|
36
|
+
*/
|
|
37
|
+
private resolveEnvironment;
|
|
38
|
+
/**
|
|
39
|
+
* Resolve display mode.
|
|
40
|
+
*/
|
|
41
|
+
private resolveDisplayMode;
|
|
42
|
+
/**
|
|
43
|
+
* Resolve permission mode. Defaults to danger for QA (container provides isolation).
|
|
44
|
+
*/
|
|
45
|
+
private resolvePermissionMode;
|
|
46
|
+
/**
|
|
47
|
+
* Set up catch-all devcontainer for directories without one.
|
|
48
|
+
*/
|
|
49
|
+
private setupCatchallDevcontainer;
|
|
50
|
+
/**
|
|
51
|
+
* Check if catch-all container image is available.
|
|
52
|
+
*/
|
|
53
|
+
private checkCatchallImage;
|
|
54
|
+
}
|