@comfanion/workflow 4.39.0-dev.0 → 4.39.1

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
@@ -54,7 +54,6 @@ program
54
54
  .option('--tdd', 'Use TDD methodology')
55
55
  .option('--stub', 'Use STUB methodology')
56
56
  .option('--full', 'Create full repo structure')
57
- .option('--vectorizer', 'Install vectorizer for semantic code search')
58
57
  .action(async (options) => {
59
58
  console.log(chalk.blue.bold(`\nšŸš€ OpenCode Workflow v${VERSION}\n`));
60
59
 
@@ -70,9 +69,6 @@ program
70
69
  jira_url: 'https://your-domain.atlassian.net',
71
70
  jira_project: 'PROJ',
72
71
  create_repo_structure: false,
73
- vectorizer_enabled: true,
74
- vectorizer_auto_index: true,
75
- vectorizer_model: 'Xenova/all-MiniLM-L6-v2',
76
72
  project_name: path.basename(process.cwd())
77
73
  };
78
74
 
@@ -99,19 +95,6 @@ program
99
95
  if (jiraUrlMatch) config.jira_url = jiraUrlMatch[1];
100
96
  if (jiraProjMatch) config.jira_project = jiraProjMatch[1];
101
97
 
102
- // Parse vectorizer settings from vectorizer.yaml if exists
103
- const vecPath = path.join(targetDir, 'vectorizer.yaml');
104
- if (await fs.pathExists(vecPath)) {
105
- const vecContent = await fs.readFile(vecPath, 'utf8');
106
- const vEnabledMatch = vecContent.match(/enabled:\s*(true|false)/);
107
- const vAutoMatch = vecContent.match(/auto_index:\s*(true|false)/);
108
- const vModelMatch = vecContent.match(/model:\s*["']?([^"'\n]+)["']?/);
109
-
110
- if (vEnabledMatch) config.vectorizer_enabled = vEnabledMatch[1] === 'true';
111
- if (vAutoMatch) config.vectorizer_auto_index = vAutoMatch[1] === 'true';
112
- if (vModelMatch) config.vectorizer_model = vModelMatch[1].trim();
113
- }
114
-
115
98
  isUpdate = true;
116
99
  } catch (e) {
117
100
  // Could not parse, use defaults
@@ -199,40 +182,6 @@ program
199
182
  message: 'Create full repository structure (README, CONTRIBUTING, .gitignore, docs/)?',
200
183
  default: options.full || false
201
184
  },
202
- {
203
- type: 'confirm',
204
- name: 'vectorizer_enabled',
205
- message: 'Enable semantic code search (vectorizer)?',
206
- default: true
207
- },
208
- {
209
- type: 'list',
210
- name: 'vectorizer_model',
211
- message: 'Embedding model for semantic search:',
212
- when: (answers) => answers.vectorizer_enabled,
213
- choices: [
214
- {
215
- name: 'MiniLM-L6 (Fast) - ~10 files/10sec, 384 dims, good quality',
216
- value: 'Xenova/all-MiniLM-L6-v2'
217
- },
218
- {
219
- name: 'BGE-small (Balanced) - ~9 files/10sec, 384 dims, better quality',
220
- value: 'Xenova/bge-small-en-v1.5'
221
- },
222
- {
223
- name: 'BGE-base (Quality) - ~3 files/10sec, 768 dims, best quality',
224
- value: 'Xenova/bge-base-en-v1.5'
225
- }
226
- ],
227
- default: config.vectorizer_model
228
- },
229
- {
230
- type: 'confirm',
231
- name: 'vectorizer_auto_index',
232
- message: 'Enable auto-indexing? (reindex files on save)',
233
- when: (answers) => answers.vectorizer_enabled,
234
- default: true
235
- },
236
185
  {
237
186
  type: 'checkbox',
238
187
  name: 'mcp_servers',
@@ -259,7 +208,6 @@ program
259
208
  if (options.stub) config.methodology = 'stub';
260
209
  if (options.jira) config.jira_enabled = true;
261
210
  if (options.full) config.create_repo_structure = true;
262
- if (options.vectorizer) config.install_vectorizer = true;
263
211
  }
264
212
 
265
213
  const spinner = ora('Initializing OpenCode Workflow...').start();
@@ -324,7 +272,6 @@ program
324
272
  // Update config.yaml with user values
325
273
  spinner.text = 'Configuring...';
326
274
  const configPath = path.join(targetDir, 'config.yaml');
327
- const vecPath = path.join(targetDir, 'vectorizer.yaml');
328
275
  let configContent;
329
276
 
330
277
  // If we had existing config, use it as base (preserves comments and formatting)
@@ -354,19 +301,6 @@ program
354
301
 
