feat(tags): Implement tagged task lists migration system (Part 1/2)

This commit introduces the foundational infrastructure for tagged task lists,
enabling multi-context task management without remote storage to prevent merge conflicts.

CORE ARCHITECTURE:
• Silent migration system transforms tasks.json from old format { "tasks": [...] }
  to new tagged format { "master": { "tasks": [...] } }
• Tag resolution layer provides complete backward compatibility - existing code continues to work
• Automatic configuration and state management for seamless user experience

SILENT MIGRATION SYSTEM:
• Automatic detection and migration of legacy tasks.json format
• Complete project migration: tasks.json + config.json + state.json
• Transparent tag resolution returns old format to maintain compatibility
• Zero breaking changes - all existing functionality preserved

CONFIGURATION MANAGEMENT:
• Added global.defaultTag setting (defaults to 'master')
• New tags section with gitIntegration placeholders for future features
• Automatic config.json migration during first run
• Proper state.json creation with migration tracking

USER EXPERIENCE:
• Clean, one-time FYI notice after migration (no emojis, professional styling)
• Notice appears after 'Suggested Next Steps' and is tracked in state.json
• Silent operation - users unaware migration occurred unless explicitly shown

TECHNICAL IMPLEMENTATION:
• Enhanced readJSON() with automatic migration detection and processing
• New utility functions: getCurrentTag(), resolveTag(), getTasksForTag(), setTasksForTag()
• Complete migration orchestration via performCompleteTagMigration()
• Robust error handling and fallback mechanisms

BACKWARD COMPATIBILITY:
• 100% backward compatibility maintained
• Existing CLI commands and MCP tools continue to work unchanged
• Legacy tasks.json format automatically upgraded on first read
• All existing workflows preserved

TESTING VERIFIED:
• Complete migration from legacy state works correctly
• Config.json properly updated with tagged system settings
• State.json created with correct initial values
• Migration notice system functions as designed
• All existing functionality continues to work normally

Part 2 will implement tag management commands (add-tag, use-tag, list-tags)
and MCP tool updates for full tagged task system functionality.

Related: Task 103 - Implement Tagged Task Lists System for Multi-Context Task Management
This commit is contained in:
Eyal Toledano
2025-06-11 16:36:48 -04:00
parent f3fe481f3f
commit 2328efe482
10 changed files with 7201 additions and 6724 deletions

View File

@@ -13,7 +13,7 @@ import http from 'http';
import inquirer from 'inquirer';
import ora from 'ora'; // Import ora
import { log, readJSON, findProjectRoot } from './utils.js';
import { log, readJSON, writeJSON, findProjectRoot } from './utils.js';
import {
parsePRD,
updateTasks,
@@ -74,7 +74,8 @@ import {
displayAvailableModels,
displayApiKeyStatus,
displayAiUsageSummary,
displayMultipleTasksSummary
displayMultipleTasksSummary,
displayTaggedTasksFYI
} from './ui.js';
import { initializeProject } from '../init.js';
@@ -3266,6 +3267,42 @@ async function runCLI(argv = process.argv) {
updateInfo.latestVersion
);
}
// Check if migration has occurred and show FYI notice once
try {
const projectRoot = findProjectRoot() || '.';
const tasksPath = path.join(
projectRoot,
'.taskmaster',
'tasks',
'tasks.json'
);
const statePath = path.join(projectRoot, '.taskmaster', 'state.json');
if (fs.existsSync(tasksPath)) {
// Read raw file to check if it has master key (bypassing tag resolution)
const rawData = fs.readFileSync(tasksPath, 'utf8');
const parsedData = JSON.parse(rawData);
if (parsedData && parsedData.master) {
// Migration has occurred, check if we've shown the notice
let stateData = { migrationNoticeShown: false };
if (fs.existsSync(statePath)) {
stateData = readJSON(statePath) || stateData;
}
if (!stateData.migrationNoticeShown) {
displayTaggedTasksFYI({ _migrationHappened: true });
// Mark as shown
stateData.migrationNoticeShown = true;
writeJSON(statePath, stateData);
}
}
}
} catch (error) {
// Silently ignore errors checking for migration notice
}
} catch (error) {
// ** Specific catch block for missing configuration file **
if (error instanceof ConfigurationError) {