@comfanion/workflow 3.5.0 → 3.6.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.
package/bin/cli.js CHANGED
@@ -18,7 +18,7 @@ const program = new Command();
18
18
  program
19
19
  .name('create-opencode-workflow')
20
20
  .description('Initialize OpenCode Workflow system for AI-assisted development')
21
- .version('3.5.0');
21
+ .version('3.6.0');
22
22
 
23
23
  program
24
24
  .command('init')
@@ -29,16 +29,81 @@ program
29
29
  .option('--stub', 'Use STUB methodology')
30
30
  .option('--full', 'Create full repo structure')
31
31
  .action(async (options) => {
32
- console.log(chalk.blue.bold('\nšŸš€ OpenCode Workflow v3.5\n'));
32
+ console.log(chalk.blue.bold('\nšŸš€ OpenCode Workflow v3.6\n'));
33
33
 
34
+ const targetDir = path.join(process.cwd(), '.opencode');
35
+ const existingConfigPath = path.join(targetDir, 'config.yaml');
36
+
37
+ // Default config
34
38
  let config = {
35
39
  user_name: 'Developer',
36
40
  communication_language: 'Ukrainian',
37
41
  methodology: 'tdd',
38
42
  jira_enabled: false,
43
+ jira_url: 'https://your-domain.atlassian.net',
44
+ jira_project: 'PROJ',
39
45
  create_repo_structure: false,
40
46
  project_name: path.basename(process.cwd())
41
47
  };
48
+
49
+ // Check if .opencode/ already exists
50
+ let isUpdate = false;
51
+ if (await fs.pathExists(targetDir)) {
52
+ // Try to read existing config
53
+ if (await fs.pathExists(existingConfigPath)) {
54
+ try {
55
+ const existingContent = await fs.readFile(existingConfigPath, 'utf8');
56
+
57
+ // Parse existing values
58
+ const nameMatch = existingContent.match(/user_name:\s*"([^"]+)"/);
59
+ const langMatch = existingContent.match(/communication_language:\s*"([^"]+)"/);
60
+ const methMatch = existingContent.match(/methodology:\s*(tdd|stub)/);
61
+ const jiraMatch = existingContent.match(/jira:[\s\S]*?enabled:\s*(true|false)/);
62
+ const jiraUrlMatch = existingContent.match(/base_url:\s*"([^"]+)"/);
63
+ const jiraProjMatch = existingContent.match(/project_key:\s*"([^"]+)"/);
64
+
65
+ if (nameMatch) config.user_name = nameMatch[1];
66
+ if (langMatch) config.communication_language = langMatch[1];
67
+ if (methMatch) config.methodology = methMatch[1];
68
+ if (jiraMatch) config.jira_enabled = jiraMatch[1] === 'true';
69
+ if (jiraUrlMatch) config.jira_url = jiraUrlMatch[1];
70
+ if (jiraProjMatch) config.jira_project = jiraProjMatch[1];
71
+
72
+ isUpdate = true;
73
+ } catch (e) {
74
+ // Could not parse, use defaults
75
+ }
76
+ }
77
+
78
+ console.log(chalk.yellow('.opencode/ already exists'));
79
+
80
+ if (isUpdate) {
81
+ console.log(chalk.gray(` Found config: ${config.user_name}, ${config.communication_language}, ${config.methodology.toUpperCase()}\n`));
82
+ }
83
+
84
+ const { action } = await inquirer.prompt([{
85
+ type: 'list',
86
+ name: 'action',
87
+ message: 'What would you like to do?',
88
+ choices: [
89
+ { name: 'Update files only (keep my settings)', value: 'update' },
90
+ { name: 'Reconfigure (change settings)', value: 'reconfigure' },
91
+ { name: 'Cancel', value: 'cancel' }
92
+ ],
93
+ default: 'update'
94
+ }]);
95
+
96
+ if (action === 'cancel') {
97
+ console.log(chalk.yellow('\nAborted.\n'));
98
+ process.exit(0);
99
+ }
100
+
101
+ if (action === 'update') {
102
+ // Use existing config, skip prompts
103
+ options.yes = true;
104
+ }
105
+ // If 'reconfigure', continue to prompts with existing values as defaults
106
+ }
42
107
 