355
302
  await fs.writeFile(configPath, configContent);
356
303
 
357
- // Update vectorizer.yaml
358
- if (await fs.pathExists(vecPath)) {
359
- let vecContent = await fs.readFile(vecPath, 'utf8');
360
- vecContent = vecContent
361
- .replace(/(enabled:)\s*(true|false)/, `$1 ${config.vectorizer_enabled}`)
362
- .replace(/(auto_index:)\s*(true|false)/, `$1 ${config.vectorizer_auto_index}`);
363
-
364
- if (config.vectorizer_model) {
365
- vecContent = vecContent.replace(/(model:)\s*["']?[^"'\n]+["']?/, `$1 "${config.vectorizer_model}"`);
366
- }
367
- await fs.writeFile(vecPath, vecContent);
368
- }
369
-
370
304
  // Create docs structure (always)
371
305
  spinner.text = 'Creating docs structure...';
372
306
  await fs.ensureDir(path.join(process.cwd(), 'docs'));
@@ -476,24 +410,10 @@ program
476
410
  console.log(chalk.gray(' Run manually: cd .opencode && bun install'));
477
411
  }
478
412
 
479
- // Show what was done
480
- const vectorizerInstalled = await fs.pathExists(path.join(targetDir, 'vectorizer', 'node_modules'));
481
- if (vectorizerInstalled) {
482
- console.log(chalk.green('āœ… Vectorizer installed (fresh dependencies)'));
483
- } else if (config.vectorizer_enabled) {
484
- console.log(chalk.yellow('āš ļø Vectorizer: run `npx @comfanion/workflow vectorizer install`'));
485
- } else {
486
- console.log(chalk.gray('ā„¹ļø Vectorizer disabled (enable in config.yaml to use semantic search)'));
487
- }
488
413
  if (hadVectors) {
489
414
  console.log(chalk.green('āœ… Vector indexes preserved'));
490
415
  }
491
416
 
492
- // Install vectorizer if requested and failed above
493
- if (config.install_vectorizer && !vectorizerInstalled) {
494
- await installVectorizer(targetDir);
495
- }
496
-
497
417
  // Show summary
498
418
  console.log(chalk.yellow('\nšŸ“ Created structure:'));
