clavix 2.7.1 → 2.8.0

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 (165) hide show
  1. package/README.md +18 -4
  2. package/bin/clavix.js +12 -5
  3. package/dist/cli/commands/archive.d.ts +5 -4
  4. package/dist/cli/commands/archive.js +135 -161
  5. package/dist/cli/commands/config.d.ts +4 -4
  6. package/dist/cli/commands/config.js +66 -105
  7. package/dist/cli/commands/deep.d.ts +3 -3
  8. package/dist/cli/commands/deep.js +97 -103
  9. package/dist/cli/commands/execute.d.ts +4 -4
  10. package/dist/cli/commands/execute.js +57 -63
  11. package/dist/cli/commands/fast.d.ts +3 -3
  12. package/dist/cli/commands/fast.js +122 -128
  13. package/dist/cli/commands/implement.d.ts +4 -4
  14. package/dist/cli/commands/implement.js +84 -148
  15. package/dist/cli/commands/init.js +87 -126
  16. package/dist/cli/commands/list.d.ts +5 -5
  17. package/dist/cli/commands/list.js +72 -111
  18. package/dist/cli/commands/plan.d.ts +7 -7
  19. package/dist/cli/commands/plan.js +92 -131
  20. package/dist/cli/commands/prd.d.ts +4 -4
  21. package/dist/cli/commands/prd.js +76 -111
  22. package/dist/cli/commands/prompts/clear.d.ts +6 -6
  23. package/dist/cli/commands/prompts/clear.js +70 -76
  24. package/dist/cli/commands/prompts/list.js +37 -43
  25. package/dist/cli/commands/show.d.ts +4 -4
  26. package/dist/cli/commands/show.js +72 -111
  27. package/dist/cli/commands/start.d.ts +3 -3
  28. package/dist/cli/commands/start.js +63 -101
  29. package/dist/cli/commands/summarize.d.ts +4 -4
  30. package/dist/cli/commands/summarize.js +81 -120
  31. package/dist/cli/commands/task-complete.d.ts +4 -4
  32. package/dist/cli/commands/task-complete.js +86 -123
  33. package/dist/cli/commands/update.d.ts +3 -3
  34. package/dist/cli/commands/update.js +97 -130
  35. package/dist/cli/commands/version.js +13 -48
  36. package/dist/core/adapters/agents-md-generator.js +17 -50
  37. package/dist/core/adapters/amp-adapter.d.ts +1 -1
  38. package/dist/core/adapters/amp-adapter.js +13 -21
  39. package/dist/core/adapters/augment-adapter.d.ts +2 -2
  40. package/dist/core/adapters/augment-adapter.js +16 -56
  41. package/dist/core/adapters/base-adapter.d.ts +1 -1
  42. package/dist/core/adapters/base-adapter.js +11 -47
  43. package/dist/core/adapters/claude-code-adapter.d.ts +2 -2
  44. package/dist/core/adapters/claude-code-adapter.js +19 -60
  45. package/dist/core/adapters/cline-adapter.d.ts +1 -1
  46. package/dist/core/adapters/cline-adapter.js +13 -21
  47. package/dist/core/adapters/codebuddy-adapter.d.ts +2 -2
  48. package/dist/core/adapters/codebuddy-adapter.js +17 -57
  49. package/dist/core/adapters/codex-adapter.d.ts +2 -2
  50. package/dist/core/adapters/codex-adapter.js +16 -56
  51. package/dist/core/adapters/copilot-instructions-generator.js +18 -51
  52. package/dist/core/adapters/crush-adapter.d.ts +2 -2
  53. package/dist/core/adapters/crush-adapter.js +13 -20
  54. package/dist/core/adapters/cursor-adapter.d.ts +1 -1
  55. package/dist/core/adapters/cursor-adapter.js +12 -20
  56. package/dist/core/adapters/droid-adapter.d.ts +2 -2
  57. package/dist/core/adapters/droid-adapter.js +14 -21
  58. package/dist/core/adapters/gemini-adapter.d.ts +2 -2
  59. package/dist/core/adapters/gemini-adapter.js +16 -52
  60. package/dist/core/adapters/kilocode-adapter.d.ts +1 -1
  61. package/dist/core/adapters/kilocode-adapter.js +12 -20
  62. package/dist/core/adapters/octo-md-generator.js +17 -50
  63. package/dist/core/adapters/opencode-adapter.d.ts +2 -2
  64. package/dist/core/adapters/opencode-adapter.js +14 -21
  65. package/dist/core/adapters/qwen-adapter.d.ts +2 -2
  66. package/dist/core/adapters/qwen-adapter.js +16 -52
  67. package/dist/core/adapters/roocode-adapter.d.ts +2 -2
  68. package/dist/core/adapters/roocode-adapter.js +12 -19
  69. package/dist/core/adapters/warp-md-generator.js +17 -50
  70. package/dist/core/adapters/windsurf-adapter.d.ts +1 -1
  71. package/dist/core/adapters/windsurf-adapter.js +12 -20
  72. package/dist/core/agent-manager.d.ts +1 -1
  73. package/dist/core/agent-manager.js +34 -38
  74. package/dist/core/archive-manager.js +10 -46
  75. package/dist/core/config-manager.d.ts +2 -2
  76. package/dist/core/config-manager.js +3 -40
  77. package/dist/core/conversation-analyzer.d.ts +1 -1
  78. package/dist/core/conversation-analyzer.js +1 -5
  79. package/dist/core/doc-injector.js +23 -60
  80. package/dist/core/git-manager.js +11 -48
  81. package/dist/core/prd-generator.js +16 -51
  82. package/dist/core/prompt-manager.js +6 -42
  83. package/dist/core/prompt-optimizer.js +1 -5
  84. package/dist/core/question-engine.js +6 -45
  85. package/dist/core/session-manager.d.ts +1 -1
  86. package/dist/core/session-manager.js +11 -49
  87. package/dist/core/task-manager.d.ts +26 -0
  88. package/dist/core/task-manager.js +243 -101
  89. package/dist/index.d.ts +2 -1
  90. package/dist/index.js +8 -12
  91. package/dist/templates/agents/agents.md +31 -2
  92. package/dist/templates/agents/copilot-instructions.md +1 -1
  93. package/dist/templates/agents/octo.md +20 -1
  94. package/dist/templates/agents/warp.md +1 -1
  95. package/dist/templates/slash-commands/_canonical/implement.md +33 -11
  96. package/dist/types/agent.js +1 -2
  97. package/dist/types/config.js +3 -8
  98. package/dist/types/errors.js +7 -13
  99. package/dist/types/session.js +1 -2
  100. package/dist/utils/agent-error-messages.js +1 -5
  101. package/dist/utils/error-utils.js +5 -12
  102. package/dist/utils/file-system.js +20 -57
  103. package/dist/utils/legacy-command-cleanup.d.ts +1 -1
  104. package/dist/utils/legacy-command-cleanup.js +9 -45
  105. package/dist/utils/template-loader.d.ts +1 -1
  106. package/dist/utils/template-loader.js +9 -41
  107. package/dist/utils/toml-templates.js +1 -4
  108. package/package.json +9 -4
  109. package/dist/core/adapters 2/agents-md-generator.d.ts +0 -26
  110. package/dist/core/adapters 2/agents-md-generator.js +0 -102
  111. package/dist/core/adapters 2/amp-adapter.d.ts +0 -27
  112. package/dist/core/adapters 2/amp-adapter.js +0 -42
  113. package/dist/core/adapters 2/augment-adapter.d.ts +0 -22
  114. package/dist/core/adapters 2/augment-adapter.js +0 -77
  115. package/dist/core/adapters 2/base-adapter.d.ts +0 -45
  116. package/dist/core/adapters 2/base-adapter.js +0 -142
  117. package/dist/core/adapters 2/claude-code-adapter.d.ts +0 -32
  118. package/dist/core/adapters 2/claude-code-adapter.js +0 -116
  119. package/dist/core/adapters 2/cline-adapter.d.ts +0 -34
  120. package/dist/core/adapters 2/cline-adapter.js +0 -52
  121. package/dist/core/adapters 2/codebuddy-adapter.d.ts +0 -24
  122. package/dist/core/adapters 2/codebuddy-adapter.js +0 -82
  123. package/dist/core/adapters 2/codex-adapter.d.ts +0 -24
  124. package/dist/core/adapters 2/codex-adapter.js +0 -79
  125. package/dist/core/adapters 2/copilot-instructions-generator.d.ts +0 -26
  126. package/dist/core/adapters 2/copilot-instructions-generator.js +0 -104
  127. package/dist/core/adapters 2/crush-adapter.d.ts +0 -35
  128. package/dist/core/adapters 2/crush-adapter.js +0 -49
  129. package/dist/core/adapters 2/cursor-adapter.d.ts +0 -25
  130. package/dist/core/adapters 2/cursor-adapter.js +0 -40
  131. package/dist/core/adapters 2/droid-adapter.d.ts +0 -33
  132. package/dist/core/adapters 2/droid-adapter.js +0 -57
  133. package/dist/core/adapters 2/gemini-adapter.d.ts +0 -27
  134. package/dist/core/adapters 2/gemini-adapter.js +0 -90
  135. package/dist/core/adapters 2/kilocode-adapter.d.ts +0 -34
  136. package/dist/core/adapters 2/kilocode-adapter.js +0 -49
  137. package/dist/core/adapters 2/octo-md-generator.d.ts +0 -26
  138. package/dist/core/adapters 2/octo-md-generator.js +0 -102
  139. package/dist/core/adapters 2/opencode-adapter.d.ts +0 -33
  140. package/dist/core/adapters 2/opencode-adapter.js +0 -56
  141. package/dist/core/adapters 2/qwen-adapter.d.ts +0 -27
  142. package/dist/core/adapters 2/qwen-adapter.js +0 -90
  143. package/dist/core/adapters 2/roocode-adapter.d.ts +0 -40
  144. package/dist/core/adapters 2/roocode-adapter.js +0 -68
  145. package/dist/core/adapters 2/warp-md-generator.d.ts +0 -17
  146. package/dist/core/adapters 2/warp-md-generator.js +0 -88
  147. package/dist/core/adapters 2/windsurf-adapter.d.ts +0 -34
  148. package/dist/core/adapters 2/windsurf-adapter.js +0 -49
  149. package/dist/core/agent-manager 2.js +0 -126
  150. package/dist/core/agent-manager.d 2.ts +0 -51
  151. package/dist/core/archive-manager 2.js +0 -338
  152. package/dist/core/archive-manager.d 2.ts +0 -100
  153. package/dist/core/conversation-analyzer.d 2.ts +0 -86
  154. package/dist/core/doc-injector 2.js +0 -236
  155. package/dist/core/doc-injector.d 2.ts +0 -51
  156. package/dist/core/git-manager 2.js +0 -214
  157. package/dist/core/git-manager.d 2.ts +0 -100
  158. package/dist/core/prompt-optimizer 2.js +0 -963
  159. package/dist/core/prompt-optimizer.d 2.ts +0 -268
  160. package/dist/core/question-engine 2.js +0 -395
  161. package/dist/core/question-engine.d 2.ts +0 -167
  162. package/dist/core/session-manager 2.js +0 -403
  163. package/dist/core/session-manager.d 2.ts +0 -139
  164. package/dist/core/task-manager 2.js +0 -689
  165. package/dist/core/task-manager.d 2.ts +0 -155
