moflo 4.7.2 → 4.7.4

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.
@@ -333,8 +333,9 @@ function getSecurityStatus() {
333
333
  function getSwarmStatus() {
334
334
  const activityData = readJSON(path.join(CWD, '.claude-flow', 'metrics', 'swarm-activity.json'));
335
335
  if (activityData?.swarm) {
336
+ const count = activityData.swarm.agent_count || 0;
336
337
  return {
337
- activeAgents: activityData.swarm.agent_count || 0,
338
+ activeAgents: Math.min(count, CONFIG.maxAgents),
338
339
  maxAgents: CONFIG.maxAgents,
339
340
  coordinationActive: activityData.swarm.coordination_active || activityData.swarm.active || false,
340
341
  };
@@ -342,10 +343,12 @@ function getSwarmStatus() {
342
343
 
343
344
  const progressData = readJSON(path.join(CWD, '.claude-flow', 'metrics', 'v3-progress.json'));
344
345
  if (progressData?.swarm) {
346
+ const count = progressData.swarm.activeAgents || progressData.swarm.agent_count || 0;
347
+ const max = progressData.swarm.totalAgents || CONFIG.maxAgents;
345
348
  return {
346
- activeAgents: progressData.swarm.activeAgents || progressData.swarm.agent_count || 0,
347
- maxAgents: progressData.swarm.totalAgents || CONFIG.maxAgents,
348
- coordinationActive: progressData.swarm.active || (progressData.swarm.activeAgents > 0),
349
+ activeAgents: Math.min(count, max),
350
+ maxAgents: max,
351
+ coordinationActive: progressData.swarm.active || (count > 0),
349
352
  };
350
353
  }
351
354
 
@@ -0,0 +1,577 @@
1
+ ---
2
+ name: flo
3
+ description: MoFlo ticket workflow - analyze and execute GitHub issues
4
+ arguments: "[options] <issue-number | title>"
5
+ ---
6
+
7
+ # /flo - MoFlo Ticket Workflow
8
+
9
+ Research, create tickets for, and execute GitHub issues automatically.
10
+
11
+ **Arguments:** $ARGUMENTS
12
+
13
+ ## Usage
14
+
15
+ ```
16
+ /flo <issue-number> # Full workflow with SWARM (default)
17
+ /flo -t <issue-number> # Ticket only: research and update ticket, then STOP
18
+ /flo -t <title> # Create a NEW ticket with description, acceptance criteria, test cases
19
+ /flo --ticket <issue-number|title> # Same as -t
20
+ /flo -r <issue-number> # Research only: analyze issue, output findings
21
+ /flo --research <issue-number> # Same as -r
22
+ ```
23
+
24
+ Also available as `/fl` (shorthand alias).
25
+
26
+ ### Execution Mode (how work is done)
27
+
28
+ ```
29
+ /flo 123 # SWARM mode (default) - multi-agent coordination
30
+ /flo -s 123 # SWARM mode (explicit)
31
+ /flo --swarm 123 # Same as -s
32
+ /flo -h 123 # HIVE-MIND mode - consensus-based coordination
33
+ /flo --hive 123 # Same as -h
34
+ /flo -n 123 # NORMAL mode - single Claude, no agents
35
+ /flo --normal 123 # Same as -n
36
+ ```
37
+
38
+ ### Epic Handling
39
+
40
+ ```
41
+ /flo 42 # If #42 is an epic, processes all stories sequentially
42
+ ```
43
+
44
+ **Epic Detection:** An issue is automatically detected as an epic if ANY of these are true:
45
+ - Has a label matching: `epic`, `tracking`, `parent`, or `umbrella` (case-insensitive)
46
+ - Body contains `## Stories` or `## Tasks` sections
47
+ - Body has checklist-linked issues: `- [ ] #123`
48
+ - Body has numbered issue references: `1. #123`
49
+ - The issue has GitHub sub-issues (via `subIssues` API field)
50
+
51
+ **Sequential Processing:** When an epic is selected:
52
+ 1. List all child stories/tasks (from checklist or linked issues)
53
+ 2. Process each story **one at a time** in order
54
+ 3. Each story goes through the full workflow (research -> ticket -> implement -> test -> PR)
55
+ 4. After each story's PR is created, move to the next story
56
+ 5. Continue until all stories are complete
57
+
58
+ ### Combined Examples
59
+
60
+ ```
61
+ /flo 123 # Swarm + full workflow (default) - includes ALL tests
62
+ /flo 42 # If #42 is epic, processes stories sequentially
63
+ /flo -t 123 # Swarm + ticket only (no implementation)
64
+ /flo -h -t 123 # Hive-mind + ticket only
65
+ /flo -n -r 123 # Normal + research only
66
+ /flo --swarm --ticket 123 # Explicit swarm + ticket only
67
+ /flo -n 123 # Normal + full workflow (still runs all tests)
68
+ ```
69
+
70
+ ## SWARM IS MANDATORY BY DEFAULT
71
+
72
+ Even if a task "looks simple", you MUST use swarm coordination unless
73
+ the user explicitly passes -n/--normal. "Simple" is a trap. Tasks have
74
+ hidden complexity. Swarm catches it.
75
+
76
+ THE ONLY WAY TO SKIP SWARM: User passes -n or --normal explicitly.
77
+
78
+ ## COMPREHENSIVE TESTING REQUIREMENT
79
+
80
+ ALL tests MUST pass BEFORE PR creation - NO EXCEPTIONS.
81
+ - Unit Tests: MANDATORY for all new/modified code
82
+ - Integration Tests: MANDATORY for API endpoints and services
83
+ - E2E Tests: MANDATORY for user-facing features
84
+ PR CANNOT BE CREATED until all relevant tests pass.
85
+
86
+ ## Workflow Overview
87
+
88
+ ```
89
+ Research -> Ticket -> Execute -> Testing -> Simplify -> PR+Done
90
+
91
+ Research: Fetch issue, search memory, read guidance, find files
92
+ Ticket: Create or update GitHub issue with description, acceptance criteria, test cases
93
+ Execute: Assign self, create branch, implement changes
94
+ Testing: Unit + Integration + E2E tests (ALL MUST PASS - gate)
95
+ Simplify: Run /simplify on changed code (gate - must run before PR)
96
+ PR+Done: Create PR, update issue status, store learnings
97
+ ```
98
+
99
+ ### Workflow Gates
100
+
101
+ | Gate | Requirement | Blocked Action |
102
+ |------|-------------|----------------|
103
+ | **Testing Gate** | Unit + Integration + E2E must pass | PR creation |
104
+ | **Simplification Gate** | /simplify must run on changed files | PR creation |
105
+
106
+ ### Execution Mode (applies to all phases)
107
+
108
+ | Mode | Description |
109
+ |------|-------------|
110
+ | **SWARM** (default) | Multi-agent via Task tool: researcher, coder, tester, reviewer |
111
+ | **HIVE-MIND** (-h) | Consensus-based coordination for architecture decisions |
112
+ | **NORMAL** (-n) | Single Claude, no agent spawning. Only when user explicitly requests. |
113
+
114
+ ## Phase 1: Research (-r or default first step)
115
+
116
+ ### 1.1 Fetch Issue Details
117
+ ```bash
118
+ gh issue view <issue-number> --json number,title,body,labels,state,assignees,comments,milestone
119
+ ```
120
+
121
+ ### 1.2 Check Ticket Status
122
+ Look for `## Acceptance Criteria` marker in issue body.
123
+ - **If present**: Ticket already enhanced, skip to execute or confirm
124
+ - **If absent**: Proceed with research and ticket update
125
+
126
+ ### 1.3 Search Memory FIRST
127
+ ALWAYS search memory BEFORE reading guidance or docs files.
128
+ Memory has file paths, context, and patterns - often all you need.
129
+ Only read guidance files if memory search returns zero relevant results.
130
+
131
+ ```bash
132
+ npx flo memory search --query "<issue title keywords>" --namespace patterns
133
+ npx flo memory search --query "<domain keywords>" --namespace guidance
134
+ ```
135
+
136
+ Or via MCP: `mcp__claude-flow__memory_search`
137
+
138
+ ### 1.4 Read Guidance Docs (ONLY if memory insufficient)
139
+ **Only if memory search returned < 3 relevant results**, read guidance files:
140
+ - Bug -> testing patterns, error handling
141
+ - Feature -> domain model, architecture
142
+ - UI -> frontend patterns, components
143
+
144
+ ### 1.5 Research Codebase
145
+ Use Task tool with Explore agent to find:
146
+ - Affected files and their current state
147
+ - Related code and dependencies
148
+ - Existing patterns to follow
149
+ - Test coverage gaps
150
+
151
+ ## Phase 2: Ticket (-t creates or updates a ticket)
152
+
153
+ When given an issue number, `-t` enhances the existing ticket. When given a title (non-numeric argument), `-t` creates a new GitHub issue. Either way, the ticket MUST include all three of the following sections.
154
+
155
+ ### 2.0 Complexity Assessment (MANDATORY before building ticket)
156
+
157
+ After research, assess the complexity of the work. This determines whether the issue stays as a single ticket or gets promoted to an epic with sub-issues.
158
+
159
+ **Complexity Signals — count how many apply:**
160
+
161
+ | Signal | Weight | Example |
162
+ |--------|--------|---------|
163
+ | Multiple files changed (5+) | +2 | Touches models, API, tests, docs, config |
164
+ | New module or package | +2 | Requires new directory structure |
165
+ | Cross-cutting concern | +2 | Auth, logging, error handling across layers |
166
+ | Database/schema changes | +2 | Migrations, new tables, index changes |
167
+ | Multiple independent work streams | +3 | Frontend + backend + infra changes |
168
+ | External API integration | +1 | Third-party service, webhook, OAuth |
169
+ | Breaking change / migration | +2 | Requires deprecation, data migration |
170
+ | Significant test surface | +1 | Needs 10+ new test cases across categories |
171
+ | Security implications | +1 | Authentication, authorization, input validation |
172
+ | UI + backend changes together | +2 | Full-stack feature spanning layers |
173
+
174
+ **Complexity Thresholds:**
175
+
176
+ | Score | Classification | Action |
177
+ |-------|---------------|--------|
178
+ | 0–3 | **Simple** | Single ticket — proceed normally |
179
+ | 4–6 | **Moderate** | Single ticket — flag in description that it may benefit from splitting |
180
+ | 7+ | **Complex** | **PROMOTE TO EPIC** — decompose into sub-issues |
181
+
182
+ **When promoting to epic:**
183
+
184
+ 1. Decompose the work into 2–6 independent, shippable stories
185
+ 2. Each story should be completable in a single PR
186
+ 3. Stories should have clear boundaries (one concern per story)
187
+ 4. Order stories by dependency (independent ones first)
188
+ 5. Create each story as a GitHub issue with its own Description, Acceptance Criteria, and Test Cases
189
+ 6. Create or convert the parent issue into an epic with a `## Stories` checklist
190
+
191
+ ```javascript
192
+ // Complexity assessment pseudocode
193
+ function assessComplexity(research) {
194
+ let score = 0;
195
+ if (research.affectedFiles.length >= 5) score += 2;
196
+ if (research.requiresNewModule) score += 2;
197
+ if (research.crossCutting) score += 2;
198
+ if (research.schemaChanges) score += 2;
199
+ if (research.independentWorkStreams >= 2) score += 3;
200
+ if (research.externalAPIs) score += 1;
201
+ if (research.breakingChanges) score += 2;
202
+ if (research.estimatedTestCases >= 10) score += 1;
203
+ if (research.securityImplications) score += 1;
204
+ if (research.fullStack) score += 2;
205
+ return score;
206
+ }
207
+ ```
208
+
209
+ ### 2.0.1 Epic Decomposition (when score >= 7)
210
+
211
+ When complexity warrants an epic, decompose into stories:
212
+
213
+ ```bash
214
+ # Step 1: Create each sub-issue
215
+ gh issue create --title "Story: <story-title>" --body "<## Description + ## Acceptance Criteria + ## Suggested Test Cases>" --label "story"
216
+ # Capture the new issue number from output
217
+
218
+ # Step 2: Repeat for all stories (2-6 stories typically)
219
+
220
+ # Step 3: Build the epic body with checklist referencing ALL story issue numbers
221
+ # Step 4: If updating an existing issue, convert it to epic:
222
+ gh issue edit <parent-number> --add-label "epic" --body "<epic body with ## Stories checklist>"
223
+
224
+ # Step 5: If creating new, create the epic:
225
+ gh issue create --title "Epic: <title>" --label "epic" --body "<epic body>"
226
+ ```
227
+
228
+ **Epic body format (MANDATORY — this is how tracking works):**
229
+
230
+ ```markdown
231
+ ## Overview
232
+ <High-level description of the epic goal>
233
+
234
+ ## Stories
235
+
236
+ - [ ] #<story-1-number> <story-1-title>
237
+ - [ ] #<story-2-number> <story-2-title>
238
+ - [ ] #<story-3-number> <story-3-title>
239
+
240
+ ## Complexity Assessment
241
+ Score: <N>/20 — <Simple|Moderate|Complex>
242
+ Signals: <list of signals that triggered>
243
+ ```
244
+
245
+ The `## Stories` checklist with `- [ ] #<number>` format is **mandatory** — this is what enables:
246
+ - Epic detection by the `/flo` skill
247
+ - Story extraction for sequential processing
248
+ - Progress tracking via checked/unchecked items
249
+
250
+ ### 2.1 Build Ticket Content
251
+ Compile research into a well-structured ticket. The issue MUST include all three of the following sections:
252
+
253
+ **Detailed Description** — Clear, thorough explanation of what needs to be done and why. Include:
254
+ - Root cause analysis (bugs) or approach rationale (features)
255
+ - Impact and risk factors
256
+ - Affected files (with line numbers), new files, deletions
257
+ - Implementation plan: numbered steps with clear actions, dependencies, decision points
258
+
259
+ **Acceptance Criteria** — Specific, testable conditions that must be true for this issue to be considered complete. Write as a checklist:
260
+ - [ ] Criterion 1 (e.g., "API returns 200 with valid token")
261
+ - [ ] Criterion 2 (e.g., "Error message shown when input exceeds 255 chars")
262
+ - [ ] ...each criterion must be independently verifiable
263
+
264
+ **Suggested Test Cases** — Concrete test scenarios covering happy path, edge cases, and error conditions:
265
+ - Test case 1: description, input, expected output
266
+ - Test case 2: description, input, expected output
267
+ - Include unit, integration, and E2E test suggestions as appropriate
268
+
269
+ ### 2.2 Create or Update GitHub Issue
270
+
271
+ **If issue number was given** (update existing):
272
+ ```bash
273
+ gh issue edit <issue-number> --body "<original body + ## Description + ## Acceptance Criteria + ## Suggested Test Cases>"
274
+ gh issue comment <issue-number> --body "Ticket enhanced with description, acceptance criteria, and test cases. Ready for execution."
275
+ ```
276
+
277
+ **If title was given** (create new):
278
+ ```bash
279
+ gh issue create --title "<title>" --body "<## Description + ## Acceptance Criteria + ## Suggested Test Cases>"
280
+ ```
281
+ Print the new issue URL so the user can see it.
282
+
283
+ ## Phase 3: Execute (default, runs automatically after ticket)
284
+
285
+ ### 3.1 Assign Issue and Update Status
286
+ ```bash
287
+ gh issue edit <issue-number> --add-assignee @me
288
+ gh issue edit <issue-number> --add-label "in-progress"
289
+ ```
290
+
291
+ ### 3.2 Create Branch
292
+ ```bash
293
+ git checkout main && git pull origin main
294
+ git checkout -b <type>/<issue-number>-<short-desc>
295
+ ```
296
+ Types: `feature/`, `fix/`, `refactor/`, `docs/`
297
+
298
+ ### 3.3 Implement
299
+ Follow the implementation plan from the ticket. No prompts - execute all steps.
300
+
301
+ ## Phase 4: Testing (MANDATORY GATE)
302
+
303
+ This is NOT optional. ALL applicable test types must pass for the change type.
304
+ WORKFLOW STOPS HERE until tests pass. No shortcuts. No exceptions.
305
+
306
+ ### 4.1 Write and Run Tests
307
+ Write unit, integration, and E2E tests as appropriate for the change type.
308
+ Use the project's existing test runner and patterns.
309
+
310
+ ### 4.2 Test Auto-Fix Loop
311
+ If any tests fail, enter the auto-fix loop (max 3 retries OR 10 minutes):
312
+ 1. Run all tests
313
+ 2. If ALL pass -> proceed to simplification
314
+ 3. If ANY fail: analyze failure, fix test or implementation code, retry
315
+ 4. If retries exhausted -> STOP and report to user
316
+
317
+ ## Phase 4.5: Code Simplification (MANDATORY)
318
+
319
+ The built-in /simplify command reviews ALL changed code for:
320
+ - Reuse opportunities and code quality
321
+ - Efficiency improvements
322
+ - Consistency with existing codebase patterns
323
+ - Preserves ALL functionality - no behavior changes
324
+
325
+ If /simplify makes changes -> re-run tests to confirm nothing broke.
326
+ If re-tests fail -> revert changes, proceed with original code.
327
+
328
+ ## Phase 5: Commit and PR (only after tests pass)
329
+
330
+ ### 5.1 Commit
331
+ ```bash
332
+ git add <specific files>
333
+ git commit -m "type(scope): description
334
+
335
+ Closes #<issue-number>
336
+
337
+ Co-Authored-By: Claude <noreply@anthropic.com>"
338
+ ```
339
+
340
+ ### 5.2 Create PR
341
+ ```bash
342
+ git push -u origin <branch-name>
343
+ gh pr create --title "type(scope): description" --body "## Summary
344
+ <brief description>
345
+
346
+ ## Changes
347
+ <bullet list>
348
+
349
+ ## Testing
350
+ - [x] Unit tests pass
351
+ - [x] Integration tests pass
352
+ - [x] E2E tests pass
353
+ - [ ] Manual testing done
354
+
355
+ Closes #<issue-number>"
356
+ ```
357
+
358
+ ### 5.3 Update Issue Status
359
+ ```bash
360
+ gh issue edit <issue-number> --remove-label "in-progress" --add-label "ready-for-review"
361
+ gh issue comment <issue-number> --body "PR created: <pr-url>"
362
+ ```
363
+
364
+ ## Epic Handling
365
+
366
+ ### Detecting Epics
367
+
368
+ An issue is an **epic** if:
369
+ 1. It has the `epic` label, OR
370
+ 2. Its body contains `## Stories` or `## Tasks` sections, OR
371
+ 3. It has linked child issues (via `- [ ] #123` checklist format)
372
+
373
+ ### Epic Processing Flow
374
+
375
+ 1. DETECT EPIC - Check labels, parse body for ## Stories / ## Tasks, extract issue references
376
+ 2. LIST ALL STORIES - Extract from checklist, order top-to-bottom as listed
377
+ 3. SEQUENTIAL PROCESSING - For each story:
378
+ a. Run full /flo workflow (research -> ticket -> implement -> test -> PR)
379
+ b. After PR is created, **check off the story** in the epic body
380
+ c. Move to the next unchecked story
381
+ 4. COMPLETION - All stories checked off, epic marked as ready-for-review
382
+
383
+ ONE STORY AT A TIME - NO PARALLEL STORY EXECUTION.
384
+ Each story must complete (PR created) before starting next.
385
+
386
+ ### Epic Checklist Tracking (MANDATORY)
387
+
388
+ After each story's PR is created, update the epic body to check off that story:
389
+
390
+ ```bash
391
+ # 1. Fetch current epic body
392
+ EPIC_BODY=$(gh issue view <epic-number> --json body -q '.body')
393
+
394
+ # 2. Replace "- [ ] #<story-number>" with "- [x] #<story-number>"
395
+ UPDATED_BODY=$(echo "$EPIC_BODY" | sed 's/- \[ \] #<story-number>/- [x] #<story-number>/')
396
+
397
+ # 3. Update the epic
398
+ gh issue edit <epic-number> --body "$UPDATED_BODY"
399
+
400
+ # 4. Comment on the epic with progress
401
+ gh issue comment <epic-number> --body "✅ Story #<story-number> completed — PR: <pr-url>"
402
+ ```
403
+
404
+ This applies to ALL epics, regardless of how they were created:
405
+ - Epics created by `/flo -t` complexity promotion
406
+ - Epics created manually by users
407
+ - Epics detected from existing issues
408
+
409
+ The checklist state (`[ ]` vs `[x]`) is the **single source of truth** for epic progress.
410
+
411
+ ### Epic Detection Code
412
+
413
+ ```javascript
414
+ function isEpic(issue) {
415
+ // Label-based detection (case-insensitive)
416
+ const epicLabels = ['epic', 'tracking', 'parent', 'umbrella'];
417
+ if (issue.labels?.some(l => epicLabels.includes(l.name.toLowerCase()))) return true;
418
+ // Section-based detection
419
+ if (issue.body?.includes('## Stories') || issue.body?.includes('## Tasks')) return true;
420
+ // Checklist-linked issues: - [ ] #123 or - [x] #123
421
+ if (/- \[[ x]\] #\d+/.test(issue.body)) return true;
422
+ // Numbered issue references: 1. #123
423
+ if (/\d+\.\s+#\d+/.test(issue.body)) return true;
424
+ // GitHub sub-issues API
425
+ if (issue.subIssues?.length > 0) return true;
426
+ return false;
427
+ }
428
+
429
+ function extractStories(epicBody) {
430
+ const stories = [];
431
+ // Checklist format: - [ ] #123
432
+ const checklistPattern = /- \[[ ]\] #(\d+)/g;
433
+ let match;
434
+ while ((match = checklistPattern.exec(epicBody)) !== null) {
435
+ stories.push(parseInt(match[1]));
436
+ }
437
+ // Numbered format: 1. #123
438
+ if (stories.length === 0) {
439
+ const numberedPattern = /\d+\.\s+#(\d+)/g;
440
+ while ((match = numberedPattern.exec(epicBody)) !== null) {
441
+ stories.push(parseInt(match[1]));
442
+ }
443
+ }
444
+ return stories;
445
+ }
446
+ ```
447
+
448
+ ## Parse Arguments
449
+
450
+ ```javascript
451
+ const args = "$ARGUMENTS".trim().split(/\s+/);
452
+ let workflowMode = "full"; // full, ticket, research
453
+ let execMode = "swarm"; // swarm (default), hive, normal
454
+ let issueNumber = null;
455
+ let titleWords = [];
456
+
457
+ for (let i = 0; i < args.length; i++) {
458
+ const arg = args[i];
459
+
460
+ // Workflow mode (what to do)
461
+ if (arg === "-t" || arg === "--ticket") {
462
+ workflowMode = "ticket";
463
+ } else if (arg === "-r" || arg === "--research") {
464
+ workflowMode = "research";
465
+ }
466
+
467
+ // Execution mode (how to do it)
468
+ else if (arg === "-s" || arg === "--swarm") {
469
+ execMode = "swarm";
470
+ } else if (arg === "-h" || arg === "--hive") {
471
+ execMode = "hive";
472
+ } else if (arg === "-n" || arg === "--normal") {
473
+ execMode = "normal";
474
+ }
475
+
476
+ // Issue number or title text
477
+ else if (/^\d+$/.test(arg)) {
478
+ issueNumber = arg;
479
+ } else {
480
+ // Non-flag, non-numeric argument — collect as title words
481
+ titleWords.push(arg);
482
+ }
483
+ }
484
+
485
+ // In ticket mode, a title can be given instead of an issue number
486
+ let ticketTitle = titleWords.join(" ");
487
+ if (!issueNumber && !ticketTitle) {
488
+ throw new Error("Issue number or title required. Usage: /flo <issue-number | title>");
489
+ }
490
+ if (!issueNumber && workflowMode !== "ticket") {
491
+ throw new Error("Issue number required for full/research mode. Use -t for new tickets.");
492
+ }
493
+
494
+ // Log execution mode to prevent silent skipping
495
+ console.log("Execution mode: " + execMode.toUpperCase());
496
+ if (execMode === "swarm") {
497
+ console.log("SWARM MODE: Will spawn agents via Task tool. Do NOT skip this.");
498
+ }
499
+ console.log("TESTING: Unit + Integration + E2E tests REQUIRED before PR.");
500
+ console.log("SIMPLIFY: /simplify command runs on changed code before PR.");
501
+ ```
502
+
503
+ ## Execution Flow
504
+
505
+ ### Workflow Modes (what to do)
506
+
507
+ | Mode | Command | Steps | Stops After |
508
+ |------|---------|-------|-------------|
509
+ | **Full** (default) | `/flo 123` | Research -> Ticket -> Implement -> Test -> Simplify -> PR | PR created |
510
+ | **Epic** | `/flo 42` (epic) | For each story: Full workflow sequentially | All story PRs created |
511
+ | **Ticket** | `/flo -t 123` | Research -> Ticket | Issue updated |
512
+ | **Research** | `/flo -r 123` | Research | Findings output |
513
+
514
+ ### Execution Modes (how to do it)
515
+
516
+ | Mode | Flag | Description | When to Use |
517
+ |------|------|-------------|-------------|
518
+ | **Swarm** (DEFAULT) | `-s`, `--swarm` | Multi-agent via Task tool | Always, unless explicitly overridden |
519
+ | **Hive-Mind** | `-h`, `--hive` | Consensus-based coordination | Architecture decisions, tradeoffs |
520
+ | **Normal** | `-n`, `--normal` | Single Claude, no agents | User explicitly wants simple mode |
521
+
522
+ ## Execution Mode Details
523
+
524
+ ### SWARM Mode (Default) - ALWAYS USE UNLESS TOLD OTHERWISE
525
+
526
+ You MUST use the Task tool to spawn agents. No exceptions.
527
+
528
+ **Swarm spawns these agents via Task tool:**
529
+ - `researcher` - Analyzes issue, searches memory, finds patterns
530
+ - `coder` - Implements changes following plan
531
+ - `tester` - Writes and runs tests
532
+ - `/simplify` - Built-in command that reviews changed code before PR
533
+ - `reviewer` - Reviews code before PR
534
+
535
+ **Swarm execution pattern:**
536
+ ```javascript
537
+ // 1. Create task list FIRST
538
+ TaskCreate({ subject: "Research issue #123", ... })
539
+ TaskCreate({ subject: "Implement changes", ... })
540
+ TaskCreate({ subject: "Test implementation", ... })
541
+ TaskCreate({ subject: "Run /simplify on changed files", ... })
542
+ TaskCreate({ subject: "Review and PR", ... })
543
+
544
+ // 2. Init swarm
545
+ Bash("npx flo swarm init --topology hierarchical --max-agents 8 --strategy specialized")
546
+
547
+ // 3. Spawn agents with Task tool (run_in_background: true)
548
+ Task({ prompt: "...", subagent_type: "researcher", run_in_background: true })
549
+ Task({ prompt: "...", subagent_type: "coder", run_in_background: true })
550
+
551
+ // 4. Wait for results, synthesize, continue
552
+ ```
553
+
554
+ ### HIVE-MIND Mode (-h, --hive)
555
+
556
+ Use for consensus-based decisions:
557
+ - Architecture choices
558
+ - Approach tradeoffs
559
+ - Design decisions with multiple valid options
560
+
561
+ ### NORMAL Mode (-n, --normal)
562
+
563
+ **Only when user explicitly requests.** Single Claude execution without agents.
564
+ - Still uses Task tool for tracking
565
+ - Still creates tasks for visibility
566
+ - Just doesn't spawn multiple agents
567
+
568
+ ---
569
+
570
+ **Full mode executes without prompts.** It will:
571
+ 1. Research the issue and codebase
572
+ 2. Enhance the GitHub issue with implementation plan
573
+ 3. Assign issue to self, add "in-progress" label
574
+ 4. Create branch, implement, test
575
+ 5. Run /simplify on changed code, re-test if changes made
576
+ 6. Commit, create PR, update issue status
577
+ 7. Store learnings
@@ -150,7 +150,102 @@ Use Task tool with Explore agent to find:
150
150
 
151
151
  ## Phase 2: Ticket (-t creates or updates a ticket)
152
152
 
153
- When given an issue number, `-t` enhances the existing ticket. When given a title (non-numeric argument), `-t` creates a new GitHub issue. Either way, the ticket MUST include all three of the following sections:
153
+ When given an issue number, `-t` enhances the existing ticket. When given a title (non-numeric argument), `-t` creates a new GitHub issue. Either way, the ticket MUST include all three of the following sections.
154
+
155
+ ### 2.0 Complexity Assessment (MANDATORY before building ticket)
156
+
157
+ After research, assess the complexity of the work. This determines whether the issue stays as a single ticket or gets promoted to an epic with sub-issues.
158
+
159
+ **Complexity Signals — count how many apply:**
160
+
161
+ | Signal | Weight | Example |
162
+ |--------|--------|---------|
163
+ | Multiple files changed (5+) | +2 | Touches models, API, tests, docs, config |
164
+ | New module or package | +2 | Requires new directory structure |
165
+ | Cross-cutting concern | +2 | Auth, logging, error handling across layers |
166
+ | Database/schema changes | +2 | Migrations, new tables, index changes |
167
+ | Multiple independent work streams | +3 | Frontend + backend + infra changes |
168
+ | External API integration | +1 | Third-party service, webhook, OAuth |
169
+ | Breaking change / migration | +2 | Requires deprecation, data migration |
170
+ | Significant test surface | +1 | Needs 10+ new test cases across categories |
171
+ | Security implications | +1 | Authentication, authorization, input validation |
172
+ | UI + backend changes together | +2 | Full-stack feature spanning layers |
173
+
174
+ **Complexity Thresholds:**
175
+
176
+ | Score | Classification | Action |
177
+ |-------|---------------|--------|
178
+ | 0–3 | **Simple** | Single ticket — proceed normally |
179
+ | 4–6 | **Moderate** | Single ticket — flag in description that it may benefit from splitting |
180
+ | 7+ | **Complex** | **PROMOTE TO EPIC** — decompose into sub-issues |
181
+
182
+ **When promoting to epic:**
183
+
184
+ 1. Decompose the work into 2–6 independent, shippable stories
185
+ 2. Each story should be completable in a single PR
186
+ 3. Stories should have clear boundaries (one concern per story)
187
+ 4. Order stories by dependency (independent ones first)
188
+ 5. Create each story as a GitHub issue with its own Description, Acceptance Criteria, and Test Cases
189
+ 6. Create or convert the parent issue into an epic with a `## Stories` checklist
190
+
191
+ ```javascript
192
+ // Complexity assessment pseudocode
193
+ function assessComplexity(research) {
194
+ let score = 0;
195
+ if (research.affectedFiles.length >= 5) score += 2;
196
+ if (research.requiresNewModule) score += 2;
197
+ if (research.crossCutting) score += 2;
198
+ if (research.schemaChanges) score += 2;
199
+ if (research.independentWorkStreams >= 2) score += 3;
200
+ if (research.externalAPIs) score += 1;
201
+ if (research.breakingChanges) score += 2;
202
+ if (research.estimatedTestCases >= 10) score += 1;
203
+ if (research.securityImplications) score += 1;
204
+ if (research.fullStack) score += 2;
205
+ return score;
206
+ }
207
+ ```
208
+
209
+ ### 2.0.1 Epic Decomposition (when score >= 7)
210
+
211
+ When complexity warrants an epic, decompose into stories:
212
+
213
+ ```bash
214
+ # Step 1: Create each sub-issue
215
+ gh issue create --title "Story: <story-title>" --body "<## Description + ## Acceptance Criteria + ## Suggested Test Cases>" --label "story"
216
+ # Capture the new issue number from output
217
+
218
+ # Step 2: Repeat for all stories (2-6 stories typically)
219
+
220
+ # Step 3: Build the epic body with checklist referencing ALL story issue numbers
221
+ # Step 4: If updating an existing issue, convert it to epic:
222
+ gh issue edit <parent-number> --add-label "epic" --body "<epic body with ## Stories checklist>"
223
+
224
+ # Step 5: If creating new, create the epic:
225
+ gh issue create --title "Epic: <title>" --label "epic" --body "<epic body>"
226
+ ```
227
+
228
+ **Epic body format (MANDATORY — this is how tracking works):**
229
+
230
+ ```markdown
231
+ ## Overview
232
+ <High-level description of the epic goal>
233
+
234
+ ## Stories
235
+
236
+ - [ ] #<story-1-number> <story-1-title>
237
+ - [ ] #<story-2-number> <story-2-title>
238
+ - [ ] #<story-3-number> <story-3-title>
239
+
240
+ ## Complexity Assessment
241
+ Score: <N>/20 — <Simple|Moderate|Complex>
242
+ Signals: <list of signals that triggered>
243
+ ```
244
+
245
+ The `## Stories` checklist with `- [ ] #<number>` format is **mandatory** — this is what enables:
246
+ - Epic detection by the `/flo` skill
247
+ - Story extraction for sequential processing
248
+ - Progress tracking via checked/unchecked items
154
249
 
155
250
  ### 2.1 Build Ticket Content
156
251
  Compile research into a well-structured ticket. The issue MUST include all three of the following sections:
@@ -279,12 +374,40 @@ An issue is an **epic** if:
279
374
 
280
375
  1. DETECT EPIC - Check labels, parse body for ## Stories / ## Tasks, extract issue references
281
376
  2. LIST ALL STORIES - Extract from checklist, order top-to-bottom as listed
282
- 3. SEQUENTIAL PROCESSING - For each story: run full /flo workflow, wait for PR, update checklist
283
- 4. COMPLETION - All stories have PRs, epic marked as ready-for-review
377
+ 3. SEQUENTIAL PROCESSING - For each story:
378
+ a. Run full /flo workflow (research -> ticket -> implement -> test -> PR)
379
+ b. After PR is created, **check off the story** in the epic body
380
+ c. Move to the next unchecked story
381
+ 4. COMPLETION - All stories checked off, epic marked as ready-for-review
284
382
 
285
383
  ONE STORY AT A TIME - NO PARALLEL STORY EXECUTION.
286
384
  Each story must complete (PR created) before starting next.
287
385
 
386
+ ### Epic Checklist Tracking (MANDATORY)
387
+
388
+ After each story's PR is created, update the epic body to check off that story:
389
+
390
+ ```bash
391
+ # 1. Fetch current epic body
392
+ EPIC_BODY=$(gh issue view <epic-number> --json body -q '.body')
393
+
394
+ # 2. Replace "- [ ] #<story-number>" with "- [x] #<story-number>"
395
+ UPDATED_BODY=$(echo "$EPIC_BODY" | sed 's/- \[ \] #<story-number>/- [x] #<story-number>/')
396
+
397
+ # 3. Update the epic
398
+ gh issue edit <epic-number> --body "$UPDATED_BODY"
399
+
400
+ # 4. Comment on the epic with progress
401
+ gh issue comment <epic-number> --body "✅ Story #<story-number> completed — PR: <pr-url>"
402
+ ```
403
+
404
+ This applies to ALL epics, regardless of how they were created:
405
+ - Epics created by `/flo -t` complexity promotion
406
+ - Epics created manually by users
407
+ - Epics detected from existing issues
408
+
409
+ The checklist state (`[ ]` vs `[x]`) is the **single source of truth** for epic progress.
410
+
288
411
  ### Epic Detection Code
289
412
 
290
413
  ```javascript
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  /**
3
3
  * MoFlo Project Setup
4
4
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moflo",
3
- "version": "4.7.2",
3
+ "version": "4.7.4",
4
4
  "description": "MoFlo — AI agent orchestration for Claude Code. Forked from ruflo/claude-flow with patches applied to source, plus feature-level orchestration.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -61,6 +61,7 @@
61
61
  },
62
62
  "dependencies": {
63
63
  "@ruvector/learning-wasm": "^0.1.29",
64
+ "js-yaml": "^4.1.1",
64
65
  "semver": "^7.6.0",
65
66
  "sql.js": "^1.12.0",
66
67
  "zod": "^3.22.4"
@@ -229,7 +229,7 @@ const listCommand = {
229
229
  }
230
230
  // Format for display
231
231
  const displayAgents = result.agents.map(agent => ({
232
- id: agent.id,
232
+ id: agent.agentId,
233
233
  type: agent.agentType,
234
234
  status: agent.status,
235
235
  created: new Date(agent.createdAt).toLocaleTimeString(),
@@ -239,7 +239,7 @@ const listCommand = {
239
239
  }));
240
240
  output.printTable({
241
241
  columns: [
242
- { key: 'id', header: 'ID', width: 20 },
242
+ { key: 'id', header: 'ID', width: 35 },
243
243
  { key: 'type', header: 'Type', width: 15 },
244
244
  { key: 'status', header: 'Status', width: 12, format: formatStatus },
245
245
  { key: 'created', header: 'Created', width: 12 },
@@ -540,13 +540,17 @@ const poolCommand = {
540
540
  `Auto-Scale: ${result.autoScale ? 'Yes' : 'No'}`,
541
541
  `Utilization: ${(utilization * 100).toFixed(1)}%`
542
542
  ].join('\n'), 'Agent Pool');
543
- const agents = result.agents ?? [];
543
+ const agents = (result.agents ?? []).map((a) => ({
544
+ id: a.agentId || a.id,
545
+ type: a.agentType || a.type,
546
+ status: a.status,
547
+ }));
544
548
  if (agents.length > 0) {
545
549
  output.writeln();
546
550
  output.writeln(output.bold('Pool Agents'));
547
551
  output.printTable({
548
552
  columns: [
549
- { key: 'id', header: 'ID', width: 20 },
553
+ { key: 'id', header: 'ID', width: 35 },
550
554
  { key: 'type', header: 'Type', width: 15 },
551
555
  { key: 'status', header: 'Status', width: 12, format: formatStatus }
552
556
  ],
@@ -370,9 +370,9 @@ const initCommand = {
370
370
  const config = {
371
371
  topology: topology || 'hierarchical-mesh',
372
372
  consensus: consensus || 'byzantine',
373
- maxAgents: ctx.flags.maxAgents || 15,
373
+ maxAgents: (ctx.flags.maxAgents ?? ctx.flags['max-agents']) || 15,
374
374
  persist: ctx.flags.persist,
375
- memoryBackend: ctx.flags.memoryBackend || 'hybrid'
375
+ memoryBackend: (ctx.flags.memoryBackend ?? ctx.flags['memory-backend']) || 'hybrid'
376
376
  };
377
377
  output.writeln();
378
378
  output.writeln(output.bold('Initializing Hive Mind'));
@@ -1095,9 +1095,9 @@ const shutdownCommand = {
1095
1095
  spinner.succeed('Hive mind shutdown complete');
1096
1096
  output.writeln();
1097
1097
  output.printList([
1098
- `Agents terminated: ${result.agentsTerminated}`,
1098
+ `Agents terminated: ${result.agentsTerminated ?? 0}`,
1099
1099
  `State saved: ${result.stateSaved ? 'Yes' : 'No'}`,
1100
- `Shutdown time: ${result.shutdownTime}`
1100
+ `Shutdown time: ${result.shutdownTime ?? 'N/A'}`
1101
1101
  ]);
1102
1102
  return { success: true, data: result };
1103
1103
  }
@@ -178,28 +178,15 @@ const initAction = async (ctx) => {
178
178
  output.printWarning(`MoFlo setup: ${e instanceof Error ? e.message : String(e)}`);
179
179
  }
180
180
  // ── End MoFlo Setup ────────────────────────────────────────────────
181
- // Check if already initialized
181
+ // Check if already initialized — allow re-running to update/merge
182
182
  const initialized = isInitialized(cwd);
183
183
  const hasExisting = initialized.claude || initialized.claudeFlow;
184
184
  if (hasExisting && !force) {
185
- output.printWarning('MoFlo appears to be already initialized');
185
+ output.printInfo('MoFlo is already initialized updating configuration');
186
186
  if (initialized.claude)
187
187
  output.printInfo(' Found: .claude/settings.json');
188
188
  if (initialized.claudeFlow)
189
189
  output.printInfo(' Found: .claude-flow/config.yaml');
190
- output.printInfo('Use --force to reinitialize');
191
- if (ctx.interactive) {
192
- const proceed = await confirm({
193
- message: 'Do you want to reinitialize? This will overwrite existing configuration.',
194
- default: false,
195
- });
196
- if (!proceed) {
197
- return { success: true, message: 'Initialization cancelled' };
198
- }
199
- }
200
- else {
201
- return { success: false, exitCode: 1, message: 'Already initialized' };
202
- }
203
190
  }
204
191
  output.writeln();
205
192
  output.writeln(output.bold('Initializing MoFlo V4'));
@@ -519,7 +519,8 @@ const stopCommand = {
519
519
  const swarmId = ctx.args[0];
520
520
  const force = ctx.flags.force;
521
521
  if (!swarmId) {
522
- output.printError('Swarm ID is required');
522
+ output.printError('Swarm ID is required. Usage: moflo swarm stop <swarm-id>');
523
+ output.printInfo('Run "moflo swarm status" to find the active swarm ID');
523
524
  return { success: false, exitCode: 1 };
524
525
  }
525
526
  if (ctx.interactive && !force) {
@@ -567,7 +568,8 @@ const scaleCommand = {
567
568
  const targetAgents = ctx.flags.agents;
568
569
  const agentType = ctx.flags.type;
569
570
  if (!swarmId) {
570
- output.printError('Swarm ID is required');
571
+ output.printError('Swarm ID is required. Usage: moflo swarm scale <swarm-id>');
572
+ output.printInfo('Run "moflo swarm status" to find the active swarm ID');
571
573
  return { success: false, exitCode: 1 };
572
574
  }
573
575
  if (!targetAgents) {
@@ -4,7 +4,16 @@
4
4
  */
5
5
  import * as fs from 'fs';
6
6
  import * as path from 'path';
7
- import yaml from 'js-yaml';
7
+ let yaml;
8
+ try {
9
+ yaml = await import('js-yaml');
10
+ if (yaml.default)
11
+ yaml = yaml.default;
12
+ }
13
+ catch {
14
+ // js-yaml not installed — YAML config files will fall back to JSON parsing
15
+ yaml = null;
16
+ }
8
17
  // ============================================================================
9
18
  // Defaults
10
19
  // ============================================================================
@@ -181,9 +190,17 @@ export function loadMofloConfig(projectRoot) {
181
190
  }
182
191
  try {
183
192
  const content = fs.readFileSync(configFile.path, 'utf-8');
184
- const raw = configFile.format === 'json'
185
- ? JSON.parse(content)
186
- : yaml.load(content);
193
+ let raw;
194
+ if (configFile.format === 'json') {
195
+ raw = JSON.parse(content);
196
+ }
197
+ else if (yaml) {
198
+ raw = yaml.load(content);
199
+ }
200
+ else {
201
+ // js-yaml not available — cannot parse YAML config
202
+ throw new Error('js-yaml is required to parse moflo.yaml. Install it: npm install js-yaml');
203
+ }
187
204
  if (!raw || typeof raw !== 'object') {
188
205
  return { ...DEFAULT_CONFIG, project: { name: path.basename(root) } };
189
206
  }
@@ -11,6 +11,7 @@
11
11
  */
12
12
  import * as fs from 'fs';
13
13
  import * as path from 'path';
14
+ import { fileURLToPath } from 'url';
14
15
  // ============================================================================
15
16
  // Init
16
17
  // ============================================================================
@@ -429,17 +430,29 @@ function generateSkill(root, force) {
429
430
  }
430
431
  // Copy static SKILL.md from moflo package instead of generating it
431
432
  let skillContent = '';
433
+ // Resolve this file's directory in ESM-safe way
434
+ let thisDir;
435
+ try {
436
+ thisDir = path.dirname(fileURLToPath(import.meta.url));
437
+ }
438
+ catch {
439
+ // Fallback for CJS or environments where import.meta.url is unavailable
440
+ thisDir = typeof __dirname !== 'undefined' ? __dirname : '';
441
+ }
432
442
  const staticSkillCandidates = [
433
- // Installed via npm
443
+ // Installed via npm (most common)
434
444
  path.join(root, 'node_modules', 'moflo', '.claude', 'skills', 'flo', 'SKILL.md'),
435
- // Running from moflo repo itself
436
- path.join(path.dirname(path.dirname(path.dirname(path.dirname(path.dirname(__dirname))))), '.claude', 'skills', 'flo', 'SKILL.md'),
445
+ // Running from moflo repo itself (dev)
446
+ ...(thisDir ? [path.join(thisDir, '..', '..', '..', '..', '.claude', 'skills', 'flo', 'SKILL.md')] : []),
437
447
  ];
438
448
  for (const candidate of staticSkillCandidates) {
439
- if (fs.existsSync(candidate)) {
440
- skillContent = fs.readFileSync(candidate, 'utf-8');
441
- break;
449
+ try {
450
+ if (fs.existsSync(candidate)) {
451
+ skillContent = fs.readFileSync(candidate, 'utf-8');
452
+ break;
453
+ }
442
454
  }
455
+ catch { /* skip inaccessible paths */ }
443
456
  }
444
457
  if (!skillContent) {
445
458
  return { name: '.claude/skills/flo/', status: 'error', detail: 'Could not find SKILL.md in moflo package' };
@@ -567,12 +580,24 @@ function syncScripts(root, force) {
567
580
  fs.mkdirSync(scriptsDir, { recursive: true });
568
581
  }
569
582
  // Find moflo bin/ directory
583
+ let syncThisDir;
584
+ try {
585
+ syncThisDir = path.dirname(fileURLToPath(import.meta.url));
586
+ }
587
+ catch {
588
+ syncThisDir = typeof __dirname !== 'undefined' ? __dirname : '';
589
+ }
570
590
  const candidates = [
571
591
  path.join(root, 'node_modules', 'moflo', 'bin'),
572
592
  // When running from moflo repo itself
573
- path.join(path.dirname(path.dirname(path.dirname(path.dirname(path.dirname(__dirname))))), 'bin'),
593
+ ...(syncThisDir ? [path.join(syncThisDir, '..', '..', '..', '..', 'bin')] : []),
574
594
  ];
575
- const binDir = candidates.find(d => fs.existsSync(d));
595
+ const binDir = candidates.find(d => { try {
596
+ return fs.existsSync(d);
597
+ }
598
+ catch {
599
+ return false;
600
+ } });
576
601
  if (!binDir) {
577
602
  return { name: '.claude/scripts/', status: 'skipped', detail: 'moflo bin/ not found' };
578
603
  }
@@ -608,8 +633,11 @@ function updateGitignore(root) {
608
633
  const gitignorePath = path.join(root, '.gitignore');
609
634
  const entries = ['.claude-orc/', '.swarm/', '.moflo/'];
610
635
  if (!fs.existsSync(gitignorePath)) {
611
- fs.writeFileSync(gitignorePath, entries.join('\n') + '\n', 'utf-8');
612
- return { name: '.gitignore', status: 'created', detail: entries.join(', ') };
636
+ // Create .gitignore with common defaults + MoFlo entries
637
+ const defaultEntries = ['node_modules/', 'dist/', '.env', '.env.*', ''];
638
+ const content = '# Dependencies\n' + defaultEntries.join('\n') + '\n# MoFlo state\n' + entries.join('\n') + '\n';
639
+ fs.writeFileSync(gitignorePath, content, 'utf-8');
640
+ return { name: '.gitignore', status: 'created', detail: 'Created with node_modules, .env, and MoFlo entries' };
613
641
  }
614
642
  const existing = fs.readFileSync(gitignorePath, 'utf-8');
615
643
  const toAdd = entries.filter(e => !existing.includes(e));
@@ -289,8 +289,9 @@ function getSecurityStatus() {
289
289
  function getSwarmStatus() {
290
290
  const activityData = readJSON(path.join(CWD, '.claude-flow', 'metrics', 'swarm-activity.json'));
291
291
  if (activityData && activityData.swarm) {
292
+ const count = activityData.swarm.agent_count || 0;
292
293
  return {
293
- activeAgents: activityData.swarm.agent_count || 0,
294
+ activeAgents: Math.min(count, CONFIG.maxAgents),
294
295
  maxAgents: CONFIG.maxAgents,
295
296
  coordinationActive: activityData.swarm.coordination_active || activityData.swarm.active || false,
296
297
  };
@@ -298,10 +299,12 @@ function getSwarmStatus() {
298
299
 
299
300
  const progressData = readJSON(path.join(CWD, '.claude-flow', 'metrics', 'v3-progress.json'));
300
301
  if (progressData && progressData.swarm) {
302
+ const count = progressData.swarm.activeAgents || progressData.swarm.agent_count || 0;
303
+ const max = progressData.swarm.totalAgents || CONFIG.maxAgents;
301
304
  return {
302
- activeAgents: progressData.swarm.activeAgents || progressData.swarm.agent_count || 0,
303
- maxAgents: progressData.swarm.totalAgents || CONFIG.maxAgents,
304
- coordinationActive: progressData.swarm.active || (progressData.swarm.activeAgents > 0),
305
+ activeAgents: Math.min(count, max),
306
+ maxAgents: max,
307
+ coordinationActive: progressData.swarm.active || (count > 0),
305
308
  };
306
309
  }
307
310
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moflo/cli",
3
- "version": "4.7.2",
3
+ "version": "4.7.4",
4
4
  "type": "module",
5
5
  "description": "MoFlo CLI — AI agent orchestration with specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
6
6
  "main": "dist/src/index.js",
@@ -1,5 +0,0 @@
1
- {
2
- "tasksCreated": false,
3
- "taskCount": 0,
4
- "memorySearched": true
5
- }