@comfanion/workflow 4.36.23 → 4.36.25

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.
@@ -0,0 +1,57 @@
1
+ # {{Unit Name}} Data Model
2
+
3
+ **Version:** 1.0
4
+ **Date:** {{YYYY-MM-DD}}
5
+ **Status:** Active
6
+
7
+ ---
8
+
9
+ ## Design Principles
10
+
11
+ | Principle | Description |
12
+ |-----------|-------------|
13
+ | {{Principle}} | {{Why this matters}} |
14
+
15
+ ---
16
+
17
+ ## Entity Relationship Diagram
18
+
19
+ ```
20
+ {{ASCII or Mermaid diagram}}
21
+ ```
22
+
23
+ ---
24
+
25
+ ## Tables
26
+
27
+ ### {{Table Name}}
28
+
29
+ {{Purpose of this table}}
30
+
31
+ | Field | Type | Constraints | Description |
32
+ |-------|------|-------------|-------------|
33
+ | id | UUID | PK | Primary identifier |
34
+ | {{field}} | {{type}} | {{constraints}} | {{description}} |
35
+
36
+ **Indexes:**
37
+ - `({{fields}})` — {{purpose}}
38
+
39
+ ---
40
+
41
+ ## Relations
42
+
43
+ | Relation | Type | Description |
44
+ |----------|------|-------------|
45
+ | {{table_a}} → {{table_b}} | 1:N | {{description}} |
46
+
47
+ ---
48
+
49
+ ## Status Lifecycle
50
+
51
+ ```
52
+ {{state_a}} ──► {{state_b}} ──► {{state_c}}
53
+ ```
54
+
55
+ | Status | Description | Transitions To |
56
+ |--------|-------------|----------------|
57
+ | {{status}} | {{meaning}} | {{allowed_next}} |
@@ -0,0 +1,85 @@
1
+ # {{Name}}
2
+
3
+ ```yaml
4
+ type: entity
5
+ status: draft | approved
6
+ version: "1.0"
7
+ ```
8
+
9
+ ---
10
+
11
+ ## Overview
12
+
13
+ {{What this entity represents, its role in the domain.}}
14
+
15
+ ---
16
+
17
+ ## Boundaries
18
+
19
+ | Aspect | Details |
20
+ |--------|---------|
21
+ | **Owns** | {{fields, behavior}} |
22
+ | **Part of** | {{parent domain/module path}} |
23
+
24
+ ---
25
+
26
+ ## Data Model
27
+
28
+ | Field | Type | Constraints | Description |
29
+ |-------|------|-------------|-------------|
30
+ | id | UUID | PK | Primary identifier |
31
+ | {{field}} | {{type}} | {{constraints}} | {{description}} |
32
+
33
+ ---
34
+
35
+ ## Relations
36
+
37
+ ```
38
+ {{Entity}} ──► {{Other}} ({{type}})
39
+ {{Entity}} ──< {{Other}} ({{type}})
40
+ ```
41
+
42
+ | Relation | Target | Type | Description |
43
+ |----------|--------|------|-------------|
44
+ | {{name}} | {{target}} | N:1 / 1:N / N:M | {{description}} |
45
+
46
+ ---
47
+
48
+ ## State Machine
49
+
50
+ ```
51
+ {{state_a}} ──► {{state_b}} ──► {{state_c}}
52
+ ```
53
+
54
+ | State | Description | Transitions To |
55
+ |-------|-------------|----------------|
56
+ | {{state}} | {{meaning}} | {{allowed_next}} |
57
+
58
+ ---
59
+
60
+ ## Operations
61
+
62
+ | Operation | Input | Output | Description |
63
+ |-----------|-------|--------|-------------|
64
+ | Create | {{params}} | Entity | {{description}} |
65
+ | {{op}} | {{params}} | {{result}} | {{description}} |
66
+
67
+ **Business Rules:**
68
+ - {{rule}}
69
+
70
+ ---
71
+
72
+ ## Errors
73
+
74
+ | Error | Code | When |
75
+ |-------|------|------|
76
+ | {{Error}} | {{CODE}} | {{condition}} |
77
+
78
+ ---
79
+
80
+ ## References
81
+
82
+ ```
83
+ → Parent: {{parent path}}
84
+ → Related: {{related path}}
85
+ ```
@@ -0,0 +1,42 @@
1
+ # {{Unit Name}} Events
2
+
3
+ **Version:** 1.0
4
+ **Date:** {{YYYY-MM-DD}}
5
+
6
+ ---
7
+
8
+ ## Overview
9
+
10
+ {{Brief description of event patterns in this unit}}
11
+
12
+ ---
13
+
14
+ ## Event Flow
15
+
16
+ ```
17
+ {{ASCII diagram: sources → processing → sinks}}
18
+ ```
19
+
20
+ ---
21
+
22
+ ## Topics
23
+
24
+ ### Produced Events
25
+
26
+ | Topic | Events | Key | Description |
27
+ |-------|--------|-----|-------------|
28
+ | {{topic}} | {{EventType}} | {{partition_key}} | {{description}} |
29
+
30
+ ### Consumed Events
31
+
32
+ | Topic | Events | Source |
33
+ |-------|--------|--------|
34
+ | {{topic}} | {{EventType}} | {{source_system}} |
35
+
36
+ ---
37
+
38
+ ## Schema Files
39
+
40
+ | Schema | Description |
41
+ |--------|-------------|
42
+ | [{{event}}.avsc]({{event}}.avsc) | {{description}} |
@@ -0,0 +1,61 @@
1
+ # {{Name}}
2
+
3
+ ```yaml
4
+ type: module | domain | service | entity
5
+ status: draft | approved
6
+ version: "1.0"
7
+ created: {{YYYY-MM-DD}}
8
+ ```
9
+
10
+ ---
11
+
12
+ ## Overview
13
+
14
+ {{One paragraph describing what this unit does, what problem it solves, and key characteristics.}}
15
+
16
+ **Not responsible for:**
17
+ - {{What this unit explicitly doesn't handle}}
18
+
19
+ ---
20
+
21
+ ## Boundaries
22
+
23
+ | Aspect | Details |
24
+ |--------|---------|
25
+ | **Owns** | {{tables, domain objects, behavior}} |
26
+ | **Uses** | → Unit: `{{dependency}}` ({{purpose}}) |
27
+ | **Provides** | {{APIs, events, services to others}} |
28
+
29
+ ---
30
+
31
+ ## Architecture
32
+
33
+ ```
34
+ {{ASCII diagram showing high-level structure}}
35
+ ```
36
+
37
+ ---
38
+
39
+ ## Documents
40
+
41
+ | Document | Description |
42
+ |----------|-------------|
43
+ | [data-model.md](data-model.md) | Database schema |
44
+ | [api/](api/) | API specifications |
45
+ | [events/](events/) | Event schemas |
46
+
47
+ ## Child Units
48
+
49
+ | Unit | Type | Description |
50
+ |------|------|-------------|
51
+ | [services/{{service}}/](services/{{service}}/) | service | {{description}} |
52
+ | [domains/{{domain}}/](domains/{{domain}}/) | domain | {{description}} |
53
+
54
+ ---
55
+
56
+ ## References
57
+
58
+ ```
59
+ → Architecture: docs/architecture.md
60
+ → Related: modules/{{related}}/ or services/{{related}}/
61
+ ```
@@ -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
  }
@@ -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
- return results;
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
  /**