clavix 2.7.0 → 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 +22 -8
  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 +12 -7
  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
package/README.md CHANGED
@@ -26,6 +26,8 @@ Provider paths and argument placeholders are listed in [docs/providers.md](docs/
26
26
 
27
27
  ## Quickstart
28
28
 
29
+ > **⚠️ v2.8.0 Breaking Change**: Clavix is now a pure ESM package. Requires **Node.js ≥ 16.0.0**. See [CHANGELOG.md](CHANGELOG.md#280---2025-11-17) for migration details.
30
+
29
31
  ### For AI Agents (Recommended)
30
32
 
31
33
  Most Clavix users work through AI coding assistants:
@@ -94,21 +96,33 @@ clavix prd
94
96
  - CLEAR Framework: [docs/clear-framework.md](docs/clear-framework.md)
95
97
  - Guides: [docs/guides/](docs/guides/workflows.md)
96
98
 
97
- ## Development
98
- - Requires Node.js ≥ 18
99
- - Run tests: `npm test`
99
+ ## Requirements
100
+
101
+ ### For End Users
102
+ - **Node.js ≥ 16.0.0** (required for ESM support)
103
+ - npm or yarn package manager
104
+
105
+ ### For Contributors
106
+ - **Node.js ≥ 16.0.0** (pure ESM package since v2.8.0)
107
+ - Run tests: `npm test` (uses `--experimental-vm-modules` for Jest with ESM)
100
108
  - Lint: `npm run lint`
101
- - Build: `npm run build`
109
+ - Build: `npm run build` (TypeScript ES2020 modules)
110
+
111
+ **ESM Migration (v2.8.0+):**
112
+ - All source code uses ES modules (`import`/`export`)
113
+ - TypeScript configured with `NodeNext` module resolution
114
+ - All imports require `.js` file extensions
115
+ - See [ESM_MIGRATION_NOTES.md](ESM_MIGRATION_NOTES.md) for details
102
116
 
103
117
  ## License
104
118
  MIT
105
119
 
106
120
  ## Star History
107
121
 
108
- <a href="https://www.star-history.com/#Bob5k/Clavix&type=date&legend=top-left">
122
+ <a href="https://www.star-history.com/#ClavixDev/Clavix&type=date&legend=top-left">
109
123
  <picture>
110
- <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=Bob5k/Clavix&type=date&theme=dark&legend=top-left" />
111
- <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=Bob5k/Clavix&type=date&legend=top-left" />
112
- <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=Bob5k/Clavix&type=date&legend=top-left" />
124
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=ClavixDev/Clavix&type=date&theme=dark&legend=top-left" />
125
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=ClavixDev/Clavix&type=date&legend=top-left" />
126
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=ClavixDev/Clavix&type=date&legend=top-left" />
113
127
  </picture>
114
128
  </a>
package/bin/clavix.js CHANGED
@@ -1,8 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // Disable debug mode (stack traces) unless explicitly requested via DEBUG env var
3
+ import { run, handle, settings } from '@oclif/core';
4
+ import { fileURLToPath } from 'url';
5
+ import { dirname, join } from 'path';
6
+
7
+ // Get the project root (one level up from bin/)
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ const projectRoot = join(__dirname, '..');
11
+
12
+ // Disable debug mode unless explicitly requested
4
13
  if (!process.env.DEBUG) {
5
- require('@oclif/core').settings.debug = false;
14
+ settings.debug = false;
6
15
  }
7
16
 
8
17
  // Custom error handler to suppress stack traces
@@ -15,10 +24,8 @@ async function handleError(error) {
15
24
  }
16
25
 
17
26
  // For other errors, use default handler
18
- const { handle } = require('@oclif/core');
19
27
  return handle(error);
20
28
  }
21
29
 
22
- require('../dist/index.js')
23
- .run()
30
+ run(undefined, projectRoot)
24
31
  .catch(handleError);
@@ -3,12 +3,13 @@ export default class Archive extends Command {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static args: {
6
- project: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
6
+ project: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
7
  };
8
8
  static flags: {
9
- list: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
- force: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
- restore: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ list: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ restore: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
13
  };
13
14
  run(): Promise<void>;
14
15
  /**
@@ -1,53 +1,50 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
1
+ import { Command, Flags, Args } from '@oclif/core';
2
+ import chalk from 'chalk';
3
+ import inquirer from 'inquirer';
4
+ import { ArchiveManager } from '../../core/archive-manager.js';
5
+ export default class Archive extends Command {
6
+ static description = 'Archive completed PRD projects';
7
+ static examples = [
8
+ '<%= config.bin %> <%= command.id %> # Interactive selection',
9
+ '<%= config.bin %> <%= command.id %> my-project # Archive specific project',
10
+ '<%= config.bin %> <%= command.id %> --list # List archived projects',
11
+ '<%= config.bin %> <%= command.id %> my-project --force # Force archive',
12
+ '<%= config.bin %> <%= command.id %> --restore my-project # Restore from archive',
13
+ ];
14
+ static args = {
15
+ project: Args.string({
16
+ description: 'Name of the project to archive',
17
+ required: false,
18
+ }),
26
19
  };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
20
+ static flags = {
21
+ list: Flags.boolean({
22
+ char: 'l',
23
+ description: 'List archived projects',
24
+ default: false,
25
+ }),
26
+ force: Flags.boolean({
27
+ char: 'f',
28
+ description: 'Force archive even if tasks are incomplete',
29
+ default: false,
30
+ }),
31
+ yes: Flags.boolean({
32
+ char: 'y',
33
+ description: 'Skip all confirmation prompts (agent-friendly)',
34
+ default: false,
35
+ }),
36
+ restore: Flags.string({
37
+ char: 'r',
38
+ description: 'Restore an archived project',
39
+ }),
33
40
  };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- const core_1 = require("@oclif/core");
40
- const chalk_1 = __importDefault(require("chalk"));
41
- const inquirer_1 = __importDefault(require("inquirer"));
42
- const archive_manager_1 = require("../../core/archive-manager");
43
- class Archive extends core_1.Command {
44
41
  async run() {
45
42
  const { args, flags } = await this.parse(Archive);
46
- const archiveManager = new archive_manager_1.ArchiveManager();
43
+ const archiveManager = new ArchiveManager();
47
44
  try {
48
45
  // Handle restore flag
49
46
  if (flags.restore) {
50
- await this.restoreProject(flags.restore, archiveManager);
47
+ await this.restoreProject(flags.restore, archiveManager, flags.yes);
51
48
  return;
52
49
  }
53
50
  // Handle list flag
@@ -57,45 +54,45 @@ class Archive extends core_1.Command {
57
54
  }
58
55
  // Handle direct project archival
59
56
  if (args.project) {
60
- await this.archiveSpecificProject(args.project, flags.force, archiveManager);
57
+ await this.archiveSpecificProject(args.project, flags.force, flags.yes, archiveManager);
61
58
  return;
62
59
  }
63
60
  // Interactive mode
64
- await this.interactiveArchive(archiveManager);
61
+ await this.interactiveArchive(archiveManager, flags.yes);
65
62
  }
66
63
  catch (error) {
67
- const { getErrorMessage } = await Promise.resolve().then(() => __importStar(require('../../utils/error-utils.js')));
68
- this.error(chalk_1.default.red(`Archive failed: ${getErrorMessage(error)}`));
64
+ const { getErrorMessage } = await import('../../utils/error-utils.js');
65
+ this.error(chalk.red(`Archive failed: ${getErrorMessage(error)}`));
69
66
  }
70
67
  }
71
68
  /**
72
69
  * Interactive archive mode - show list of archivable projects
73
70
  */
74
- async interactiveArchive(archiveManager) {
75
- this.log(chalk_1.default.bold.cyan('\n📦 Archive PRD Projects\n'));
71
+ async interactiveArchive(archiveManager, yes) {
72
+ this.log(chalk.bold.cyan('\n📦 Archive PRD Projects\n'));
76
73
  // Get all archivable projects (100% tasks completed)
77
74
  const archivableProjects = await archiveManager.getArchivablePrds();
78
75
  if (archivableProjects.length === 0) {
79
- this.log(chalk_1.default.gray('No projects ready to archive.'));
80
- this.log(chalk_1.default.gray('\nProjects can be archived when all tasks are completed.'));
81
- this.log(chalk_1.default.gray('Use ') + chalk_1.default.cyan('clavix list --outputs') + chalk_1.default.gray(' to see all projects.'));
76
+ this.log(chalk.gray('No projects ready to archive.'));
77
+ this.log(chalk.gray('\nProjects can be archived when all tasks are completed.'));
78
+ this.log(chalk.gray('Use ') + chalk.cyan('clavix list --outputs') + chalk.gray(' to see all projects.'));
82
79
  return;
83
80
  }
84
81
  // Show archivable projects
85
- this.log(chalk_1.default.green(`Found ${archivableProjects.length} project(s) ready to archive:\n`));
82
+ this.log(chalk.green(`Found ${archivableProjects.length} project(s) ready to archive:\n`));
86
83
  // Inquirer choices can be mixed types (choices + separators)
87
84
  const choices = archivableProjects.map((project) => ({
88
85
  name: `${project.name} (${project.taskStatus.completed} tasks completed)`,
89
86
  value: project.name,
90
87
  short: project.name,
91
88
  }));
92
- choices.push(new inquirer_1.default.Separator());
89
+ choices.push(new inquirer.Separator());
93
90
  choices.push({
94
- name: chalk_1.default.gray('Cancel'),
91
+ name: chalk.gray('Cancel'),
95
92
  value: '__cancel__',
96
93
  short: 'Cancel',
97
94
  });
98
- const { selectedProject } = await inquirer_1.default.prompt([
95
+ const { selectedProject } = await inquirer.prompt([
99
96
  {
100
97
  type: 'list',
101
98
  name: 'selectedProject',
@@ -105,101 +102,107 @@ class Archive extends core_1.Command {
105
102
  },
106
103
  ]);
107
104
  if (selectedProject === '__cancel__') {
108
- this.log(chalk_1.default.yellow('\n✗ Archive cancelled\n'));
105
+ this.log(chalk.yellow('\n✗ Archive cancelled\n'));
109
106
  return;
110
107
  }
111
- // Confirm archival
112
- const { confirm } = await inquirer_1.default.prompt([
113
- {
114
- type: 'confirm',
115
- name: 'confirm',
116
- message: `Archive "${selectedProject}"? (This will move it to .clavix/outputs/archive/)`,
117
- default: false,
118
- },
119
- ]);
120
- if (!confirm) {
121
- this.log(chalk_1.default.yellow('\n✗ Archive cancelled\n'));
122
- return;
108
+ // Confirm archival (unless --yes)
109
+ if (!yes) {
110
+ const { confirm } = await inquirer.prompt([
111
+ {
112
+ type: 'confirm',
113
+ name: 'confirm',
114
+ message: `Archive "${selectedProject}"? (This will move it to .clavix/outputs/archive/)`,
115
+ default: false,
116
+ },
117
+ ]);
118
+ if (!confirm) {
119
+ this.log(chalk.yellow('\n✗ Archive cancelled\n'));
120
+ return;
121
+ }
123
122
  }
124
123
  // Archive the project
125
124
  const result = await archiveManager.archiveProject(selectedProject);
126
125
  if (result.success) {
127
- this.log(chalk_1.default.green(`\n✓ ${result.message}\n`));
126
+ this.log(chalk.green(`\n✓ ${result.message}\n`));
128
127
  }
129
128
  else {
130
- this.error(chalk_1.default.red(`\n✗ ${result.message}\n`));
129
+ this.error(chalk.red(`\n✗ ${result.message}\n`));
131
130
  }
132
131
  }
133
132
  /**
134
133
  * Archive a specific project by name
135
134
  */
136
- async archiveSpecificProject(projectName, force, archiveManager) {
137
- this.log(chalk_1.default.cyan(`\nArchiving project: ${chalk_1.default.bold(projectName)}\n`));
135
+ async archiveSpecificProject(projectName, force, yes, archiveManager) {
136
+ this.log(chalk.cyan(`\nArchiving project: ${chalk.bold(projectName)}\n`));
138
137
  // Check task status
139
138
  const projectPath = `.clavix/outputs/${projectName}`;
140
139
  const taskStatus = await archiveManager.checkTasksStatus(projectPath);
141
- // If not forcing and tasks are incomplete, ask for confirmation
140
+ // If not forcing and tasks are incomplete, ask for confirmation (unless --yes)
142
141
  if (!force && !taskStatus.allCompleted) {
143
142
  if (!taskStatus.hasTasksFile) {
144
- this.log(chalk_1.default.yellow(`⚠ Project has no tasks.md file\n`));
145
- const { proceed } = await inquirer_1.default.prompt([
146
- {
147
- type: 'confirm',
148
- name: 'proceed',
149
- message: 'Archive anyway?',
150
- default: false,
151
- },
152
- ]);
153
- if (!proceed) {
154
- this.log(chalk_1.default.yellow('\n✗ Archive cancelled\n'));
155
- return;
143
+ this.log(chalk.yellow(`⚠ Project has no tasks.md file\n`));
144
+ if (!yes) {
145
+ const { proceed } = await inquirer.prompt([
146
+ {
147
+ type: 'confirm',
148
+ name: 'proceed',
149
+ message: 'Archive anyway?',
150
+ default: false,
151
+ },
152
+ ]);
153
+ if (!proceed) {
154
+ this.log(chalk.yellow('\n✗ Archive cancelled\n'));
155
+ return;
156
+ }
156
157
  }
157
158
  }
158
159
  else if (taskStatus.remaining > 0) {
159
- this.log(chalk_1.default.yellow(`⚠ Project has ${taskStatus.remaining} incomplete task(s):\n`));
160
+ this.log(chalk.yellow(`⚠ Project has ${taskStatus.remaining} incomplete task(s):\n`));
160
161
  // Show incomplete tasks
161
162
  const incompleteTasks = await archiveManager.getIncompleteTasks(projectPath);
162
163
  incompleteTasks.slice(0, 5).forEach((task) => {
163
- this.log(chalk_1.default.gray(` • ${task}`));
164
+ this.log(chalk.gray(` • ${task}`));
164
165
  });
165
166
  if (incompleteTasks.length > 5) {
166
- this.log(chalk_1.default.gray(` ... and ${incompleteTasks.length - 5} more\n`));
167
+ this.log(chalk.gray(` ... and ${incompleteTasks.length - 5} more\n`));
167
168
  }
168
169
  else {
169
170
  this.log('');
170
171
  }
171
- const { proceed } = await inquirer_1.default.prompt([
172
- {
173
- type: 'confirm',
174
- name: 'proceed',
175
- message: 'Archive anyway?',
176
- default: false,
177
- },
178
- ]);
179
- if (!proceed) {
180
- this.log(chalk_1.default.yellow('\n✗ Archive cancelled\n'));
181
- return;
172
+ if (!yes) {
173
+ const { proceed } = await inquirer.prompt([
174
+ {
175
+ type: 'confirm',
176
+ name: 'proceed',
177
+ message: 'Archive anyway?',
178
+ default: false,
179
+ },
180
+ ]);
181
+ if (!proceed) {
182
+ this.log(chalk.yellow('\n✗ Archive cancelled\n'));
183
+ return;
184
+ }
182
185
  }
183
186
  }
184
187
  }
185
188
  // Archive the project
186
189
  const result = await archiveManager.archiveProject(projectName, true);
187
190
  if (result.success) {
188
- this.log(chalk_1.default.green(`✓ ${result.message}\n`));
191
+ this.log(chalk.green(`✓ ${result.message}\n`));
189
192
  }
190
193
  else {
191
- this.error(chalk_1.default.red(`✗ ${result.message}\n`));
194
+ this.error(chalk.red(`✗ ${result.message}\n`));
192
195
  }
193
196
  }
194
197
  /**
195
198
  * List all archived projects
196
199
  */
197
200
  async listArchivedProjects(archiveManager) {
198
- this.log(chalk_1.default.bold.cyan('\n📦 Archived Projects\n'));
201
+ this.log(chalk.bold.cyan('\n📦 Archived Projects\n'));
199
202
  const archivedProjects = await archiveManager.listArchivedProjects();
200
203
  if (archivedProjects.length === 0) {
201
- this.log(chalk_1.default.gray('No archived projects found.'));
202
- this.log(chalk_1.default.gray('\nUse ') + chalk_1.default.cyan('clavix archive') + chalk_1.default.gray(' to archive completed projects.\n'));
204
+ this.log(chalk.gray('No archived projects found.'));
205
+ this.log(chalk.gray('\nUse ') + chalk.cyan('clavix archive') + chalk.gray(' to archive completed projects.\n'));
203
206
  return;
204
207
  }
205
208
  // Display archived projects
@@ -209,40 +212,42 @@ class Archive extends core_1.Command {
209
212
  ? `${project.taskStatus.completed}/${project.taskStatus.total} tasks`
210
213
  : 'no tasks';
211
214
  const modified = project.modifiedTime.toLocaleDateString();
212
- this.log(` ${statusIcon} ${chalk_1.default.bold(project.name)}` +
213
- `\n ${chalk_1.default.gray('Tasks:')} ${taskInfo} ${chalk_1.default.gray('│')} ` +
214
- `${chalk_1.default.gray('Archived:')} ${modified}` +
215
- `\n ${chalk_1.default.gray('Path:')} ${chalk_1.default.dim(project.path)}` +
215
+ this.log(` ${statusIcon} ${chalk.bold(project.name)}` +
216
+ `\n ${chalk.gray('Tasks:')} ${taskInfo} ${chalk.gray('│')} ` +
217
+ `${chalk.gray('Archived:')} ${modified}` +
218
+ `\n ${chalk.gray('Path:')} ${chalk.dim(project.path)}` +
216
219
  (index < archivedProjects.length - 1 ? '\n' : ''));
217
220
  });
218
221
  this.log('');
219
- this.log(chalk_1.default.gray(` Total: ${archivedProjects.length} archived project(s)`));
220
- this.log(chalk_1.default.gray(` Use ${chalk_1.default.cyan('clavix archive --restore <project>')} to restore a project\n`));
222
+ this.log(chalk.gray(` Total: ${archivedProjects.length} archived project(s)`));
223
+ this.log(chalk.gray(` Use ${chalk.cyan('clavix archive --restore <project>')} to restore a project\n`));
221
224
  }
222
225
  /**
223
226
  * Restore an archived project
224
227
  */
225
- async restoreProject(projectName, archiveManager) {
226
- this.log(chalk_1.default.cyan(`\nRestoring project: ${chalk_1.default.bold(projectName)}\n`));
227
- // Confirm restoration
228
- const { confirm } = await inquirer_1.default.prompt([
229
- {
230
- type: 'confirm',
231
- name: 'confirm',
232
- message: `Restore "${projectName}" from archive?`,
233
- default: false,
234
- },
235
- ]);
236
- if (!confirm) {
237
- this.log(chalk_1.default.yellow('\n✗ Restore cancelled\n'));
238
- return;
228
+ async restoreProject(projectName, archiveManager, yes) {
229
+ this.log(chalk.cyan(`\nRestoring project: ${chalk.bold(projectName)}\n`));
230
+ // Confirm restoration (unless --yes)
231
+ if (!yes) {
232
+ const { confirm } = await inquirer.prompt([
233
+ {
234
+ type: 'confirm',
235
+ name: 'confirm',
236
+ message: `Restore "${projectName}" from archive?`,
237
+ default: false,
238
+ },
239
+ ]);
240
+ if (!confirm) {
241
+ this.log(chalk.yellow('\n✗ Restore cancelled\n'));
242
+ return;
243
+ }
239
244
  }
240
245
  const result = await archiveManager.restoreProject(projectName);
241
246
  if (result.success) {
242
- this.log(chalk_1.default.green(`✓ ${result.message}\n`));
247
+ this.log(chalk.green(`✓ ${result.message}\n`));
243
248
  }
244
249
  else {
245
- this.error(chalk_1.default.red(`✗ ${result.message}\n`));
250
+ this.error(chalk.red(`✗ ${result.message}\n`));
246
251
  }
247
252
  }
248
253
  /**
@@ -253,40 +258,9 @@ class Archive extends core_1.Command {
253
258
  const taskInfo = project.taskStatus.hasTasksFile
254
259
  ? `${project.taskStatus.completed}/${project.taskStatus.total} tasks (${Math.round(project.taskStatus.percentage)}%)`
255
260
  : 'no tasks';
256
- this.log(` ${statusIcon} ${chalk_1.default.bold(project.name)}` +
257
- `\n ${chalk_1.default.gray('Tasks:')} ${taskInfo}` +
258
- `\n ${chalk_1.default.gray('Modified:')} ${project.modifiedTime.toLocaleDateString()}`);
261
+ this.log(` ${statusIcon} ${chalk.bold(project.name)}` +
262
+ `\n ${chalk.gray('Tasks:')} ${taskInfo}` +
263
+ `\n ${chalk.gray('Modified:')} ${project.modifiedTime.toLocaleDateString()}`);
259
264
  }
260
265
  }
261
- Archive.description = 'Archive completed PRD projects';
262
- Archive.examples = [
263
- '<%= config.bin %> <%= command.id %> # Interactive selection',
264
- '<%= config.bin %> <%= command.id %> my-project # Archive specific project',
265
- '<%= config.bin %> <%= command.id %> --list # List archived projects',
266
- '<%= config.bin %> <%= command.id %> my-project --force # Force archive',
267
- '<%= config.bin %> <%= command.id %> --restore my-project # Restore from archive',
268
- ];
269
- Archive.args = {
270
- project: core_1.Args.string({
271
- description: 'Name of the project to archive',
272
- required: false,
273
- }),
274
- };
275
- Archive.flags = {
276
- list: core_1.Flags.boolean({
277
- char: 'l',
278
- description: 'List archived projects',
279
- default: false,
280
- }),
281
- force: core_1.Flags.boolean({
282
- char: 'f',
283
- description: 'Force archive even if tasks are incomplete',
284
- default: false,
285
- }),
286
- restore: core_1.Flags.string({
287
- char: 'r',
288
- description: 'Restore an archived project',
289
- }),
290
- };
291
- exports.default = Archive;
292
266
  //# sourceMappingURL=archive.js.map
@@ -3,12 +3,12 @@ export default class Config extends Command {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static args: {
6
- action: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
- key: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
8
- value: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
6
+ action: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ key: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
8
+ value: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
9
9
  };
10
10
  static flags: {
11
- global: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
+ global: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
12
  };
13
13
  run(): Promise<void>;
14
14
  private showInteractiveMenu;