@comfanion/workflow 3.5.1 ā 3.7.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 +75 -27
- package/package.json +1 -1
- package/src/build-info.json +1 -1
- package/src/opencode/agents/analyst.md +2 -2
- package/src/opencode/agents/architect.md +2 -2
- package/src/opencode/agents/change-manager.md +2 -2
- package/src/opencode/agents/dev.md +2 -2
- package/src/opencode/agents/pm.md +2 -2
- package/src/opencode/agents/researcher.md +2 -2
- package/src/opencode/config.yaml +1 -1
- package/src/opencode/opencode.json +2 -9
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.
|
|
21
|
+
.version('3.7.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.
|
|
32
|
+
console.log(chalk.blue.bold('\nš OpenCode Workflow v3.7\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:
|
|
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' :
|
|
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 ||
|
|
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:
|
|
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:
|
|
151
|
+
default: config.jira_project
|
|
87
152
|
},
|
|
88
153
|
{
|
|
89
154
|
type: 'confirm',
|
|
@@ -105,35 +170,18 @@ program
|
|
|
105
170
|
const spinner = ora('Initializing OpenCode Workflow...').start();
|
|
106
171
|
|
|
107
172
|
try {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
// Check if already exists
|
|
111
|
-
let existingConfig = null;
|
|
173
|
+
// If updating, create backup and remove old directory
|
|
112
174
|
if (await fs.pathExists(targetDir)) {
|
|
113
|
-
spinner.warn(chalk.yellow('.opencode/ already exists'));
|
|
114
|
-
const { overwrite } = await inquirer.prompt([{
|
|
115
|
-
type: 'confirm',
|
|
116
|
-
name: 'overwrite',
|
|
117
|
-
message: 'Overwrite existing .opencode/?',
|
|
118
|
-
default: false
|
|
119
|
-
}]);
|
|
120
|
-
|
|
121
|
-
if (!overwrite) {
|
|
122
|
-
console.log(chalk.yellow('\nAborted. Use `update` command to update existing installation.\n'));
|
|
123
|
-
process.exit(0);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Create backup and remove old directory
|
|
127
175
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
128
176
|
const backupDir = path.join(process.cwd(), `.opencode.backup-${timestamp}`);
|
|
129
177
|
|
|
130
|
-
spinner.
|
|
178
|
+
spinner.text = 'Creating backup...';
|
|
131
179
|
await fs.copy(targetDir, backupDir);
|
|
132
180
|
|
|
133
181
|
spinner.text = 'Removing old .opencode/...';
|
|
134
182
|
await fs.remove(targetDir);
|
|
135
183
|
|
|
136
|
-
console.log(chalk.yellow(`\nš¦ Backup
|
|
184
|
+
console.log(chalk.yellow(`\nš¦ Backup: ${chalk.cyan(`.opencode.backup-${timestamp}/`)}`));
|
|
137
185
|
}
|
|
138
186
|
|
|
139
187
|
spinner.start('Copying OpenCode Workflow files...');
|
package/package.json
CHANGED
package/src/build-info.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "
|
|
3
|
-
mode:
|
|
2
|
+
description: "Business Analyst - Use for: gathering requirements, validating requirements, brainstorming. Has skills: requirements-gathering, requirements-validation"
|
|
3
|
+
mode: all
|
|
4
4
|
tools:
|
|
5
5
|
write: true
|
|
6
6
|
edit: true
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Solution Architect -
|
|
3
|
-
mode:
|
|
2
|
+
description: "Solution Architect - Use for: system architecture, module documentation, ADRs, coding standards, API design. Has skills: architecture-design, architecture-validation, adr-writing, module-documentation, coding-standards"
|
|
3
|
+
mode: all
|
|
4
4
|
tools:
|
|
5
5
|
write: true
|
|
6
6
|
edit: true
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Change Manager -
|
|
3
|
-
mode:
|
|
2
|
+
description: "Change Manager - Use for: change proposals, document updates with delta tracking, reviewing changes before merge"
|
|
3
|
+
mode: all
|
|
4
4
|
tools:
|
|
5
5
|
write: true
|
|
6
6
|
edit: true
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Senior Developer -
|
|
3
|
-
mode:
|
|
2
|
+
description: "Senior Developer - Use for: implementing stories, TDD development, code review, running tests. Has skills: code-review, test-design"
|
|
3
|
+
mode: all
|
|
4
4
|
tools:
|
|
5
5
|
write: true
|
|
6
6
|
edit: true
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Product Manager - PRD, epics, stories, sprint planning, Jira sync"
|
|
3
|
-
mode:
|
|
2
|
+
description: "Product Manager - Use for: creating PRD, writing epics, writing stories, sprint planning, Jira sync. Has skills: prd-writing, epic-writing, story-writing, sprint-planning, jira-integration"
|
|
3
|
+
mode: all
|
|
4
4
|
tools:
|
|
5
5
|
write: true
|
|
6
6
|
edit: true
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Research Specialist -
|
|
3
|
-
mode:
|
|
2
|
+
description: "Research Specialist - Use for: technical research, market research, domain research, competitive analysis. Has skills: research-methodology, methodologies"
|
|
3
|
+
mode: all
|
|
4
4
|
tools:
|
|
5
5
|
write: true
|
|
6
6
|
edit: true
|
package/src/opencode/config.yaml
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# PROJECT CONFIGURATION
|
|
7
7
|
# =============================================================================
|
|
8
8
|
project_name: "ai-wf"
|
|
9
|
-
version: "3.
|
|
9
|
+
version: "3.7.0"
|
|
10
10
|
|
|
11
11
|
# =============================================================================
|
|
12
12
|
# USER CONFIGURATION
|
|
@@ -11,17 +11,10 @@
|
|
|
11
11
|
"agent": {
|
|
12
12
|
"build": {
|
|
13
13
|
"mode": "primary",
|
|
14
|
-
"description": "Default development agent
|
|
15
|
-
"model": "anthropic/claude-sonnet-4-20250514"
|
|
14
|
+
"description": "Default development agent - use @pm, @architect, @analyst, @dev for specialized tasks"
|
|
16
15
|
},
|
|
17
16
|
"plan": {
|
|
18
|
-
"
|
|
19
|
-
"description": "Planning agent - analyzes without making changes",
|
|
20
|
-
"model": "anthropic/claude-sonnet-4-20250514",
|
|
21
|
-
"permission": {
|
|
22
|
-
"edit": "ask",
|
|
23
|
-
"bash": "ask"
|
|
24
|
-
}
|
|
17
|
+
"disable": true
|
|
25
18
|
}
|
|
26
19
|
},
|
|
27
20
|
|