@@ -1,49 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WindsurfAdapter = void 0;
4
- const base_adapter_1 = require("./base-adapter");
5
- const file_system_1 = require("../../utils/file-system");
6
- /**
7
- * Windsurf adapter
8
- * Workflows stored in .windsurf/workflows/ (supports subdirectories)
9
- * Slash command format: /[name] (no .md extension)
10
- *
11
- * Features:
12
- * - Supports subdirectories for workflow organization
13
- * - 12,000 character limit per workflow file
14
- * - Auto-discovers from workspace, subdirectories, and parent dirs up to git root
15
- *
16
- * Reference: https://docs.windsurf.com/windsurf/cascade/workflows
17
- */
18
- class WindsurfAdapter extends base_adapter_1.BaseAdapter {
19
- constructor() {
20
- super(...arguments);
21
- this.name = 'windsurf';
22
- this.displayName = 'Windsurf';
23
- this.directory = '.windsurf/workflows';
24
- this.fileExtension = '.md';
25
- this.features = {
26
- supportsSubdirectories: true,
27
- supportsFrontmatter: false,
28
- };
29
- // Uses default formatCommand and generateCommands from BaseAdapter
30
- }
31
- /**
32
- * Detect if Windsurf is available in the project
33
- * Checks for .windsurf directory
34
- */
35
- async detectProject() {
36
- return await file_system_1.FileSystem.exists('.windsurf');
37
- }
38
- /**
39
- * Get command path for Windsurf
40
- */
41
- getCommandPath() {
42
- return this.directory;
43
- }
44
- getTargetFilename(name) {
45
- return `clavix-${name}${this.fileExtension}`;
46
- }
47
- }
48
- exports.WindsurfAdapter = WindsurfAdapter;
49
- //# sourceMappingURL=windsurf-adapter.js.map
@@ -1,126 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AgentManager = void 0;
4
- const claude_code_adapter_1 = require("./adapters/claude-code-adapter");
5
- const cursor_adapter_1 = require("./adapters/cursor-adapter");
6
- const droid_adapter_1 = require("./adapters/droid-adapter");
7
- const opencode_adapter_1 = require("./adapters/opencode-adapter");
8
- const amp_adapter_1 = require("./adapters/amp-adapter");
9
- const crush_adapter_1 = require("./adapters/crush-adapter");
10
- const windsurf_adapter_1 = require("./adapters/windsurf-adapter");
11
- const kilocode_adapter_1 = require("./adapters/kilocode-adapter");
12
- const cline_adapter_1 = require("./adapters/cline-adapter");
13
- const roocode_adapter_1 = require("./adapters/roocode-adapter");
14
- const errors_1 = require("../types/errors");
15
- const codebuddy_adapter_1 = require("./adapters/codebuddy-adapter");
16
- const gemini_adapter_1 = require("./adapters/gemini-adapter");
17
- const qwen_adapter_1 = require("./adapters/qwen-adapter");
18
- const codex_adapter_1 = require("./adapters/codex-adapter");
19
- const augment_adapter_1 = require("./adapters/augment-adapter");
20
- /**
21
- * Agent Manager - handles agent detection and registration
22
- */
23
- class AgentManager {
24
- constructor() {
25
- this.adapters = new Map();
26
- // Register all built-in adapters
27
- this.registerAdapter(new claude_code_adapter_1.ClaudeCodeAdapter());
28
- this.registerAdapter(new cursor_adapter_1.CursorAdapter());
29
- this.registerAdapter(new droid_adapter_1.DroidAdapter());
30
- this.registerAdapter(new opencode_adapter_1.OpenCodeAdapter());
31
- this.registerAdapter(new amp_adapter_1.AmpAdapter());
32
- this.registerAdapter(new crush_adapter_1.CrushAdapter());
33
- this.registerAdapter(new windsurf_adapter_1.WindsurfAdapter());
34
- this.registerAdapter(new kilocode_adapter_1.KilocodeAdapter());
35
- this.registerAdapter(new cline_adapter_1.ClineAdapter());
36
- this.registerAdapter(new roocode_adapter_1.RoocodeAdapter());
37
- this.registerAdapter(new augment_adapter_1.AugmentAdapter());
38
- this.registerAdapter(new codebuddy_adapter_1.CodeBuddyAdapter());
39
- this.registerAdapter(new gemini_adapter_1.GeminiAdapter());
40
- this.registerAdapter(new qwen_adapter_1.QwenAdapter());
41
- this.registerAdapter(new codex_adapter_1.CodexAdapter());
42
- }
43
- /**
44
- * Register a new agent adapter
45
- */
46
- registerAdapter(adapter) {
47
- this.adapters.set(adapter.name, adapter);
48
- }
49
- /**
50
- * Get all registered adapters
51
- */
52
- getAdapters() {
53
- return Array.from(this.adapters.values());
54
- }
55
- /**
56
- * Get adapter by name
57
- */
58
- getAdapter(name) {
59
- return this.adapters.get(name);
60
- }
61
- /**
62
- * Detect which agents are available in the current project
63
- */
64
- async detectAgents() {
65
- const detected = [];
66
- for (const adapter of this.adapters.values()) {
67
- if (await adapter.detectProject()) {
68
- detected.push(adapter);
69
- }
70
- }
71
- return detected;
72
- }
73
- /**
74
- * Get agent adapter by name or throw error
75
- */
76
- requireAdapter(name) {
77
- const adapter = this.getAdapter(name);
78
- if (!adapter) {
79
- throw new errors_1.IntegrationError(`Agent "${name}" is not registered`, `Available agents: ${Array.from(this.adapters.keys()).join(', ')}`);
80
- }
81
- return adapter;
82
- }
83
- /**
84
- * Check if an agent is available
85
- */
86
- hasAgent(name) {
87
- return this.adapters.has(name);
88
- }
89
- /**
90
- * Get list of available agent names
91
- */
92
- getAvailableAgents() {
93
- return Array.from(this.adapters.keys());
94
- }
95
- /**
96
- * Validate multiple adapters
97
- * Returns map of adapter name to validation result
98
- */
99
- async validateAdapters(adapterNames) {
100
- const results = new Map();
101
- for (const name of adapterNames) {
102
- const adapter = this.requireAdapter(name);
103
- if (adapter.validate) {
104
- results.set(name, await adapter.validate());
105
- }
106
- else {
107
- // No validation method - assume valid
108
- results.set(name, { valid: true });
109
- }
110
- }
111
- return results;
112
- }
113
- /**
114
- * Get adapter choices for inquirer checkbox prompt
115
- * Returns array of choices with pre-selected defaults
116
- */
117
- getAdapterChoices() {
118
- return Array.from(this.adapters.values()).map((adapter) => ({
119
- name: `${adapter.displayName} (${adapter.directory})`,
120
- value: adapter.name,
121
- checked: adapter.name === 'claude-code', // Pre-select Claude Code by default
122
- }));
123
- }
124
- }
125
- exports.AgentManager = AgentManager;
126
- //# sourceMappingURL=agent-manager.js.map
@@ -1,51 +0,0 @@
1
- import { AgentAdapter, ValidationResult } from '../types/agent';
2
- /**
3
- * Agent Manager - handles agent detection and registration
4
- */
5
- export declare class AgentManager {
6
- private adapters;
7
- constructor();
8
- /**
9
- * Register a new agent adapter
10
- */
11
- registerAdapter(adapter: AgentAdapter): void;
12
- /**
13
- * Get all registered adapters
14
- */
15
- getAdapters(): AgentAdapter[];
16
- /**
17
- * Get adapter by name
18
- */
19
- getAdapter(name: string): AgentAdapter | undefined;
20
- /**
21
- * Detect which agents are available in the current project
22
- */
23
- detectAgents(): Promise<AgentAdapter[]>;
24
- /**
25
- * Get agent adapter by name or throw error
26
- */
27
- requireAdapter(name: string): AgentAdapter;
28
- /**
29
- * Check if an agent is available
30
- */
31
- hasAgent(name: string): boolean;
32
- /**
33
- * Get list of available agent names
34
- */
35
- getAvailableAgents(): string[];
36
- /**
37
- * Validate multiple adapters
38
- * Returns map of adapter name to validation result
39
- */
40
- validateAdapters(adapterNames: string[]): Promise<Map<string, ValidationResult>>;
41
- /**
42
- * Get adapter choices for inquirer checkbox prompt
43
- * Returns array of choices with pre-selected defaults
44
- */
45
- getAdapterChoices(): Array<{
46
- name: string;
47
- value: string;
48
- checked?: boolean;
49
- }>;
50
- }
51
- //# sourceMappingURL=agent-manager.d.ts.map
@@ -1,338 +0,0 @@
1
- "use strict";
2
- /**
3
- * ArchiveManager - Manages archival of completed PRD projects
4
- *
5
- * This class handles:
6
- * - Listing active and archived PRD projects
7
- * - Checking task completion status
8
- * - Moving completed projects to archive
9
- * - Managing archive directory structure
10
- */
11
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
- if (k2 === undefined) k2 = k;
13
- var desc = Object.getOwnPropertyDescriptor(m, k);
14
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
- desc = { enumerable: true, get: function() { return m[k]; } };
16
- }
17
- Object.defineProperty(o, k2, desc);
18
- }) : (function(o, m, k, k2) {
19
- if (k2 === undefined) k2 = k;
20
- o[k2] = m[k];
21
- }));
22
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
- Object.defineProperty(o, "default", { enumerable: true, value: v });
24
- }) : function(o, v) {
25
- o["default"] = v;
26
- });
27
- var __importStar = (this && this.__importStar) || (function () {
28
- var ownKeys = function(o) {
29
- ownKeys = Object.getOwnPropertyNames || function (o) {
30
- var ar = [];
31
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
- return ar;
33
- };
34
- return ownKeys(o);
35
- };
36
- return function (mod) {
37
- if (mod && mod.__esModule) return mod;
38
- var result = {};
39
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
- __setModuleDefault(result, mod);
41
- return result;
42
- };
43
- })();
44
- Object.defineProperty(exports, "__esModule", { value: true });
45
- exports.ArchiveManager = void 0;
46
- const fs = __importStar(require("fs-extra"));
47
- const path = __importStar(require("path"));
48
- const task_manager_1 = require("./task-manager");
49
- /**
50
- * ArchiveManager class
51
- *
52
- * Manages archival of completed PRD projects
53
- */
54
- class ArchiveManager {
55
- constructor() {
56
- this.outputsDir = '.clavix/outputs';
57
- this.archiveDir = '.clavix/outputs/archive';
58
- this.taskManager = new task_manager_1.TaskManager();
59
- }
60
- /**
61
- * List all PRD projects in outputs directory
62
- *
63
- * @param includeArchived - Include archived projects in results
64
- * @returns Array of PRD projects
65
- */
66
- async listPrdProjects(includeArchived = false) {
67
- const projects = [];
68
- // Check if outputs directory exists
69
- if (!(await fs.pathExists(this.outputsDir))) {
70
- return projects;
71
- }
72
- const dirs = await fs.readdir(this.outputsDir);
73
- for (const dir of dirs) {
74
- // Skip archive directory when listing active projects
75
- if (dir === 'archive' && !includeArchived) {
76
- continue;
77
- }
78
- const fullPath = path.join(this.outputsDir, dir);
79
- const stat = await fs.stat(fullPath);
80
- if (stat.isDirectory()) {
81
- // Check if it has a PRD file
82
- if (await this.hasPrdFile(fullPath)) {
83
- const taskStatus = await this.checkTasksStatus(fullPath);
84
- projects.push({
85
- name: dir,
86
- path: fullPath,
87
- taskStatus,
88
- modifiedTime: stat.mtime,
89
- isArchived: false,
90
- });
91
- }
92
- }
93
- }
94
- // Add archived projects if requested
95
- if (includeArchived) {
96
- const archivedProjects = await this.listArchivedProjects();
97
- projects.push(...archivedProjects);
98
- }
99
- // Sort by modification time (most recent first)
100
- projects.sort((a, b) => b.modifiedTime.getTime() - a.modifiedTime.getTime());
101
- return projects;
102
- }
103
- /**
104
- * List archived PRD projects
105
- *
106
- * @returns Array of archived PRD projects
107
- */
108
- async listArchivedProjects() {
109
- const projects = [];
110
- if (!(await fs.pathExists(this.archiveDir))) {
111
- return projects;
112
- }
113
- const dirs = await fs.readdir(this.archiveDir);
114
- for (const dir of dirs) {
115
- const fullPath = path.join(this.archiveDir, dir);
116
- const stat = await fs.stat(fullPath);
117
- if (stat.isDirectory()) {
118
- if (await this.hasPrdFile(fullPath)) {
119
- const taskStatus = await this.checkTasksStatus(fullPath);
120
- projects.push({
121
- name: dir,
122
- path: fullPath,
123
- taskStatus,
124
- modifiedTime: stat.mtime,
125
- isArchived: true,
126
- });
127
- }
128
- }
129
- }
130
- return projects;
131
- }
132
- /**
133
- * Get PRD projects that are ready to archive (all tasks completed)
134
- *
135
- * @returns Array of archivable PRD projects
136
- */
137
- async getArchivablePrds() {
138
- const allProjects = await this.listPrdProjects(false);
139
- // Filter to only projects with all tasks completed
140
- return allProjects.filter((project) => project.taskStatus.hasTasksFile && project.taskStatus.allCompleted);
141
- }
142
- /**
143
- * Check task completion status for a PRD project
144
- *
145
- * @param projectPath - Path to the PRD project directory
146
- * @returns Task status information
147
- */
148
- async checkTasksStatus(projectPath) {
149
- const tasksPath = path.join(projectPath, 'tasks.md');
150
- // Check if tasks.md exists
151
- if (!(await fs.pathExists(tasksPath))) {
152
- return {
153
- hasTasksFile: false,
154
- total: 0,
155
- completed: 0,
156
- remaining: 0,
157
- percentage: 0,
158
- allCompleted: false,
159
- };
160
- }
161
- try {
162
- // Read and parse tasks
163
- const phases = await this.taskManager.readTasksFile(tasksPath);
164
- const stats = this.taskManager.getTaskStats(phases);
165
- return {
166
- hasTasksFile: true,
167
- total: stats.total,
168
- completed: stats.completed,
169
- remaining: stats.remaining,
170
- percentage: stats.percentage,
171
- allCompleted: stats.remaining === 0 && stats.total > 0,
172
- };
173
- }
174
- catch {
175
- // If parsing fails, return error status
176
- return {
177
- hasTasksFile: true,
178
- total: 0,
179
- completed: 0,
180
- remaining: 0,
181
- percentage: 0,
182
- allCompleted: false,
183
- };
184
- }
185
- }
186
- /**
187
- * Archive a PRD project (move to archive directory)
188
- *
189
- * @param projectName - Name of the project to archive
190
- * @param force - Force archive even if tasks are incomplete
191
- * @returns Success status and message
192
- */
193
- async archiveProject(projectName, force = false) {
194
- const sourcePath = path.join(this.outputsDir, projectName);
195
- // Check if project exists
196
- if (!(await fs.pathExists(sourcePath))) {
197
- return {
198
- success: false,
199
- message: `Project not found: ${projectName}`,
200
- };
201
- }
202
- // Check if it's already in archive
203
- if (sourcePath.includes('/archive/')) {
204
- return {
205
- success: false,
206
- message: `Project is already archived: ${projectName}`,
207
- };
208
- }
209
- // Check task status unless forced
210
- if (!force) {
211
- const taskStatus = await this.checkTasksStatus(sourcePath);
212
- if (!taskStatus.hasTasksFile) {
213
- return {
214
- success: false,
215
- message: `Project has no tasks.md file. Use --force to archive anyway.`,
216
- };
217
- }
218
- if (!taskStatus.allCompleted) {
219
- return {
220
- success: false,
221
- message: `Project has ${taskStatus.remaining} incomplete task(s). Use --force to archive anyway.`,
222
- };
223
- }
224
- }
225
- // Ensure archive directory exists
226
- await fs.ensureDir(this.archiveDir);
227
- // Move project to archive
228
- const destPath = path.join(this.archiveDir, projectName);
229
- // Check if destination already exists
230
- if (await fs.pathExists(destPath)) {
231
- return {
232
- success: false,
233
- message: `Archive already contains a project named: ${projectName}`,
234
- };
235
- }
236
- try {
237
- await fs.move(sourcePath, destPath);
238
- return {
239
- success: true,
240
- message: `Successfully archived ${projectName} to ${destPath}`,
241
- };
242
- }
243
- catch (error) {
244
- const { getErrorMessage } = await Promise.resolve().then(() => __importStar(require('../utils/error-utils.js')));
245
- return {
246
- success: false,
247
- message: `Failed to archive project: ${getErrorMessage(error)}`,
248
- };
249
- }
250
- }
251
- /**
252
- * Restore an archived project back to active outputs
253
- *
254
- * @param projectName - Name of the archived project to restore
255
- * @returns Success status and message
256
- */
257
- async restoreProject(projectName) {
258
- const sourcePath = path.join(this.archiveDir, projectName);
259
- // Check if archived project exists
260
- if (!(await fs.pathExists(sourcePath))) {
261
- return {
262
- success: false,
263
- message: `Archived project not found: ${projectName}`,
264
- };
265
- }
266
- const destPath = path.join(this.outputsDir, projectName);
267
- // Check if destination already exists
268
- if (await fs.pathExists(destPath)) {
269
- return {
270
- success: false,
271
- message: `Active outputs already contains a project named: ${projectName}`,
272
- };
273
- }
274
- try {
275
- await fs.move(sourcePath, destPath);
276
- return {
277
- success: true,
278
- message: `Successfully restored ${projectName} to ${destPath}`,
279
- };
280
- }
281
- catch (error) {
282
- const { getErrorMessage } = await Promise.resolve().then(() => __importStar(require('../utils/error-utils.js')));
283
- return {
284
- success: false,
285
- message: `Failed to restore project: ${getErrorMessage(error)}`,
286
- };
287
- }
288
- }
289
- /**
290
- * Check if a directory contains a PRD file
291
- */
292
- async hasPrdFile(dirPath) {
293
- const possibleFiles = [
294
- 'PRD.md',
295
- 'full-prd.md',
296
- 'prd.md',
297
- 'Full-PRD.md',
298
- 'FULL_PRD.md',
299
- 'FULL-PRD.md',
300
- 'QUICK_PRD.md',
301
- ];
302
- for (const filename of possibleFiles) {
303
- if (await fs.pathExists(path.join(dirPath, filename))) {
304
- return true;
305
- }
306
- }
307
- return false;
308
- }
309
- /**
310
- * Get incomplete tasks for a project (for display purposes)
311
- *
312
- * @param projectPath - Path to the PRD project
313
- * @returns Array of incomplete task descriptions
314
- */
315
- async getIncompleteTasks(projectPath) {
316
- const tasksPath = path.join(projectPath, 'tasks.md');
317
- if (!(await fs.pathExists(tasksPath))) {
318
- return [];
319
- }
320
- try {
321
- const phases = await this.taskManager.readTasksFile(tasksPath);
322
- const incompleteTasks = [];
323
- for (const phase of phases) {
324
- for (const task of phase.tasks) {
325
- if (!task.completed) {
326
- incompleteTasks.push(`[${phase.name}] ${task.description}`);
327
- }
328
- }
329
- }
330
- return incompleteTasks;
331
- }
332
- catch {
333
- return [];
334
- }
335
- }
336
- }
337
- exports.ArchiveManager = ArchiveManager;
338
- //# sourceMappingURL=archive-manager.js.map
@@ -1,100 +0,0 @@
1
- /**
2
- * ArchiveManager - Manages archival of completed PRD projects
3
- *
4
- * This class handles:
5
- * - Listing active and archived PRD projects
6
- * - Checking task completion status
7
- * - Moving completed projects to archive
8
- * - Managing archive directory structure
9
- */
10
- /**
11
- * Status of a PRD project's tasks
12
- */
13
- export interface TaskStatus {
14
- hasTasksFile: boolean;
15
- total: number;
16
- completed: number;
17
- remaining: number;
18
- percentage: number;
19
- allCompleted: boolean;
20
- }
21
- /**
22
- * Information about a PRD project
23
- */
24
- export interface PrdProject {
25
- name: string;
26
- path: string;
27
- taskStatus: TaskStatus;
28
- modifiedTime: Date;
29
- isArchived: boolean;
30
- }
31
- /**
32
- * ArchiveManager class
33
- *
34
- * Manages archival of completed PRD projects
35
- */
36
- export declare class ArchiveManager {
37
- private readonly taskManager;
38
- private readonly outputsDir;
39
- private readonly archiveDir;
40
- constructor();
41
- /**
42
- * List all PRD projects in outputs directory
43
- *
44
- * @param includeArchived - Include archived projects in results
45
- * @returns Array of PRD projects
46
- */
47
- listPrdProjects(includeArchived?: boolean): Promise<PrdProject[]>;
48
- /**
49
- * List archived PRD projects
50
- *
51
- * @returns Array of archived PRD projects
52
- */
53
- listArchivedProjects(): Promise<PrdProject[]>;
54
- /**
55
- * Get PRD projects that are ready to archive (all tasks completed)
56
- *
57
- * @returns Array of archivable PRD projects
58
- */
59
- getArchivablePrds(): Promise<PrdProject[]>;
60
- /**
61
- * Check task completion status for a PRD project
62
- *
63
- * @param projectPath - Path to the PRD project directory
64
- * @returns Task status information
65
- */
66
- checkTasksStatus(projectPath: string): Promise<TaskStatus>;
67
- /**
68
- * Archive a PRD project (move to archive directory)
69
- *
70
- * @param projectName - Name of the project to archive
71
- * @param force - Force archive even if tasks are incomplete
72
- * @returns Success status and message
73
- */
74
- archiveProject(projectName: string, force?: boolean): Promise<{
75
- success: boolean;
76
- message: string;
77
- }>;
78
- /**
79
- * Restore an archived project back to active outputs
80
- *
81
- * @param projectName - Name of the archived project to restore
82
- * @returns Success status and message
83
- */
84
- restoreProject(projectName: string): Promise<{
85
- success: boolean;
86
- message: string;
87
- }>;
88
- /**
89
- * Check if a directory contains a PRD file
90
- */
91
- private hasPrdFile;
92
- /**
93
- * Get incomplete tasks for a project (for display purposes)
94
- *
95
- * @param projectPath - Path to the PRD project
96
- * @returns Array of incomplete task descriptions
97
- */
98
- getIncompleteTasks(projectPath: string): Promise<string[]>;
99
- }
100
- //# sourceMappingURL=archive-manager.d.ts.map