43
108
  if (!options.yes) {
44
109
  const answers = await inquirer.prompt([
@@ -53,7 +118,7 @@ program
53
118
  name: 'communication_language',
54
119
  message: 'Communication language:',
55
120
  choices: ['Ukrainian', 'English'],
56
- default: 'Ukrainian'
121
+ default: config.communication_language
57
122
  },
58
123
  {
59
124
  type: 'list',
@@ -63,27 +128,27 @@ program
63
128
  { name: 'TDD - Test-Driven Development (write tests first)', value: 'tdd' },
64
129
  { name: 'STUB - Stub-First Development (write stubs, then implement)', value: 'stub' }
65
130
  ],
66
- default: options.tdd ? 'tdd' : (options.stub ? 'stub' : 'tdd')
131
+ default: options.tdd ? 'tdd' : (options.stub ? 'stub' : config.methodology)
67
132
  },
68
133
  {
69
134
  type: 'confirm',
70
135
  name: 'jira_enabled',
71
136
  message: 'Enable Jira integration?',
72
- default: options.jira || false
137
+ default: options.jira || config.jira_enabled
73
138
  },
74
139
  {
75
140
  type: 'input',
76
141
  name: 'jira_url',
77
142
  message: 'Jira URL:',
78
143
  when: (answers) => answers.jira_enabled,
79
- default: 'https://your-domain.atlassian.net'
144
+ default: config.jira_url
80
145
  },
81
146
  {
82
147
  type: 'input',
83
148
  name: 'jira_project',
84
149
  message: 'Jira project key:',
85
150
  when: (answers) => answers.jira_enabled,
86
- default: 'PROJ'
151
+ default: config.jira_project
87
152
  },
88
153
  {
89
154
  type: 'confirm',
@@ -105,28 +170,24 @@ program
105
170
  const spinner = ora('Initializing OpenCode Workflow...').start();
106
171
 
107
172
  try {
108
- const targetDir = path.join(process.cwd(), '.opencode');
109
-
110
- // Check if already exists
173
+ // If updating, create backup and remove old directory
111
174
  if (await fs.pathExists(targetDir)) {
112
- spinner.warn(chalk.yellow('.opencode/ already exists'));
113
- const { overwrite } = await inquirer.prompt([{
114
- type: 'confirm',
115
- name: 'overwrite',
116
- message: 'Overwrite existing .opencode/?',
117
- default: false
118
- }]);
175
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
176
+ const backupDir = path.join(process.cwd(), `.opencode.backup-${timestamp}`);
119
177
 
120
- if (!overwrite) {
121
- console.log(chalk.yellow('\nAborted. Use `update` command to update existing installation.\n'));
122
- process.exit(0);
123
- }
178
+ spinner.text = 'Creating backup...';
179
+ await fs.copy(targetDir, backupDir);
180
+
181
+ spinner.text = 'Removing old .opencode/...';
182
+ await fs.remove(targetDir);
183
+
184
+ console.log(chalk.yellow(`\nšŸ“¦ Backup: ${chalk.cyan(`.opencode.backup-${timestamp}/`)}`));
124
185
  }
125
186
 
126
187
  spinner.start('Copying OpenCode Workflow files...');
127
188
 
128
- // Copy .opencode structure
129
- await fs.copy(OPENCODE_SRC, targetDir, { overwrite: true });
189
+ // Copy .opencode structure (fresh, no old files)
190
+ await fs.copy(OPENCODE_SRC, targetDir);
130
191
 
131
192
  // Update config.yaml with user values
132
193
  spinner.text = 'Configuring...';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comfanion/workflow",
3
- "version": "3.5.0",
3
+ "version": "3.6.0",
4
4
  "description": "Initialize OpenCode Workflow system for AI-assisted development",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "3.0.0",
3
- "buildDate": "2026-01-23T16:24:04.259Z",
3
+ "buildDate": "2026-01-23T16:28:39.704Z",
4
4
  "files": [
5
5
  "config.yaml",
6
6
  "FLOW.yaml",
@@ -6,7 +6,7 @@
6
6
  # PROJECT CONFIGURATION
7
7
  # =============================================================================
8
8
  project_name: "ai-wf"
9
- version: "3.5.0"
9
+ version: "3.6.0"
10
10
 
11
11
  # =============================================================================
12
12
  # USER CONFIGURATION