499
419
  console.log(`
@@ -559,9 +479,8 @@ program
559
479
 
560
480
  program
561
481
  .command('update')
562
- .description('Update .opencode/ to latest version (preserves config.yaml and vectorizer)')
482
+ .description('Update .opencode/ to latest version (preserves config.yaml and vector indexes)')
563
483
  .option('--no-backup', 'Skip creating backup')
564
- .option('--vectorizer', 'Update/install vectorizer too')
565
484
  .action(async (options) => {
566
485
  const spinner = ora('Updating OpenCode Workflow...').start();
567
486
 
@@ -762,27 +681,25 @@ program
762
681
  console.log(chalk.gray(' ā—‹ Jira credentials not set'));
763
682
  }
764
683
 
765
- // Check Vectorizer
766
- console.log(chalk.cyan('\nVectorizer (semantic search):'));
767
- const vectorsExist = await fs.pathExists(path.join(process.cwd(), '.opencode', 'vectors', 'code', 'hashes.json'));
768
-
769
- // Check vectorizer config
770
- let vectorizerEnabled = true;
771
- let autoIndexEnabled = true;
684
+ // Check Semantic Search plugin
685
+ console.log(chalk.cyan('\nSemantic search (@comfanion/usethis_search):'));
772
686
  try {
773
- const vecConfigContent = await fs.readFile(path.join(process.cwd(), '.opencode/vectorizer.yaml'), 'utf8');
774
- const vecEnabledMatch = vecConfigContent.match(/enabled:\s*(true|false)/);
775
- const autoIndexMatch = vecConfigContent.match(/auto_index:\s*(true|false)/);
776
- if (vecEnabledMatch) vectorizerEnabled = vecEnabledMatch[1] === 'true';
777
- if (autoIndexMatch) autoIndexEnabled = autoIndexMatch[1] === 'true';
778
- } catch {}
779
-
780
- console.log(vectorizerEnabled
781
- ? chalk.green(' āœ… Enabled in config')
782
- : chalk.yellow(' āš ļø Disabled in config'));
783
- console.log(autoIndexEnabled
784
- ? chalk.green(' āœ… Auto-index: ON')
785
- : chalk.gray(' ā—‹ Auto-index: OFF'));
687
+ const opcPath = path.join(process.cwd(), 'opencode.json');
688
+ if (await fs.pathExists(opcPath)) {
689
+ const opc = JSON.parse(await fs.readFile(opcPath, 'utf8'));
690
+ const plugins = opc.plugin || [];
691
+ if (plugins.includes('@comfanion/usethis_search')) {
692
+ console.log(chalk.green(' āœ… Plugin registered in opencode.json'));
693
+ } else {
694
+ console.log(chalk.yellow(' āš ļø Plugin not in opencode.json (add "@comfanion/usethis_search" to plugin array)'));
695
+ }
696
+ } else {
697
+ console.log(chalk.gray(' ā—‹ No opencode.json found'));
698
+ }
699
+ } catch {
700
+ console.log(chalk.gray(' ā—‹ Could not check opencode.json'));
701
+ }
702
+ const vectorsExist = await fs.pathExists(path.join(process.cwd(), '.opencode', 'vectors', 'code', 'hashes.json'));
786
703
  if (vectorsExist) {
787
704
  try {
788
705
  const hashes = await fs.readJSON(path.join(process.cwd(), '.opencode', 'vectors', 'code', 'hashes.json'));
@@ -791,14 +708,7 @@ program
791
708
  console.log(chalk.gray(' ā—‹ Not indexed yet'));
792
709
  }
793
710
  } else {
794
- console.log(chalk.gray(' ā—‹ Not indexed (will index on startup)'));
795
- }
796
-
797
- // Check LSP env
798
- if (process.env.OPENCODE_EXPERIMENTAL_LSP_TOOL === 'true' || process.env.OPENCODE_EXPERIMENTAL === 'true') {
799
- console.log(chalk.green(' āœ… LSP tool enabled'));
800
- } else {
801
- console.log(chalk.gray(' ā—‹ LSP tool disabled (set OPENCODE_EXPERIMENTAL_LSP_TOOL=true)'));
711
+ console.log(chalk.gray(' ā—‹ Not indexed (will index on first startup with plugin)'));
802
712
  }
803
713
 
804
714
  console.log('');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comfanion/workflow",
3
- "version": "4.39.0-dev.0",
3
+ "version": "4.39.1",
4
4
  "description": "Initialize OpenCode Workflow system for AI-assisted development with semantic code search",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "4.39.0-dev.0",
3
- "buildDate": "2026-01-28T23:02:57.835Z",
2
+ "version": "4.39.1",
3
+ "buildDate": "2026-01-29T22:52:34.568Z",
4
4
  "files": [
5
5
  ".gitignore",
6
6
  "config.yaml",
@@ -12,7 +12,6 @@
12
12
  "commands",
13
13
  "mcp",
14
14
  "package.json",
15
- "opencode.json",
16
- "vectorizer.yaml"
15
+ "opencode.json"
17
16
  ]
18
17
  }
@@ -67,6 +67,7 @@ permission:
67
67
  <r>ALWAYS write technical documentation in ENGLISH (docs/ folder)</r>
68
68
  <r>Translations go to docs/confluence/ folder</r>
69
69
  <r critical="MANDATORY">šŸ“š LOAD SKILL FIRST: Before creating any document (architecture/ADR/unit/coding-standards), MUST load appropriate skill</r>
70
+ <r recommended="true">šŸ“ For large docs (1000+ lines): prefer template → fill incrementally (better performance & quality)</r>
70
71
  <r>Always check existing codebase patterns in CLAUDE.md before proposing new patterns</r>
71
72
  <r>Document all decisions with ADRs and clear rationale</r>
72
73
  <r>Never skip NFR analysis</r>
@@ -114,8 +115,12 @@ permission:
114
115
  - LARGE: 2000-4000 lines, multiple files, DOMAINS
115
116
  - ENTERPRISE: 4000+ lines, per-domain files
116
117
 
118
+ REALITY CHECK: Most projects are TOY (30%) or SMALL (40%), MEDIUM+ (30%)
119
+ Default assumption: TOY/SMALL until proven otherwise
120
+
117
121
  Example:
118
122
  - PRD says "TOY" → Write 350 lines, 3 components, NO modules
123
+ - PRD says "SMALL" → Write 700 lines, simple structure, NO modules
119
124
  - PRD says "MEDIUM" → Write 1500 lines, 3 MODULES with Unit docs
120
125
 
121
126
  DON'T write 2000-line architecture for Tetris!
@@ -130,9 +135,11 @@ permission:
130
135
  </phase>
131
136
 
132
137
  <phase name="3. Execution">
138
+ <action>For large docs (1000+ lines): Create template → fill section by section (better performance)</action>
139
+ <action>For small docs: Can write directly</action>
133
140
  <action>Work through tasklist sequentially</action>
134
141
  <action>Mark tasks in_progress → completed</action>
135
- <action>If uncertain about something — ask, don't assume</action>
142
+ <action>If uncertain — ask, don't assume</action>
136
143
  </phase>
137
144
 
138
145
  <phase name="4. Review">
@@ -142,10 +149,8 @@ permission:
142
149
 
143
150
  <never-do>
144
151
  - Start creating files WITHOUT loading the skill first
145
- - Start creating files before user confirms the plan
146
152
  - Skip the tasklist for complex work
147
153
  - Assume what user wants without asking
148
- - Create all files at once without progress updates
149
154
  </never-do>
150
155
  </workflow>
151
156
 
@@ -64,6 +64,7 @@ permission:
64
64
  <r>ALWAYS write technical documentation in ENGLISH (docs/ folder)</r>
65
65
  <r>Translations go to docs/confluence/ folder</r>
66
66
  <r critical="MANDATORY">šŸ“š LOAD SKILL FIRST: Before creating any document (PRD/epic/story), MUST load appropriate skill</r>
67
+ <r recommended="true">šŸ“ For large docs (PRD, epics): prefer template → fill incrementally (better performance)</r>
67
68
  <r>PRDs emerge from user interviews, not template filling</r>
68
69
  <r>Ship the smallest thing that validates the assumption</r>
69
70
  <r>Every feature must trace to a user problem</r>
@@ -112,9 +113,12 @@ permission:
112
113
  </phase>
113
114
 
114
115
  <phase name="3. Execution">
116
+ <action>For large docs (PRD 1000+ lines): Create template → fill section by section (better performance)</action>
117
+ <action>For PRD: Start with "Project Classification" section FIRST</action>
118
+ <action>For small docs (stories, epics): Can write directly</action>
115
119
  <action>Work through tasklist sequentially</action>
116
120
  <action>Mark tasks in_progress → completed</action>
117
- <action>If uncertain about something — ask, don't assume</action>
121
+ <action>If uncertain — ask, don't assume</action>
118
122
  </phase>
119
123
 
120
124
  <phase name="4. Review">
@@ -124,10 +128,9 @@ permission:
124
128
 
125
129
  <never-do>
126
130
  - Start writing docs WITHOUT loading the skill first
127
- - Start writing docs before user confirms the plan
128
131
  - Skip the tasklist for complex work
129
132
  - Assume what user wants without asking
130
- - Create all documents at once without progress updates
133
+ - For PRD: Skip "Project Classification" section or fill it last (MUST BE FIRST!)
131
134
  </never-do>
132
135
  </workflow>
133
136
 
@@ -162,6 +165,9 @@ permission:
162
165
  5. Fill Project Classification table in PRD (first section!)
163
166
  6. Then write rest of PRD according to that size
164
167
 
168
+ REALITY CHECK: Most projects are TOY (30%) or SMALL (40%), MEDIUM+ (30%)
169
+ Default assumption: TOY/SMALL until proven otherwise
170
+
165
171
  Example questions:
166
172
  - "How many database tables do you expect?" (5-10 = SMALL, 20+ = MEDIUM)
167
173
  - "How many external integrations?" (0-2 = SMALL, 3-5 = MEDIUM)
@@ -9,6 +9,7 @@ vectorizer/node_modules/
9
9
 
10
10
  # Vectorizer cache (re-indexable, large binary files)
11
11
  vectors/
12
+ graph/
12
13
 
13
14
  # Build artifacts (regenerated by npm run build)
14
15
  cli/src/
@@ -1,45 +0,0 @@
1
- vectorizer:
2
- # Enable/disable vectorizer functionality
3
- enabled: true
4
-
5
- # Auto-index files when they change (requires file-indexer plugin)
6
- auto_index: true
7
-
8
- # Debounce time in ms (wait before indexing after file change)
9
- debounce_ms: 1000
10
-
11
- # Indexes to maintain - each has pattern (what to include) and ignore (what to skip)
12
- indexes:
13
-
14
- # Documentation index - markdown, text files
15
- docs:
16
- enabled: true
17
- pattern: "docs/**/*.{md,mdx,txt,rst,adoc}"
18
- ignore: []
19
-
20
- # Configuration index - yaml, json, toml
21
- config:
22
- enabled: false
23
- pattern: "**/*.{yaml,yml,json,toml,ini}"
24
- ignore:
25
- - "**/node_modules/**"
26
- - "**/.git/**"
27
- - "**/dist/**"
28
- - "**/build/**"
29
- - "**/.opencode/**"
30
- - "**/docs/**"
31
- - "**/vendor/**"
32
- - "**/__pycache__/**"
33
- - "**/*.min.js"
34
- - "**/*.bundle.js"
35
- - "**/package-lock.json"
36
- - "**/yarn.lock"
37
-
38
- # Global exclude patterns (applied to ALL indexes, in addition to per-index ignore)
39
- exclude:
40
- - node_modules
41
- - vendor
42
- - dist
43
- - build
44
- - out
45
- - __pycache__