vibecodingmachine-cli 2026.2.26-1739 → 2026.3.9-1621
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/bin/auth/auth-compliance.js +7 -1
- package/bin/commands/agent-commands.js +150 -228
- package/bin/commands/command-aliases.js +68 -0
- package/bin/vibecodingmachine.js +1 -2
- package/package.json +2 -2
- package/src/commands/agents/list.js +71 -115
- package/src/commands/agents-check.js +16 -4
- package/src/commands/analyze-file-sizes.js +1 -1
- package/src/commands/auto-direct/auto-provider-manager.js +290 -0
- package/src/commands/auto-direct/auto-status-display.js +331 -0
- package/src/commands/auto-direct/auto-utils.js +439 -0
- package/src/commands/auto-direct/file-operations.js +110 -0
- package/src/commands/auto-direct/provider-config.js +1 -1
- package/src/commands/auto-direct/provider-manager.js +1 -1
- package/src/commands/auto-direct/status-display.js +1 -1
- package/src/commands/auto-direct/utils.js +24 -18
- package/src/commands/auto-direct-refactored.js +413 -0
- package/src/commands/auto-direct.js +594 -188
- package/src/commands/requirements/commands.js +353 -0
- package/src/commands/requirements/default-handlers.js +272 -0
- package/src/commands/requirements/disable.js +97 -0
- package/src/commands/requirements/enable.js +97 -0
- package/src/commands/requirements/utils.js +194 -0
- package/src/commands/requirements-refactored.js +60 -0
- package/src/commands/requirements.js +38 -771
- package/src/commands/specs/disable.js +96 -0
- package/src/commands/specs/enable.js +96 -0
- package/src/trui/TruiInterface.js +5 -11
- package/src/trui/agents/AgentInterface.js +24 -396
- package/src/trui/agents/handlers/CommandHandler.js +93 -0
- package/src/trui/agents/handlers/ContextManager.js +117 -0
- package/src/trui/agents/handlers/DisplayHandler.js +243 -0
- package/src/trui/agents/handlers/HelpHandler.js +51 -0
- package/src/utils/auth.js +13 -111
- package/src/utils/config.js +5 -1
- package/src/utils/interactive/requirements-navigation.js +17 -15
- package/src/utils/interactive-broken.js +2 -2
- package/src/utils/provider-checker/agent-runner.js +15 -1
- package/src/utils/provider-checker/cli-installer.js +149 -7
- package/src/utils/provider-checker/opencode-checker.js +588 -0
- package/src/utils/provider-checker/provider-validator.js +88 -3
- package/src/utils/provider-checker/time-formatter.js +3 -2
- package/src/utils/provider-manager.js +28 -20
- package/src/utils/provider-registry.js +35 -3
- package/src/utils/requirements-navigator/index.js +94 -0
- package/src/utils/requirements-navigator/input-handler.js +217 -0
- package/src/utils/requirements-navigator/section-loader.js +188 -0
- package/src/utils/requirements-navigator/tree-builder.js +105 -0
- package/src/utils/requirements-navigator/tree-renderer.js +50 -0
- package/src/utils/requirements-navigator.js +2 -583
- package/src/utils/trui-clarifications.js +188 -0
- package/src/utils/trui-feedback.js +54 -1
- package/src/utils/trui-kiro-integration.js +398 -0
- package/src/utils/trui-main-handlers.js +194 -0
- package/src/utils/trui-main-menu.js +235 -0
- package/src/utils/trui-nav-agents.js +178 -25
- package/src/utils/trui-nav-requirements.js +203 -27
- package/src/utils/trui-nav-settings.js +114 -1
- package/src/utils/trui-nav-specifications.js +44 -3
- package/src/utils/trui-navigation-backup.js +603 -0
- package/src/utils/trui-navigation.js +70 -228
- package/src/utils/trui-provider-health.js +274 -0
- package/src/utils/trui-provider-manager.js +376 -0
- package/src/utils/trui-quick-menu.js +25 -1
- package/src/utils/trui-req-actions-backup.js +507 -0
- package/src/utils/trui-req-actions.js +148 -216
- package/src/utils/trui-req-editor.js +170 -0
- package/src/utils/trui-req-file-ops.js +278 -0
- package/src/utils/trui-req-tree-old.js +719 -0
- package/src/utils/trui-req-tree.js +348 -627
- package/src/utils/trui-specifications.js +25 -7
- package/src/utils/trui-windsurf.js +231 -10
- package/src/utils/welcome-screen-extracted.js +2 -2
- package/src/utils/welcome-screen.js +2 -2
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Requirements Commands
|
|
3
|
+
*
|
|
4
|
+
* Core requirements management commands
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs-extra');
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
const chokidar = require('chokidar');
|
|
10
|
+
const {
|
|
11
|
+
getReqPathOrExit,
|
|
12
|
+
ensureRequirementsFile,
|
|
13
|
+
loadRequirements,
|
|
14
|
+
saveRequirements,
|
|
15
|
+
findRequirementByTitle,
|
|
16
|
+
findRequirementById,
|
|
17
|
+
generateRequirementId,
|
|
18
|
+
validateRequirement,
|
|
19
|
+
formatRequirement,
|
|
20
|
+
openInEditor
|
|
21
|
+
} = require('./utils');
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* List all requirements
|
|
25
|
+
*/
|
|
26
|
+
async function list(options) {
|
|
27
|
+
try {
|
|
28
|
+
const { repoPath, reqPath } = await getReqPathOrExit();
|
|
29
|
+
|
|
30
|
+
if (!await fs.pathExists(reqPath)) {
|
|
31
|
+
console.log(chalk.yellow('No requirements file found. Use "app req add" to create one.'));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const data = await loadRequirements(reqPath);
|
|
36
|
+
const { requirements, current } = data;
|
|
37
|
+
|
|
38
|
+
if (requirements.length === 0) {
|
|
39
|
+
console.log(chalk.yellow('No requirements found.'));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log(chalk.blue('\nRequirements:'));
|
|
44
|
+
|
|
45
|
+
if (options.verbose) {
|
|
46
|
+
requirements.forEach((req, index) => {
|
|
47
|
+
const isCurrent = current && current.id === req.id;
|
|
48
|
+
console.log(`${index + 1}. ${formatRequirement(req, isCurrent)}`);
|
|
49
|
+
if (req.description) {
|
|
50
|
+
console.log(` ${chalk.gray(req.description)}`);
|
|
51
|
+
}
|
|
52
|
+
if (req.package) {
|
|
53
|
+
console.log(` ${chalk.cyan('Package:')} ${req.package}`);
|
|
54
|
+
}
|
|
55
|
+
if (req.created) {
|
|
56
|
+
console.log(` ${chalk.gray('Created:')} ${new Date(req.created).toLocaleDateString()}`);
|
|
57
|
+
}
|
|
58
|
+
console.log();
|
|
59
|
+
});
|
|
60
|
+
} else {
|
|
61
|
+
requirements.forEach((req, index) => {
|
|
62
|
+
const isCurrent = current && current.id === req.id;
|
|
63
|
+
console.log(`${index + 1}. ${formatRequirement(req, isCurrent)}`);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (current) {
|
|
68
|
+
console.log(chalk.green(`\nCurrent: ${current.title}`));
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.error(chalk.red('Error listing requirements:'), error.message);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Add a new requirement
|
|
77
|
+
*/
|
|
78
|
+
async function add(name, pkg, description) {
|
|
79
|
+
try {
|
|
80
|
+
const { reqPath, repoPath } = await getReqPathOrExit();
|
|
81
|
+
await ensureRequirementsFile(reqPath);
|
|
82
|
+
|
|
83
|
+
const data = await loadRequirements(reqPath);
|
|
84
|
+
const { requirements } = data;
|
|
85
|
+
|
|
86
|
+
// Check for duplicate
|
|
87
|
+
if (findRequirementByTitle(requirements, name)) {
|
|
88
|
+
console.error(chalk.red('Requirement with this title already exists.'));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Create new requirement
|
|
93
|
+
const requirement = {
|
|
94
|
+
id: generateRequirementId(requirements),
|
|
95
|
+
title: name,
|
|
96
|
+
description: description || '',
|
|
97
|
+
package: pkg || '',
|
|
98
|
+
status: 'pending',
|
|
99
|
+
created: new Date().toISOString(),
|
|
100
|
+
updated: new Date().toISOString()
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
if (!validateRequirement(requirement)) {
|
|
104
|
+
console.error(chalk.red('Invalid requirement data.'));
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
requirements.push(requirement);
|
|
109
|
+
await saveRequirements(reqPath, data);
|
|
110
|
+
|
|
111
|
+
console.log(chalk.green('Requirement added successfully:'));
|
|
112
|
+
console.log(` ${formatRequirement(requirement)}`);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error(chalk.red('Error adding requirement:'), error.message);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Show current requirement
|
|
120
|
+
*/
|
|
121
|
+
async function current() {
|
|
122
|
+
try {
|
|
123
|
+
const { reqPath } = await getReqPathOrExit();
|
|
124
|
+
|
|
125
|
+
if (!await fs.pathExists(reqPath)) {
|
|
126
|
+
console.log(chalk.yellow('No requirements file found.'));
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const data = await loadRequirements(reqPath);
|
|
131
|
+
const { current } = data;
|
|
132
|
+
|
|
133
|
+
if (!current) {
|
|
134
|
+
console.log(chalk.yellow('No current requirement set.'));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
console.log(chalk.blue('\nCurrent Requirement:'));
|
|
139
|
+
console.log(` ${formatRequirement(current, true)}`);
|
|
140
|
+
|
|
141
|
+
if (current.description) {
|
|
142
|
+
console.log(chalk.gray(`\nDescription: ${current.description}`));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (current.package) {
|
|
146
|
+
console.log(chalk.cyan(`Package: ${current.package}`));
|
|
147
|
+
}
|
|
148
|
+
} catch (error) {
|
|
149
|
+
console.error(chalk.red('Error getting current requirement:'), error.message);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Set next requirement as current
|
|
155
|
+
*/
|
|
156
|
+
async function next() {
|
|
157
|
+
try {
|
|
158
|
+
const { reqPath } = await getReqPathOrExit();
|
|
159
|
+
|
|
160
|
+
if (!await fs.pathExists(reqPath)) {
|
|
161
|
+
console.log(chalk.yellow('No requirements file found.'));
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const data = await loadRequirements(reqPath);
|
|
166
|
+
const { requirements, current } = data;
|
|
167
|
+
|
|
168
|
+
if (requirements.length === 0) {
|
|
169
|
+
console.log(chalk.yellow('No requirements found.'));
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Find next requirement
|
|
174
|
+
let nextReq;
|
|
175
|
+
if (!current) {
|
|
176
|
+
nextReq = requirements[0];
|
|
177
|
+
} else {
|
|
178
|
+
const currentIndex = requirements.findIndex(req => req.id === current.id);
|
|
179
|
+
if (currentIndex >= 0 && currentIndex < requirements.length - 1) {
|
|
180
|
+
nextReq = requirements[currentIndex + 1];
|
|
181
|
+
} else {
|
|
182
|
+
console.log(chalk.yellow('Already at the last requirement.'));
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Update current
|
|
188
|
+
data.current = nextReq;
|
|
189
|
+
await saveRequirements(reqPath, data);
|
|
190
|
+
|
|
191
|
+
console.log(chalk.green('Current requirement updated:'));
|
|
192
|
+
console.log(` ${formatRequirement(nextReq, true)}`);
|
|
193
|
+
} catch (error) {
|
|
194
|
+
console.error(chalk.red('Error setting next requirement:'), error.message);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Edit requirements file
|
|
200
|
+
*/
|
|
201
|
+
async function edit() {
|
|
202
|
+
try {
|
|
203
|
+
const { reqPath } = await getReqPathOrExit();
|
|
204
|
+
|
|
205
|
+
if (!await fs.pathExists(reqPath)) {
|
|
206
|
+
console.log(chalk.yellow('No requirements file found. Creating new one...'));
|
|
207
|
+
await ensureRequirementsFile(reqPath);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
console.log(chalk.gray('Opening requirements file in default editor...'));
|
|
211
|
+
await openInEditor(reqPath);
|
|
212
|
+
} catch (error) {
|
|
213
|
+
console.error(chalk.red('Error editing requirements:'), error.message);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Watch requirements file for changes
|
|
219
|
+
*/
|
|
220
|
+
async function watch() {
|
|
221
|
+
try {
|
|
222
|
+
const { reqPath } = await getReqPathOrExit();
|
|
223
|
+
|
|
224
|
+
if (!await fs.pathExists(reqPath)) {
|
|
225
|
+
console.log(chalk.yellow('No requirements file found.'));
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
console.log(chalk.gray('Watching:'), chalk.cyan(reqPath));
|
|
230
|
+
|
|
231
|
+
const watcher = chokidar.watch(reqPath);
|
|
232
|
+
|
|
233
|
+
watcher.on('change', async () => {
|
|
234
|
+
console.log(chalk.blue('\nRequirements file changed. Reloading...'));
|
|
235
|
+
const data = await loadRequirements(reqPath);
|
|
236
|
+
const { requirements, current } = data;
|
|
237
|
+
|
|
238
|
+
console.log(chalk.green(`Found ${requirements.length} requirements`));
|
|
239
|
+
if (current) {
|
|
240
|
+
console.log(chalk.cyan(`Current: ${current.title}`));
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
console.log(chalk.green('Watching for changes. Press Ctrl+C to stop.'));
|
|
245
|
+
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.error(chalk.red('Error watching requirements:'), error.message);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Rename a requirement
|
|
253
|
+
*/
|
|
254
|
+
async function rename(oldTitle, newTitle, description) {
|
|
255
|
+
try {
|
|
256
|
+
const { reqPath } = await getReqPathOrExit();
|
|
257
|
+
|
|
258
|
+
if (!await fs.pathExists(reqPath)) {
|
|
259
|
+
console.log(chalk.yellow('No requirements file found.'));
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const data = await loadRequirements(reqPath);
|
|
264
|
+
const { requirements, current } = data;
|
|
265
|
+
|
|
266
|
+
const requirement = findRequirementByTitle(requirements, oldTitle);
|
|
267
|
+
if (!requirement) {
|
|
268
|
+
console.error(chalk.red('Requirement not found.'));
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Check for duplicate new title
|
|
273
|
+
if (findRequirementByTitle(requirements, newTitle)) {
|
|
274
|
+
console.error(chalk.red('A requirement with the new title already exists.'));
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Update requirement
|
|
279
|
+
requirement.title = newTitle;
|
|
280
|
+
requirement.updated = new Date().toISOString();
|
|
281
|
+
|
|
282
|
+
if (description) {
|
|
283
|
+
requirement.description = description;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Update current if needed
|
|
287
|
+
if (current && current.id === requirement.id) {
|
|
288
|
+
data.current = requirement;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
await saveRequirements(reqPath, data);
|
|
292
|
+
|
|
293
|
+
console.log(chalk.green('Requirement renamed successfully:'));
|
|
294
|
+
console.log(` ${formatRequirement(requirement)}`);
|
|
295
|
+
} catch (error) {
|
|
296
|
+
console.error(chalk.red('Error renaming requirement:'), error.message);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Show working requirement (alias for current)
|
|
302
|
+
*/
|
|
303
|
+
async function working() {
|
|
304
|
+
return await current();
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Number all requirements
|
|
309
|
+
*/
|
|
310
|
+
async function numberAll() {
|
|
311
|
+
try {
|
|
312
|
+
const { reqPath, repoPath } = await getReqPathOrExit();
|
|
313
|
+
|
|
314
|
+
if (!await fs.pathExists(reqPath)) {
|
|
315
|
+
console.log(chalk.yellow('No requirements file found.'));
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const data = await loadRequirements(reqPath);
|
|
320
|
+
const { requirements } = data;
|
|
321
|
+
|
|
322
|
+
let changed = false;
|
|
323
|
+
requirements.forEach((req, index) => {
|
|
324
|
+
const newId = `R${index + 1}`;
|
|
325
|
+
if (req.id !== newId) {
|
|
326
|
+
req.id = newId;
|
|
327
|
+
req.updated = new Date().toISOString();
|
|
328
|
+
changed = true;
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
if (changed) {
|
|
333
|
+
await saveRequirements(reqPath, data);
|
|
334
|
+
console.log(chalk.green('Requirements renumbered successfully.'));
|
|
335
|
+
} else {
|
|
336
|
+
console.log(chalk.gray('Requirements already numbered correctly.'));
|
|
337
|
+
}
|
|
338
|
+
} catch (error) {
|
|
339
|
+
console.error(chalk.red('Error numbering requirements:'), error.message);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
module.exports = {
|
|
344
|
+
list,
|
|
345
|
+
add,
|
|
346
|
+
current,
|
|
347
|
+
next,
|
|
348
|
+
edit,
|
|
349
|
+
watch,
|
|
350
|
+
rename,
|
|
351
|
+
working,
|
|
352
|
+
numberAll
|
|
353
|
+
};
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default Requirement Handlers
|
|
3
|
+
*
|
|
4
|
+
* Commands for managing default requirements
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs-extra');
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const { getRepoPath } = require('../../utils/config');
|
|
11
|
+
const { DefaultRequirementManager, JSONStorage } = require('vibecodingmachine-core');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Create a new default requirement
|
|
15
|
+
*/
|
|
16
|
+
async function createDefault(title, options = {}) {
|
|
17
|
+
const { description, maxIterations } = options;
|
|
18
|
+
const repoPath = await getRepoPath();
|
|
19
|
+
|
|
20
|
+
if (!repoPath) {
|
|
21
|
+
console.error(chalk.red('No repository configured. Run "app init" first.'));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const storage = new JSONStorage(path.join(repoPath, '.vibecodingmachine'));
|
|
27
|
+
const manager = new DefaultRequirementManager(storage);
|
|
28
|
+
|
|
29
|
+
await manager.create({
|
|
30
|
+
title,
|
|
31
|
+
description: description || '',
|
|
32
|
+
maxIterations: maxIterations || 5
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
console.log(chalk.green('Default requirement created successfully:'));
|
|
36
|
+
console.log(` ${chalk.cyan('Title:')} ${title}`);
|
|
37
|
+
if (description) {
|
|
38
|
+
console.log(` ${chalk.gray('Description:')} ${description}`);
|
|
39
|
+
}
|
|
40
|
+
console.log(` ${chalk.yellow('Max Iterations:')} ${maxIterations || 5}`);
|
|
41
|
+
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error(chalk.red('Error creating default requirement:'), error.message);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Edit existing default requirement
|
|
49
|
+
*/
|
|
50
|
+
async function editDefault(options = {}) {
|
|
51
|
+
const { title, description, maxIterations } = options;
|
|
52
|
+
const repoPath = await getRepoPath();
|
|
53
|
+
|
|
54
|
+
if (!repoPath) {
|
|
55
|
+
console.error(chalk.red('No repository configured. Run "app init" first.'));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const storage = new JSONStorage(path.join(repoPath, '.vibecodingmachine'));
|
|
61
|
+
const manager = new DefaultRequirementManager(storage);
|
|
62
|
+
|
|
63
|
+
const current = await manager.getCurrent();
|
|
64
|
+
if (!current) {
|
|
65
|
+
console.error(chalk.red('No default requirement found. Create one first.'));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const updates = {};
|
|
70
|
+
if (title !== undefined) updates.title = title;
|
|
71
|
+
if (description !== undefined) updates.description = description;
|
|
72
|
+
if (maxIterations !== undefined) updates.maxIterations = maxIterations;
|
|
73
|
+
|
|
74
|
+
await manager.update(current.id, updates);
|
|
75
|
+
|
|
76
|
+
console.log(chalk.green('Default requirement updated successfully:'));
|
|
77
|
+
|
|
78
|
+
const updated = await manager.getCurrent();
|
|
79
|
+
console.log(` ${chalk.cyan('Title:')} ${updated.title}`);
|
|
80
|
+
if (updated.description) {
|
|
81
|
+
console.log(` ${chalk.gray('Description:')} ${updated.description}`);
|
|
82
|
+
}
|
|
83
|
+
console.log(` ${chalk.yellow('Max Iterations:')} ${updated.maxIterations}`);
|
|
84
|
+
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error(chalk.red('Error editing default requirement:'), error.message);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Delete default requirement
|
|
92
|
+
*/
|
|
93
|
+
async function deleteDefault() {
|
|
94
|
+
const repoPath = await getRepoPath();
|
|
95
|
+
|
|
96
|
+
if (!repoPath) {
|
|
97
|
+
console.error(chalk.red('No repository configured. Run "app init" first.'));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
const storage = new JSONStorage(path.join(repoPath, '.vibecodingmachine'));
|
|
103
|
+
const manager = new DefaultRequirementManager(storage);
|
|
104
|
+
|
|
105
|
+
const current = await manager.getCurrent();
|
|
106
|
+
if (!current) {
|
|
107
|
+
console.error(chalk.red('No default requirement found.'));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
await manager.delete(current.id);
|
|
112
|
+
console.log(chalk.green('Default requirement deleted successfully.'));
|
|
113
|
+
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error(chalk.red('Error deleting default requirement:'), error.message);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Show current default requirement status
|
|
121
|
+
*/
|
|
122
|
+
async function showDefault() {
|
|
123
|
+
const repoPath = await getRepoPath();
|
|
124
|
+
|
|
125
|
+
if (!repoPath) {
|
|
126
|
+
console.error(chalk.red('No repository configured. Run "app init" first.'));
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const storage = new JSONStorage(path.join(repoPath, '.vibecodingmachine'));
|
|
132
|
+
const manager = new DefaultRequirementManager(storage);
|
|
133
|
+
|
|
134
|
+
const current = await manager.getCurrent();
|
|
135
|
+
if (!current) {
|
|
136
|
+
console.log(chalk.yellow('No default requirement found.'));
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
console.log(chalk.blue('\nDefault Requirement:'));
|
|
141
|
+
console.log(` ${chalk.cyan('ID:')} ${current.id}`);
|
|
142
|
+
console.log(` ${chalk.cyan('Title:')} ${current.title}`);
|
|
143
|
+
|
|
144
|
+
if (current.description) {
|
|
145
|
+
console.log(` ${chalk.gray('Description:')} ${current.description}`);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
console.log(` ${chalk.yellow('Max Iterations:')} ${current.maxIterations}`);
|
|
149
|
+
console.log(` ${chalk.gray('Status:')} ${current.status}`);
|
|
150
|
+
|
|
151
|
+
if (current.createdAt) {
|
|
152
|
+
console.log(` ${chalk.gray('Created:')} ${new Date(current.createdAt).toLocaleString()}`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (current.updatedAt) {
|
|
156
|
+
console.log(` ${chalk.gray('Updated:')} ${new Date(current.updatedAt).toLocaleString()}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (current.iterations && current.iterations.length > 0) {
|
|
160
|
+
console.log(` ${chalk.blue('Iterations:')} ${current.iterations.length}`);
|
|
161
|
+
current.iterations.forEach((iteration, index) => {
|
|
162
|
+
const status = iteration.completed ? '✓' : '○';
|
|
163
|
+
console.log(` ${index + 1}. ${status} ${iteration.summary || 'No summary'}`);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
} catch (error) {
|
|
168
|
+
console.error(chalk.red('Error showing default requirement:'), error.message);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Pause default requirement
|
|
174
|
+
*/
|
|
175
|
+
async function pauseDefault() {
|
|
176
|
+
const repoPath = await getRepoPath();
|
|
177
|
+
|
|
178
|
+
if (!repoPath) {
|
|
179
|
+
console.error(chalk.red('No repository configured. Run "app init" first.'));
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
const storage = new JSONStorage(path.join(repoPath, '.vibecodingmachine'));
|
|
185
|
+
const manager = new DefaultRequirementManager(storage);
|
|
186
|
+
|
|
187
|
+
const current = await manager.getCurrent();
|
|
188
|
+
if (!current) {
|
|
189
|
+
console.error(chalk.red('No default requirement found.'));
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
await manager.pause(current.id);
|
|
194
|
+
console.log(chalk.green('Default requirement paused successfully.'));
|
|
195
|
+
|
|
196
|
+
} catch (error) {
|
|
197
|
+
console.error(chalk.red('Error pausing default requirement:'), error.message);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Resume default requirement
|
|
203
|
+
*/
|
|
204
|
+
async function resumeDefault() {
|
|
205
|
+
const repoPath = await getRepoPath();
|
|
206
|
+
|
|
207
|
+
if (!repoPath) {
|
|
208
|
+
console.error(chalk.red('No repository configured. Run "app init" first.'));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
const storage = new JSONStorage(path.join(repoPath, '.vibecodingmachine'));
|
|
214
|
+
const manager = new DefaultRequirementManager(storage);
|
|
215
|
+
|
|
216
|
+
const current = await manager.getCurrent();
|
|
217
|
+
if (!current) {
|
|
218
|
+
console.error(chalk.red('No default requirement found.'));
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
await manager.resume(current.id);
|
|
223
|
+
console.log(chalk.green('Default requirement resumed successfully.'));
|
|
224
|
+
|
|
225
|
+
} catch (error) {
|
|
226
|
+
console.error(chalk.red('Error resuming default requirement:'), error.message);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Set max iterations for default requirement
|
|
232
|
+
*/
|
|
233
|
+
async function setMaxIterations(maxIterations) {
|
|
234
|
+
const repoPath = await getRepoPath();
|
|
235
|
+
|
|
236
|
+
if (!repoPath) {
|
|
237
|
+
console.error(chalk.red('No repository configured. Run "app init" first.'));
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (!maxIterations || maxIterations < 1) {
|
|
242
|
+
console.error(chalk.red('Max iterations must be a positive number.'));
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
const storage = new JSONStorage(path.join(repoPath, '.vibecodingmachine'));
|
|
248
|
+
const manager = new DefaultRequirementManager(storage);
|
|
249
|
+
|
|
250
|
+
const current = await manager.getCurrent();
|
|
251
|
+
if (!current) {
|
|
252
|
+
console.error(chalk.red('No default requirement found.'));
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
await manager.update(current.id, { maxIterations: parseInt(maxIterations) });
|
|
257
|
+
console.log(chalk.green(`Max iterations set to ${maxIterations}`));
|
|
258
|
+
|
|
259
|
+
} catch (error) {
|
|
260
|
+
console.error(chalk.red('Error setting max iterations:'), error.message);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
module.exports = {
|
|
265
|
+
createDefault,
|
|
266
|
+
editDefault,
|
|
267
|
+
deleteDefault,
|
|
268
|
+
showDefault,
|
|
269
|
+
pauseDefault,
|
|
270
|
+
resumeDefault,
|
|
271
|
+
setMaxIterations
|
|
272
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Command: Disable Requirement
|
|
3
|
+
*
|
|
4
|
+
* Implements "app disable requirement" command for CLI interface.
|
|
5
|
+
* Follows constitutional requirements: <800 lines, test-first approach.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { disableRequirement } = require('@vibecodingmachine/core/src/utils/requirement-enable-disable');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* CLI disable requirement command implementation
|
|
12
|
+
*/
|
|
13
|
+
class DisableRequirementCommand {
|
|
14
|
+
/**
|
|
15
|
+
* Create command instance
|
|
16
|
+
* @param {Object} options - Command options
|
|
17
|
+
*/
|
|
18
|
+
constructor(options = {}) {
|
|
19
|
+
this.options = options;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Execute disable requirement command
|
|
24
|
+
* @param {Array} args - Command arguments [requirementText]
|
|
25
|
+
* @param {Object} options - Command options
|
|
26
|
+
* @returns {Promise<Object>} - Command result
|
|
27
|
+
*/
|
|
28
|
+
async execute(args = [], options = {}) {
|
|
29
|
+
try {
|
|
30
|
+
// Parse arguments - requirement text can contain spaces
|
|
31
|
+
const requirementText = args.join(' ');
|
|
32
|
+
if (!requirementText) {
|
|
33
|
+
return {
|
|
34
|
+
success: false,
|
|
35
|
+
error: 'Missing required argument: requirementText',
|
|
36
|
+
usage: 'app disable requirement <requirementText>',
|
|
37
|
+
examples: [
|
|
38
|
+
'app disable requirement "Add user authentication"',
|
|
39
|
+
'app disable requirement "Implement OAuth2 login"'
|
|
40
|
+
]
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Call core disable function
|
|
45
|
+
const result = await disableRequirement(requirementText);
|
|
46
|
+
|
|
47
|
+
if (!result.success) {
|
|
48
|
+
return {
|
|
49
|
+
success: false,
|
|
50
|
+
error: result.message
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
success: true,
|
|
56
|
+
message: result.message,
|
|
57
|
+
data: {
|
|
58
|
+
requirementText,
|
|
59
|
+
status: 'disabled',
|
|
60
|
+
disabledAt: new Date().toISOString()
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
} catch (error) {
|
|
64
|
+
return {
|
|
65
|
+
success: false,
|
|
66
|
+
error: `Failed to disable requirement: ${error.message}`
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get command help
|
|
73
|
+
* @returns {string} - Help text
|
|
74
|
+
*/
|
|
75
|
+
getHelp() {
|
|
76
|
+
return `
|
|
77
|
+
Disable a requirement
|
|
78
|
+
|
|
79
|
+
Usage:
|
|
80
|
+
app disable requirement <requirementText>
|
|
81
|
+
|
|
82
|
+
Arguments:
|
|
83
|
+
requirementText Exact text of the requirement to disable
|
|
84
|
+
|
|
85
|
+
Examples:
|
|
86
|
+
app disable requirement "Add user authentication"
|
|
87
|
+
app disable requirement "Implement OAuth2 login"
|
|
88
|
+
app disable requirement "Create user registration page"
|
|
89
|
+
|
|
90
|
+
Description:
|
|
91
|
+
Disables a requirement by adding the DISABLED: prefix.
|
|
92
|
+
Disabled requirements will be skipped by auto-mode when running "start auto".
|
|
93
|
+
`.trim();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
module.exports = DisableRequirementCommand;
|