@comfanion/workflow 4.36.24 → 4.36.26
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/README.md +36 -0
- package/package.json +1 -1
- package/src/build-info.json +2 -2
- package/src/opencode/FLOW.yaml +21 -5
- package/src/opencode/agents/analyst.md +1 -1
- package/src/opencode/agents/change-manager.md +1 -1
- package/src/opencode/agents/coder.md +1 -1
- package/src/opencode/agents/dev.md +1 -1
- package/src/opencode/agents/pm.md +1 -1
- package/src/opencode/agents/researcher.md +1 -1
- package/src/opencode/config.yaml +7 -3
- package/src/opencode/plugins/file-indexer.ts +4 -1
- package/src/opencode/tools/search.ts +2 -1
- package/src/vectorizer/index.js +42 -4
package/README.md
CHANGED
|
@@ -12,6 +12,37 @@ AI-assisted development workflow with **semantic code search**, agents, and stru
|
|
|
12
12
|
- 🔄 **Auto-indexing** - Background indexing on startup with fun toast notifications
|
|
13
13
|
- 🎯 **Jira Integration** - Bidirectional sync with your project
|
|
14
14
|
|
|
15
|
+
## Agents & Workflow
|
|
16
|
+
|
|
17
|
+
The workflow uses specialized AI agents, each with a unique persona and skills:
|
|
18
|
+
|
|
19
|
+
| Agent | Name | Role | Phase |
|
|
20
|
+
|-------|------|------|-------|
|
|
21
|
+
| 📊 **Analyst** | Sara | Requirements gathering, stakeholder interviews | Planning |
|
|
22
|
+
| 📋 **PM** | Dima | PRD, epics, stories, sprint planning, Jira | Planning → Sprint |
|
|
23
|
+
| 🏗️ **Architect** | Winston | System design, ADRs, coding standards | Planning |
|
|
24
|
+
| 💻 **Dev** | Rick | TDD implementation, code review | Implementation |
|
|
25
|
+
| ⚡ **Coder** | Morty | Quick implementation, bug fixes | Implementation |
|
|
26
|
+
| 🔍 **Researcher** | Kristina | Technical/market/domain research | Any |
|
|
27
|
+
| 🔄 **Change Manager** | Bruce | Documentation changes, impact analysis | Any |
|
|
28
|
+
|
|
29
|
+
### Workflow Pipeline
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
Planning: /requirements → /prd → /coding-standards → /architecture
|
|
33
|
+
Sprint: /epics → /stories → /sprint-plan → /jira-sync
|
|
34
|
+
Development: /dev-story ↔ /code-review (loop until done)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Key Skills
|
|
38
|
+
|
|
39
|
+
- **requirements-gathering** - Extract FR/NFR through interviews
|
|
40
|
+
- **prd-writing** - Product requirements documents
|
|
41
|
+
- **architecture-design** - Hexagonal/DDD patterns
|
|
42
|
+
- **story-writing** - User stories with Given/When/Then AC
|
|
43
|
+
- **dev-story** - Red-green-refactor implementation cycle
|
|
44
|
+
- **jira-integration** - Bidirectional sync with Jira
|
|
45
|
+
|
|
15
46
|
## Quick Start
|
|
16
47
|
|
|
17
48
|
```bash
|
|
@@ -266,6 +297,11 @@ export JIRA_API_TOKEN="your-api-token"
|
|
|
266
297
|
- **npm:** https://www.npmjs.com/package/@comfanion/workflow
|
|
267
298
|
- **GitLab:** https://gitlab.com/comfanion/workflow
|
|
268
299
|
|
|
300
|
+
## Inspired By
|
|
301
|
+
|
|
302
|
+
- **[BMAD Method](https://github.com/bmadcode/BMAD-METHOD)** - Breakthrough Method of Agile AI-Driven Development
|
|
303
|
+
- **[OpenCode](https://github.com/opencode-ai/opencode)** - AI-native code editor
|
|
304
|
+
|
|
269
305
|
## License
|
|
270
306
|
|
|
271
307
|
MIT
|
package/package.json
CHANGED
package/src/build-info.json
CHANGED
package/src/opencode/FLOW.yaml
CHANGED
|
@@ -302,7 +302,7 @@ pipeline:
|
|
|
302
302
|
#
|
|
303
303
|
agents:
|
|
304
304
|
analyst:
|
|
305
|
-
name:
|
|
305
|
+
name: Sara
|
|
306
306
|
title: Business Analyst
|
|
307
307
|
icon: "📊"
|
|
308
308
|
description: Requirements Analyst - extracts FR/NFR through stakeholder interviews
|
|
@@ -323,7 +323,7 @@ agents:
|
|
|
323
323
|
- methodologies
|
|
324
324
|
|
|
325
325
|
pm:
|
|
326
|
-
name:
|
|
326
|
+
name: Dima
|
|
327
327
|
title: Product Manager
|
|
328
328
|
icon: "📋"
|
|
329
329
|
description: Product Manager - creates PRDs, epics, stories, sprint planning, Jira sync
|
|
@@ -371,7 +371,7 @@ agents:
|
|
|
371
371
|
- methodologies
|
|
372
372
|
|
|
373
373
|
dev:
|
|
374
|
-
name:
|
|
374
|
+
name: Rick
|
|
375
375
|
title: Senior Developer
|
|
376
376
|
icon: "💻"
|
|
377
377
|
description: Developer - implements stories following red-green-refactor cycle
|
|
@@ -389,9 +389,25 @@ agents:
|
|
|
389
389
|
- code-review
|
|
390
390
|
- test-design
|
|
391
391
|
|
|
392
|
+
coder:
|
|
393
|
+
name: Morty
|
|
394
|
+
title: Fast Coder
|
|
395
|
+
icon: "⚡"
|
|
396
|
+
description: Fast Coder - quick implementation, bug fixes, code following patterns
|
|
397
|
+
mode: subagent
|
|
398
|
+
hidden: true # Internal subagent, invoked by @dev
|
|
399
|
+
model: anthropic/claude-sonnet-4-20250514
|
|
400
|
+
temperature: 0.1
|
|
401
|
+
file: agents/coder.md
|
|
402
|
+
expertise:
|
|
403
|
+
- Quick implementation
|
|
404
|
+
- Bug fixes
|
|
405
|
+
- Following existing patterns
|
|
406
|
+
personality: Fast, no questions, executes or fails
|
|
407
|
+
|
|
392
408
|
# Supporting Agents (not in main pipeline)
|
|
393
409
|
researcher:
|
|
394
|
-
name:
|
|
410
|
+
name: Kristina
|
|
395
411
|
title: Researcher
|
|
396
412
|
icon: "🔍"
|
|
397
413
|
description: Researcher - conducts technical, market, and domain research
|
|
@@ -412,7 +428,7 @@ agents:
|
|
|
412
428
|
- methodologies
|
|
413
429
|
|
|
414
430
|
change-manager:
|
|
415
|
-
name:
|
|
431
|
+
name: Bruce
|
|
416
432
|
title: Change Manager
|
|
417
433
|
icon: "🔄"
|
|
418
434
|
description: Change Manager - manages documentation change proposals
|
|
@@ -26,7 +26,7 @@ permission:
|
|
|
26
26
|
bash: deny # No bash access
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
<agent id="analyst" name="
|
|
29
|
+
<agent id="analyst" name="Sara" title="Business Analyst" icon="📊">
|
|
30
30
|
|
|
31
31
|
<activation critical="MANDATORY">
|
|
32
32
|
<step n="1">Load persona from this agent file</step>
|
|
@@ -33,7 +33,7 @@ permission:
|
|
|
33
33
|
"cp *": ask # Copies need confirmation
|
|
34
34
|
---
|
|
35
35
|
|
|
36
|
-
<agent id="change-manager" name="
|
|
36
|
+
<agent id="change-manager" name="Bruce" title="Change Manager" icon="🔄">
|
|
37
37
|
|
|
38
38
|
<activation critical="MANDATORY">
|
|
39
39
|
<step n="1">Load persona from this agent file</step>
|
|
@@ -30,7 +30,7 @@ permission:
|
|
|
30
30
|
bash: allow # Full bash for speed
|
|
31
31
|
---
|
|
32
32
|
|
|
33
|
-
<agent id="coder" name="
|
|
33
|
+
<agent id="coder" name="Morty" title="Fast Coder" icon="⚡">
|
|
34
34
|
|
|
35
35
|
<activation critical="MANDATORY">
|
|
36
36
|
<step n="1">Receive task from parent agent or user</step>
|
|
@@ -29,7 +29,7 @@ permission:
|
|
|
29
29
|
webfetch: allow
|
|
30
30
|
---
|
|
31
31
|
|
|
32
|
-
<agent id="dev" name="
|
|
32
|
+
<agent id="dev" name="Rick" title="Senior Developer" icon="💻">
|
|
33
33
|
|
|
34
34
|
<activation critical="MANDATORY">
|
|
35
35
|
<step n="1">Load persona from this agent file</step>
|
|
@@ -34,7 +34,7 @@ permission:
|
|
|
34
34
|
"git log*": allow
|
|
35
35
|
---
|
|
36
36
|
|
|
37
|
-
<agent id="pm" name="
|
|
37
|
+
<agent id="pm" name="Dima" title="Product Manager" icon="📋">
|
|
38
38
|
|
|
39
39
|
<activation critical="MANDATORY">
|
|
40
40
|
<step n="1">Load persona from this agent file</step>
|
|
@@ -38,7 +38,7 @@ permission:
|
|
|
38
38
|
"curl *": ask # HTTP requests need approval
|
|
39
39
|
---
|
|
40
40
|
|
|
41
|
-
<agent id="researcher" name="
|
|
41
|
+
<agent id="researcher" name="Kristina" title="Research Specialist" icon="🔍">
|
|
42
42
|
|
|
43
43
|
<activation critical="MANDATORY">
|
|
44
44
|
<step n="1">Load persona from this agent file</step>
|
package/src/opencode/config.yaml
CHANGED
|
@@ -281,11 +281,15 @@ vectorizer:
|
|
|
281
281
|
- "**/yarn.lock"
|
|
282
282
|
|
|
283
283
|
# Global exclude patterns (applied to ALL indexes, in addition to per-index ignore)
|
|
284
|
+
# Patterns without * are wrapped in **/{pattern}/**
|
|
285
|
+
# NOTE: Dot-folders (.git, .claude, .idea, etc.) are already ignored by default (glob dot:false)
|
|
284
286
|
exclude:
|
|
285
287
|
- node_modules
|
|
286
|
-
-
|
|
287
|
-
-
|
|
288
|
-
-
|
|
288
|
+
- vendor
|
|
289
|
+
- dist
|
|
290
|
+
- build
|
|
291
|
+
- out
|
|
292
|
+
- __pycache__
|
|
289
293
|
|
|
290
294
|
# =============================================================================
|
|
291
295
|
# LSP (Language Server Protocol) - Code Intelligence
|
|
@@ -51,7 +51,10 @@ const DEFAULT_CONFIG = {
|
|
|
51
51
|
docs: { enabled: true, extensions: ['.md', '.mdx', '.txt', '.rst', '.adoc'] },
|
|
52
52
|
config: { enabled: false, extensions: ['.yaml', '.yml', '.json', '.toml', '.ini', '.xml'] },
|
|
53
53
|
},
|
|
54
|
-
exclude: [
|
|
54
|
+
exclude: [
|
|
55
|
+
// Build & deps (dot-folders like .git, .claude, .idea are already ignored by glob default)
|
|
56
|
+
'node_modules', 'vendor', 'dist', 'build', 'out', '__pycache__',
|
|
57
|
+
],
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
interface VectorizerConfig {
|
|
@@ -44,6 +44,7 @@ Prerequisites: Run 'npx @comfanion/workflow index --index <name>' first.`,
|
|
|
44
44
|
limit: tool.schema.number().optional().default(5).describe("Number of results to return (default: 5)"),
|
|
45
45
|
searchAll: tool.schema.boolean().optional().default(false).describe("Search all indexes instead of just one"),
|
|
46
46
|
freshen: tool.schema.boolean().optional().default(true).describe("Auto-update stale files before searching (default: true)"),
|
|
47
|
+
includeArchived: tool.schema.boolean().optional().default(false).describe("Include archived files in results (default: false). Files are archived if in /archive/ folder or have 'archived: true' in frontmatter."),
|
|
47
48
|
},
|
|
48
49
|
|
|
49
50
|
async execute(args, context) {
|
|
@@ -88,7 +89,7 @@ Prerequisites: Run 'npx @comfanion/workflow index --index <name>' first.`,
|
|
|
88
89
|
if (args.freshen !== false) {
|
|
89
90
|
await indexer.freshen()
|
|
90
91
|
}
|
|
91
|
-
const results = await indexer.search(args.query, limit)
|
|
92
|
+
const results = await indexer.search(args.query, limit, args.includeArchived)
|
|
92
93
|
allResults.push(...results.map((r: any) => ({ ...r, _index: idx })))
|
|
93
94
|
await indexer.unloadModel() // Free memory after each index search
|
|
94
95
|
}
|
package/src/vectorizer/index.js
CHANGED
|
@@ -181,6 +181,30 @@ class CodebaseIndexer {
|
|
|
181
181
|
return crypto.createHash('md5').update(content).digest('hex');
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Check if file is archived (should be excluded from default search)
|
|
186
|
+
* Archived if:
|
|
187
|
+
* - Path contains /archive/ folder
|
|
188
|
+
* - File has frontmatter with archived: true
|
|
189
|
+
*/
|
|
190
|
+
isArchived(relPath, content) {
|
|
191
|
+
// Check path
|
|
192
|
+
if (relPath.includes('/archive/') || relPath.startsWith('archive/')) {
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Check frontmatter (YAML between --- markers at start of file)
|
|
197
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
198
|
+
if (frontmatterMatch) {
|
|
199
|
+
const frontmatter = frontmatterMatch[1];
|
|
200
|
+
if (/^archived:\s*true/m.test(frontmatter)) {
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
|
|
184
208
|
async embed(text) {
|
|
185
209
|
const model = await this.loadModel();
|
|
186
210
|
const result = await model(text, { pooling: 'mean', normalize: true });
|
|
@@ -246,6 +270,7 @@ class CodebaseIndexer {
|
|
|
246
270
|
}
|
|
247
271
|
|
|
248
272
|
const chunks = this.chunkCode(content);
|
|
273
|
+
const archived = this.isArchived(relPath, content);
|
|
249
274
|
const data = [];
|
|
250
275
|
|
|
251
276
|
for (let i = 0; i < chunks.length; i++) {
|
|
@@ -254,7 +279,8 @@ class CodebaseIndexer {
|
|
|
254
279
|
file: relPath,
|
|
255
280
|
chunk_index: i,
|
|
256
281
|
content: chunks[i],
|
|
257
|
-
vector: embedding
|
|
282
|
+
vector: embedding,
|
|
283
|
+
archived: archived
|
|
258
284
|
});
|
|
259
285
|
}
|
|
260
286
|
|
|
@@ -279,8 +305,11 @@ class CodebaseIndexer {
|
|
|
279
305
|
|
|
280
306
|
/**
|
|
281
307
|
* Semantic search across indexed codebase
|
|
308
|
+
* @param {string} query - Search query
|
|
309
|
+
* @param {number} limit - Max results (default 5)
|
|
310
|
+
* @param {boolean} includeArchived - Include archived files (default false)
|
|
282
311
|
*/
|
|
283
|
-
async search(query, limit = 5) {
|
|
312
|
+
async search(query, limit = 5, includeArchived = false) {
|
|
284
313
|
const tableName = 'chunks';
|
|
285
314
|
const tables = await this.db.tableNames();
|
|
286
315
|
if (!tables.includes(tableName)) {
|
|
@@ -289,9 +318,18 @@ class CodebaseIndexer {
|
|
|
289
318
|
|
|
290
319
|
const queryEmbedding = await this.embed(query);
|
|
291
320
|
const table = await this.db.openTable(tableName);
|
|
292
|
-
const results = await table.search(queryEmbedding).limit(limit).execute();
|
|
293
321
|
|
|
294
|
-
|
|
322
|
+
// Fetch more results if we need to filter archived
|
|
323
|
+
const fetchLimit = includeArchived ? limit : limit * 3;
|
|
324
|
+
let results = await table.search(queryEmbedding).limit(fetchLimit).execute();
|
|
325
|
+
|
|
326
|
+
// Filter out archived files unless explicitly requested
|
|
327
|
+
if (!includeArchived) {
|
|
328
|
+
results = results.filter(r => !r.archived);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Trim to requested limit
|
|
332
|
+
return results.slice(0, limit);
|
|
295
333
|
}
|
|
296
334
|
|
|
297
335
|
/**
|