run method
Runs this command.
The return value is wrapped in a Future if necessary and returned by
CommandRunner.runCommand.
Implementation
@override
Future<void> run() async {
if (!ContextService.isInitialized()) {
print('ContextForge has not been initialized.\nRun: contextforge init');
return;
}
ContextService.ensureDataFilesExist();
// Prompt for task details
stdout.write('Task ID (e.g., feature-auth): ');
var id = stdin.readLineSync() ?? '';
id = id.trim();
if (id.isEmpty) {
print('Task ID cannot be empty.');
return;
}
stdout.write('Task title: ');
final title = stdin.readLineSync() ?? '';
if (title.isEmpty) {
print('Task title cannot be empty.');
return;
}
stdout.write('Short description (one line): ');
final description = stdin.readLineSync() ?? '';
stdout.write('Status (todo/in-progress/completed) [todo]: ');
final statusInput = stdin.readLineSync() ?? '';
final status = _validateStatus(statusInput.isEmpty ? 'todo' : statusInput);
if (status == null) {
print('Invalid status. Use: todo, in-progress, or completed');
return;
}
stdout.write('Related files (comma-separated, optional): ');
final filesInput = stdin.readLineSync() ?? '';
final files = filesInput.isEmpty
? <String>[]
: filesInput.split(',').map((f) => f.trim()).toList();
// Load all features (active + archive) to catch duplicate IDs
final features = ContextService.loadAllFeatures();
// Check for duplicate ID
if (features.any((f) => f.id == id)) {
print('Task with ID "$id" already exists.');
return;
}
// Create feature (tasks are managed as features)
final feature = Feature(
id: id,
title: title,
status: status,
description: description,
files: files,
);
// Add and save
features.add(feature);
ContextService.saveFeatures(features);
print('✔ Task "$title" added successfully (ID: $id)');
}