moflo 4.8.16 → 4.8.19
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/.claude/agents/browser/browser-agent.yaml +182 -182
- package/.claude/agents/core/coder.md +265 -265
- package/.claude/agents/core/planner.md +167 -167
- package/.claude/agents/core/researcher.md +189 -189
- package/.claude/agents/core/reviewer.md +325 -325
- package/.claude/agents/core/tester.md +318 -318
- package/.claude/agents/database-specialist.yaml +21 -21
- package/.claude/agents/dual-mode/codex-coordinator.md +224 -224
- package/.claude/agents/dual-mode/codex-worker.md +211 -211
- package/.claude/agents/dual-mode/dual-orchestrator.md +291 -291
- package/.claude/agents/github/code-review-swarm.md +537 -537
- package/.claude/agents/github/github-modes.md +172 -172
- package/.claude/agents/github/issue-tracker.md +318 -318
- package/.claude/agents/github/multi-repo-swarm.md +552 -552
- package/.claude/agents/github/pr-manager.md +190 -190
- package/.claude/agents/github/project-board-sync.md +508 -508
- package/.claude/agents/github/release-manager.md +366 -366
- package/.claude/agents/github/release-swarm.md +582 -582
- package/.claude/agents/github/repo-architect.md +397 -397
- package/.claude/agents/github/swarm-issue.md +572 -572
- package/.claude/agents/github/swarm-pr.md +427 -427
- package/.claude/agents/github/sync-coordinator.md +451 -451
- package/.claude/agents/github/workflow-automation.md +634 -634
- package/.claude/agents/goal/code-goal-planner.md +445 -445
- package/.claude/agents/hive-mind/collective-intelligence-coordinator.md +129 -129
- package/.claude/agents/hive-mind/queen-coordinator.md +202 -202
- package/.claude/agents/hive-mind/scout-explorer.md +241 -241
- package/.claude/agents/hive-mind/swarm-memory-manager.md +192 -192
- package/.claude/agents/hive-mind/worker-specialist.md +216 -216
- package/.claude/agents/index.yaml +17 -17
- package/.claude/agents/neural/safla-neural.md +73 -73
- package/.claude/agents/project-coordinator.yaml +15 -15
- package/.claude/agents/python-specialist.yaml +21 -21
- package/.claude/agents/reasoning/goal-planner.md +72 -72
- package/.claude/agents/security-auditor.yaml +20 -20
- package/.claude/agents/swarm/adaptive-coordinator.md +395 -395
- package/.claude/agents/swarm/hierarchical-coordinator.md +326 -326
- package/.claude/agents/swarm/mesh-coordinator.md +391 -391
- package/.claude/agents/templates/migration-plan.md +745 -745
- package/.claude/agents/typescript-specialist.yaml +21 -21
- package/.claude/checkpoints/1767754460.json +8 -8
- package/.claude/commands/agents/agent-spawning.md +28 -28
- package/.claude/commands/github/github-modes.md +146 -146
- package/.claude/commands/github/github-swarm.md +121 -121
- package/.claude/commands/github/issue-tracker.md +291 -291
- package/.claude/commands/github/pr-manager.md +169 -169
- package/.claude/commands/github/release-manager.md +337 -337
- package/.claude/commands/github/repo-architect.md +366 -366
- package/.claude/commands/github/sync-coordinator.md +300 -300
- package/.claude/commands/memory/neural.md +47 -47
- package/.claude/commands/sparc/analyzer.md +51 -51
- package/.claude/commands/sparc/architect.md +53 -53
- package/.claude/commands/sparc/ask.md +97 -97
- package/.claude/commands/sparc/batch-executor.md +54 -54
- package/.claude/commands/sparc/code.md +89 -89
- package/.claude/commands/sparc/coder.md +54 -54
- package/.claude/commands/sparc/debug.md +83 -83
- package/.claude/commands/sparc/debugger.md +54 -54
- package/.claude/commands/sparc/designer.md +53 -53
- package/.claude/commands/sparc/devops.md +109 -109
- package/.claude/commands/sparc/docs-writer.md +80 -80
- package/.claude/commands/sparc/documenter.md +54 -54
- package/.claude/commands/sparc/innovator.md +54 -54
- package/.claude/commands/sparc/integration.md +83 -83
- package/.claude/commands/sparc/mcp.md +117 -117
- package/.claude/commands/sparc/memory-manager.md +54 -54
- package/.claude/commands/sparc/optimizer.md +54 -54
- package/.claude/commands/sparc/orchestrator.md +131 -131
- package/.claude/commands/sparc/post-deployment-monitoring-mode.md +83 -83
- package/.claude/commands/sparc/refinement-optimization-mode.md +83 -83
- package/.claude/commands/sparc/researcher.md +54 -54
- package/.claude/commands/sparc/reviewer.md +54 -54
- package/.claude/commands/sparc/security-review.md +80 -80
- package/.claude/commands/sparc/sparc-modes.md +174 -174
- package/.claude/commands/sparc/sparc.md +111 -111
- package/.claude/commands/sparc/spec-pseudocode.md +80 -80
- package/.claude/commands/sparc/supabase-admin.md +348 -348
- package/.claude/commands/sparc/swarm-coordinator.md +54 -54
- package/.claude/commands/sparc/tdd.md +54 -54
- package/.claude/commands/sparc/tester.md +54 -54
- package/.claude/commands/sparc/tutorial.md +79 -79
- package/.claude/commands/sparc/workflow-manager.md +54 -54
- package/.claude/commands/sparc.md +166 -166
- package/.claude/commands/swarm/analysis.md +95 -95
- package/.claude/commands/swarm/development.md +96 -96
- package/.claude/commands/swarm/examples.md +168 -168
- package/.claude/commands/swarm/maintenance.md +102 -102
- package/.claude/commands/swarm/optimization.md +117 -117
- package/.claude/commands/swarm/research.md +136 -136
- package/.claude/commands/swarm/testing.md +131 -131
- package/.claude/commands/workflows/development.md +77 -77
- package/.claude/commands/workflows/research.md +62 -62
- package/.claude/guidance/moflo-bootstrap.md +126 -126
- package/.claude/guidance/shipped/agent-bootstrap.md +126 -126
- package/.claude/guidance/shipped/guidance-memory-strategy.md +262 -262
- package/.claude/guidance/shipped/memory-strategy.md +204 -204
- package/.claude/guidance/shipped/moflo.md +608 -608
- package/.claude/guidance/shipped/task-swarm-integration.md +441 -441
- package/.claude/helpers/intelligence.cjs +207 -207
- package/.claude/helpers/statusline.cjs +851 -851
- package/.claude/skills/fl/SKILL.md +583 -583
- package/.claude/skills/flo/SKILL.md +583 -583
- package/.claude/skills/github-code-review/SKILL.md +1140 -1140
- package/.claude/skills/github-multi-repo/SKILL.md +874 -874
- package/.claude/skills/github-project-management/SKILL.md +1277 -1277
- package/.claude/skills/github-release-management/SKILL.md +1081 -1081
- package/.claude/skills/github-workflow-automation/SKILL.md +1065 -1065
- package/.claude/skills/hive-mind-advanced/SKILL.md +712 -712
- package/.claude/skills/hooks-automation/SKILL.md +1201 -1201
- package/.claude/skills/performance-analysis/SKILL.md +563 -563
- package/.claude/skills/sparc-methodology/SKILL.md +1115 -1115
- package/.claude/skills/swarm-advanced/SKILL.md +973 -973
- package/LICENSE +21 -21
- package/README.md +685 -685
- package/bin/cli.js +0 -0
- package/bin/gate-hook.mjs +50 -50
- package/bin/gate.cjs +138 -138
- package/bin/generate-code-map.mjs +91 -12
- package/bin/hook-handler.cjs +83 -83
- package/bin/hooks.mjs +656 -656
- package/bin/index-guidance.mjs +892 -892
- package/bin/index-tests.mjs +709 -709
- package/bin/lib/process-manager.mjs +243 -243
- package/bin/lib/registry-cleanup.cjs +41 -41
- package/bin/prompt-hook.mjs +72 -72
- package/bin/semantic-search.mjs +472 -472
- package/bin/session-start-launcher.mjs +238 -226
- package/bin/setup-project.mjs +250 -250
- package/package.json +123 -121
- package/src/@claude-flow/cli/README.md +452 -452
- package/src/@claude-flow/cli/bin/cli.js +180 -175
- package/src/@claude-flow/cli/bin/preinstall.cjs +2 -2
- package/src/@claude-flow/cli/dist/src/commands/completions.js +409 -409
- package/src/@claude-flow/cli/dist/src/commands/doctor.js +1091 -1091
- package/src/@claude-flow/cli/dist/src/commands/embeddings.js +25 -25
- package/src/@claude-flow/cli/dist/src/commands/github.js +61 -61
- package/src/@claude-flow/cli/dist/src/commands/hive-mind.js +90 -90
- package/src/@claude-flow/cli/dist/src/commands/hooks.js +9 -9
- package/src/@claude-flow/cli/dist/src/commands/ruvector/import.js +14 -14
- package/src/@claude-flow/cli/dist/src/commands/ruvector/setup.js +624 -624
- package/src/@claude-flow/cli/dist/src/config/moflo-config.js +91 -91
- package/src/@claude-flow/cli/dist/src/init/claudemd-generator.d.ts +29 -29
- package/src/@claude-flow/cli/dist/src/init/claudemd-generator.js +43 -43
- package/src/@claude-flow/cli/dist/src/init/executor.js +485 -453
- package/src/@claude-flow/cli/dist/src/init/helpers-generator.js +482 -482
- package/src/@claude-flow/cli/dist/src/init/moflo-init.d.ts +30 -30
- package/src/@claude-flow/cli/dist/src/init/moflo-init.js +848 -839
- package/src/@claude-flow/cli/dist/src/init/settings-generator.js +6 -2
- package/src/@claude-flow/cli/dist/src/init/statusline-generator.js +786 -786
- package/src/@claude-flow/cli/dist/src/memory/memory-initializer.js +371 -371
- package/src/@claude-flow/cli/dist/src/runtime/headless.js +28 -28
- package/src/@claude-flow/cli/dist/src/services/agentic-flow-bridge.js +6 -0
- package/src/@claude-flow/cli/dist/src/services/headless-worker-executor.js +84 -84
- package/src/@claude-flow/cli/package.json +1 -1
- package/src/@claude-flow/guidance/README.md +1195 -1195
- package/src/@claude-flow/guidance/dist/adversarial.d.ts +284 -0
- package/src/@claude-flow/guidance/dist/adversarial.js +572 -0
- package/src/@claude-flow/guidance/dist/analyzer.d.ts +530 -0
- package/src/@claude-flow/guidance/dist/analyzer.js +2518 -0
- package/src/@claude-flow/guidance/dist/artifacts.d.ts +283 -0
- package/src/@claude-flow/guidance/dist/artifacts.js +356 -0
- package/src/@claude-flow/guidance/dist/authority.d.ts +290 -0
- package/src/@claude-flow/guidance/dist/authority.js +558 -0
- package/src/@claude-flow/guidance/dist/capabilities.d.ts +209 -0
- package/src/@claude-flow/guidance/dist/capabilities.js +485 -0
- package/src/@claude-flow/guidance/dist/coherence.d.ts +233 -0
- package/src/@claude-flow/guidance/dist/coherence.js +372 -0
- package/src/@claude-flow/guidance/dist/compiler.d.ts +87 -0
- package/src/@claude-flow/guidance/dist/compiler.js +419 -0
- package/src/@claude-flow/guidance/dist/conformance-kit.d.ts +225 -0
- package/src/@claude-flow/guidance/dist/conformance-kit.js +629 -0
- package/src/@claude-flow/guidance/dist/continue-gate.d.ts +214 -0
- package/src/@claude-flow/guidance/dist/continue-gate.js +353 -0
- package/src/@claude-flow/guidance/dist/crypto-utils.d.ts +17 -0
- package/src/@claude-flow/guidance/dist/crypto-utils.js +24 -0
- package/src/@claude-flow/guidance/dist/evolution.d.ts +282 -0
- package/src/@claude-flow/guidance/dist/evolution.js +500 -0
- package/src/@claude-flow/guidance/dist/gates.d.ts +79 -0
- package/src/@claude-flow/guidance/dist/gates.js +302 -0
- package/src/@claude-flow/guidance/dist/gateway.d.ts +206 -0
- package/src/@claude-flow/guidance/dist/gateway.js +452 -0
- package/src/@claude-flow/guidance/dist/generators.d.ts +153 -0
- package/src/@claude-flow/guidance/dist/generators.js +682 -0
- package/src/@claude-flow/guidance/dist/headless.d.ts +177 -0
- package/src/@claude-flow/guidance/dist/headless.js +342 -0
- package/src/@claude-flow/guidance/dist/hooks.d.ts +109 -0
- package/src/@claude-flow/guidance/dist/hooks.js +347 -0
- package/src/@claude-flow/guidance/dist/index.d.ts +205 -0
- package/src/@claude-flow/guidance/dist/index.js +321 -0
- package/src/@claude-flow/guidance/dist/ledger.d.ts +162 -0
- package/src/@claude-flow/guidance/dist/ledger.js +375 -0
- package/src/@claude-flow/guidance/dist/manifest-validator.d.ts +289 -0
- package/src/@claude-flow/guidance/dist/manifest-validator.js +838 -0
- package/src/@claude-flow/guidance/dist/memory-gate.d.ts +222 -0
- package/src/@claude-flow/guidance/dist/memory-gate.js +382 -0
- package/src/@claude-flow/guidance/dist/meta-governance.d.ts +265 -0
- package/src/@claude-flow/guidance/dist/meta-governance.js +348 -0
- package/src/@claude-flow/guidance/dist/optimizer.d.ts +104 -0
- package/src/@claude-flow/guidance/dist/optimizer.js +329 -0
- package/src/@claude-flow/guidance/dist/persistence.d.ts +189 -0
- package/src/@claude-flow/guidance/dist/persistence.js +464 -0
- package/src/@claude-flow/guidance/dist/proof.d.ts +185 -0
- package/src/@claude-flow/guidance/dist/proof.js +238 -0
- package/src/@claude-flow/guidance/dist/retriever.d.ts +116 -0
- package/src/@claude-flow/guidance/dist/retriever.js +394 -0
- package/src/@claude-flow/guidance/dist/ruvbot-integration.d.ts +370 -0
- package/src/@claude-flow/guidance/dist/ruvbot-integration.js +738 -0
- package/src/@claude-flow/guidance/dist/temporal.d.ts +426 -0
- package/src/@claude-flow/guidance/dist/temporal.js +658 -0
- package/src/@claude-flow/guidance/dist/trust.d.ts +283 -0
- package/src/@claude-flow/guidance/dist/trust.js +473 -0
- package/src/@claude-flow/guidance/dist/truth-anchors.d.ts +276 -0
- package/src/@claude-flow/guidance/dist/truth-anchors.js +488 -0
- package/src/@claude-flow/guidance/dist/types.d.ts +378 -0
- package/src/@claude-flow/guidance/dist/types.js +10 -0
- package/src/@claude-flow/guidance/dist/uncertainty.d.ts +372 -0
- package/src/@claude-flow/guidance/dist/uncertainty.js +619 -0
- package/src/@claude-flow/guidance/dist/wasm-kernel.d.ts +48 -0
- package/src/@claude-flow/guidance/dist/wasm-kernel.js +158 -0
- package/src/@claude-flow/guidance/package.json +198 -198
- package/src/@claude-flow/memory/README.md +587 -587
- package/src/@claude-flow/memory/package.json +44 -44
- package/src/@claude-flow/shared/README.md +323 -323
- package/src/README.md +493 -493
- package/.claude/settings.local.json +0 -18
- package/.claude/workflow-state.json +0 -9
- package/src/@claude-flow/cli/dist/src/services/container-worker-pool.d.ts +0 -197
- package/src/@claude-flow/cli/dist/src/services/container-worker-pool.js +0 -584
- package/src/@claude-flow/memory/dist/agent-memory-scope.d.ts +0 -131
- package/src/@claude-flow/memory/dist/agent-memory-scope.js +0 -223
- package/src/@claude-flow/memory/dist/agent-memory-scope.test.d.ts +0 -8
- package/src/@claude-flow/memory/dist/agent-memory-scope.test.js +0 -463
- package/src/@claude-flow/memory/dist/agentdb-adapter.d.ts +0 -165
- package/src/@claude-flow/memory/dist/agentdb-adapter.js +0 -806
- package/src/@claude-flow/memory/dist/agentdb-backend.d.ts +0 -214
- package/src/@claude-flow/memory/dist/agentdb-backend.js +0 -844
- package/src/@claude-flow/memory/dist/agentdb-backend.test.d.ts +0 -7
- package/src/@claude-flow/memory/dist/agentdb-backend.test.js +0 -258
- package/src/@claude-flow/memory/dist/application/commands/delete-memory.command.d.ts +0 -65
- package/src/@claude-flow/memory/dist/application/commands/delete-memory.command.js +0 -129
- package/src/@claude-flow/memory/dist/application/commands/store-memory.command.d.ts +0 -48
- package/src/@claude-flow/memory/dist/application/commands/store-memory.command.js +0 -72
- package/src/@claude-flow/memory/dist/application/index.d.ts +0 -12
- package/src/@claude-flow/memory/dist/application/index.js +0 -15
- package/src/@claude-flow/memory/dist/application/queries/search-memory.query.d.ts +0 -72
- package/src/@claude-flow/memory/dist/application/queries/search-memory.query.js +0 -143
- package/src/@claude-flow/memory/dist/application/services/memory-application-service.d.ts +0 -121
- package/src/@claude-flow/memory/dist/application/services/memory-application-service.js +0 -190
- package/src/@claude-flow/memory/dist/auto-memory-bridge.d.ts +0 -226
- package/src/@claude-flow/memory/dist/auto-memory-bridge.js +0 -709
- package/src/@claude-flow/memory/dist/auto-memory-bridge.test.d.ts +0 -8
- package/src/@claude-flow/memory/dist/auto-memory-bridge.test.js +0 -754
- package/src/@claude-flow/memory/dist/benchmark.test.d.ts +0 -2
- package/src/@claude-flow/memory/dist/benchmark.test.js +0 -277
- package/src/@claude-flow/memory/dist/cache-manager.d.ts +0 -134
- package/src/@claude-flow/memory/dist/cache-manager.js +0 -407
- package/src/@claude-flow/memory/dist/controller-registry.d.ts +0 -216
- package/src/@claude-flow/memory/dist/controller-registry.js +0 -893
- package/src/@claude-flow/memory/dist/controller-registry.test.d.ts +0 -14
- package/src/@claude-flow/memory/dist/controller-registry.test.js +0 -636
- package/src/@claude-flow/memory/dist/database-provider.d.ts +0 -87
- package/src/@claude-flow/memory/dist/database-provider.js +0 -375
- package/src/@claude-flow/memory/dist/database-provider.test.d.ts +0 -7
- package/src/@claude-flow/memory/dist/database-provider.test.js +0 -285
- package/src/@claude-flow/memory/dist/domain/entities/memory-entry.d.ts +0 -143
- package/src/@claude-flow/memory/dist/domain/entities/memory-entry.js +0 -226
- package/src/@claude-flow/memory/dist/domain/index.d.ts +0 -11
- package/src/@claude-flow/memory/dist/domain/index.js +0 -12
- package/src/@claude-flow/memory/dist/domain/repositories/memory-repository.interface.d.ts +0 -102
- package/src/@claude-flow/memory/dist/domain/repositories/memory-repository.interface.js +0 -11
- package/src/@claude-flow/memory/dist/domain/services/memory-domain-service.d.ts +0 -105
- package/src/@claude-flow/memory/dist/domain/services/memory-domain-service.js +0 -297
- package/src/@claude-flow/memory/dist/hnsw-index.d.ts +0 -111
- package/src/@claude-flow/memory/dist/hnsw-index.js +0 -781
- package/src/@claude-flow/memory/dist/hnsw-lite.d.ts +0 -23
- package/src/@claude-flow/memory/dist/hnsw-lite.js +0 -168
- package/src/@claude-flow/memory/dist/hybrid-backend.d.ts +0 -245
- package/src/@claude-flow/memory/dist/hybrid-backend.js +0 -569
- package/src/@claude-flow/memory/dist/hybrid-backend.test.d.ts +0 -8
- package/src/@claude-flow/memory/dist/hybrid-backend.test.js +0 -320
- package/src/@claude-flow/memory/dist/index.d.ts +0 -207
- package/src/@claude-flow/memory/dist/index.js +0 -361
- package/src/@claude-flow/memory/dist/infrastructure/index.d.ts +0 -17
- package/src/@claude-flow/memory/dist/infrastructure/index.js +0 -16
- package/src/@claude-flow/memory/dist/infrastructure/repositories/hybrid-memory-repository.d.ts +0 -66
- package/src/@claude-flow/memory/dist/infrastructure/repositories/hybrid-memory-repository.js +0 -409
- package/src/@claude-flow/memory/dist/learning-bridge.d.ts +0 -137
- package/src/@claude-flow/memory/dist/learning-bridge.js +0 -335
- package/src/@claude-flow/memory/dist/learning-bridge.test.d.ts +0 -8
- package/src/@claude-flow/memory/dist/learning-bridge.test.js +0 -578
- package/src/@claude-flow/memory/dist/memory-graph.d.ts +0 -100
- package/src/@claude-flow/memory/dist/memory-graph.js +0 -333
- package/src/@claude-flow/memory/dist/memory-graph.test.d.ts +0 -8
- package/src/@claude-flow/memory/dist/memory-graph.test.js +0 -609
- package/src/@claude-flow/memory/dist/migration.d.ts +0 -68
- package/src/@claude-flow/memory/dist/migration.js +0 -513
- package/src/@claude-flow/memory/dist/persistent-sona.d.ts +0 -144
- package/src/@claude-flow/memory/dist/persistent-sona.js +0 -332
- package/src/@claude-flow/memory/dist/query-builder.d.ts +0 -211
- package/src/@claude-flow/memory/dist/query-builder.js +0 -438
- package/src/@claude-flow/memory/dist/rvf-backend.d.ts +0 -51
- package/src/@claude-flow/memory/dist/rvf-backend.js +0 -481
- package/src/@claude-flow/memory/dist/rvf-learning-store.d.ts +0 -139
- package/src/@claude-flow/memory/dist/rvf-learning-store.js +0 -295
- package/src/@claude-flow/memory/dist/rvf-migration.d.ts +0 -45
- package/src/@claude-flow/memory/dist/rvf-migration.js +0 -234
- package/src/@claude-flow/memory/dist/sqlite-backend.d.ts +0 -121
- package/src/@claude-flow/memory/dist/sqlite-backend.js +0 -572
- package/src/@claude-flow/memory/dist/sqljs-backend.d.ts +0 -128
- package/src/@claude-flow/memory/dist/sqljs-backend.js +0 -601
- package/src/@claude-flow/memory/dist/types.d.ts +0 -484
- package/src/@claude-flow/memory/dist/types.js +0 -58
- package/src/@claude-flow/shared/dist/core/config/defaults.d.ts +0 -41
- package/src/@claude-flow/shared/dist/core/config/defaults.js +0 -186
- package/src/@claude-flow/shared/dist/core/config/index.d.ts +0 -8
- package/src/@claude-flow/shared/dist/core/config/index.js +0 -12
- package/src/@claude-flow/shared/dist/core/config/loader.d.ts +0 -45
- package/src/@claude-flow/shared/dist/core/config/loader.js +0 -222
- package/src/@claude-flow/shared/dist/core/config/schema.d.ts +0 -1134
- package/src/@claude-flow/shared/dist/core/config/schema.js +0 -158
- package/src/@claude-flow/shared/dist/core/config/validator.d.ts +0 -92
- package/src/@claude-flow/shared/dist/core/config/validator.js +0 -147
- package/src/@claude-flow/shared/dist/core/event-bus.d.ts +0 -31
- package/src/@claude-flow/shared/dist/core/event-bus.js +0 -197
- package/src/@claude-flow/shared/dist/core/index.d.ts +0 -15
- package/src/@claude-flow/shared/dist/core/index.js +0 -19
- package/src/@claude-flow/shared/dist/core/interfaces/agent.interface.d.ts +0 -200
- package/src/@claude-flow/shared/dist/core/interfaces/agent.interface.js +0 -6
- package/src/@claude-flow/shared/dist/core/interfaces/coordinator.interface.d.ts +0 -310
- package/src/@claude-flow/shared/dist/core/interfaces/coordinator.interface.js +0 -7
- package/src/@claude-flow/shared/dist/core/interfaces/event.interface.d.ts +0 -224
- package/src/@claude-flow/shared/dist/core/interfaces/event.interface.js +0 -46
- package/src/@claude-flow/shared/dist/core/interfaces/index.d.ts +0 -10
- package/src/@claude-flow/shared/dist/core/interfaces/index.js +0 -15
- package/src/@claude-flow/shared/dist/core/interfaces/memory.interface.d.ts +0 -298
- package/src/@claude-flow/shared/dist/core/interfaces/memory.interface.js +0 -7
- package/src/@claude-flow/shared/dist/core/interfaces/task.interface.d.ts +0 -185
- package/src/@claude-flow/shared/dist/core/interfaces/task.interface.js +0 -6
- package/src/@claude-flow/shared/dist/core/orchestrator/event-coordinator.d.ts +0 -35
- package/src/@claude-flow/shared/dist/core/orchestrator/event-coordinator.js +0 -101
- package/src/@claude-flow/shared/dist/core/orchestrator/health-monitor.d.ts +0 -60
- package/src/@claude-flow/shared/dist/core/orchestrator/health-monitor.js +0 -166
- package/src/@claude-flow/shared/dist/core/orchestrator/index.d.ts +0 -46
- package/src/@claude-flow/shared/dist/core/orchestrator/index.js +0 -64
- package/src/@claude-flow/shared/dist/core/orchestrator/lifecycle-manager.d.ts +0 -56
- package/src/@claude-flow/shared/dist/core/orchestrator/lifecycle-manager.js +0 -195
- package/src/@claude-flow/shared/dist/core/orchestrator/session-manager.d.ts +0 -83
- package/src/@claude-flow/shared/dist/core/orchestrator/session-manager.js +0 -193
- package/src/@claude-flow/shared/dist/core/orchestrator/task-manager.d.ts +0 -49
- package/src/@claude-flow/shared/dist/core/orchestrator/task-manager.js +0 -253
- package/src/@claude-flow/shared/dist/events/domain-events.d.ts +0 -282
- package/src/@claude-flow/shared/dist/events/domain-events.js +0 -165
- package/src/@claude-flow/shared/dist/events/event-store.d.ts +0 -126
- package/src/@claude-flow/shared/dist/events/event-store.js +0 -416
- package/src/@claude-flow/shared/dist/events/event-store.test.d.ts +0 -8
- package/src/@claude-flow/shared/dist/events/event-store.test.js +0 -293
- package/src/@claude-flow/shared/dist/events/example-usage.d.ts +0 -10
- package/src/@claude-flow/shared/dist/events/example-usage.js +0 -193
- package/src/@claude-flow/shared/dist/events/index.d.ts +0 -21
- package/src/@claude-flow/shared/dist/events/index.js +0 -22
- package/src/@claude-flow/shared/dist/events/projections.d.ts +0 -177
- package/src/@claude-flow/shared/dist/events/projections.js +0 -421
- package/src/@claude-flow/shared/dist/events/rvf-event-log.d.ts +0 -82
- package/src/@claude-flow/shared/dist/events/rvf-event-log.js +0 -340
- package/src/@claude-flow/shared/dist/events/state-reconstructor.d.ts +0 -101
- package/src/@claude-flow/shared/dist/events/state-reconstructor.js +0 -263
- package/src/@claude-flow/shared/dist/events.d.ts +0 -80
- package/src/@claude-flow/shared/dist/events.js +0 -249
- package/src/@claude-flow/shared/dist/hooks/example-usage.d.ts +0 -42
- package/src/@claude-flow/shared/dist/hooks/example-usage.js +0 -351
- package/src/@claude-flow/shared/dist/hooks/executor.d.ts +0 -100
- package/src/@claude-flow/shared/dist/hooks/executor.js +0 -264
- package/src/@claude-flow/shared/dist/hooks/hooks.test.d.ts +0 -9
- package/src/@claude-flow/shared/dist/hooks/hooks.test.js +0 -322
- package/src/@claude-flow/shared/dist/hooks/index.d.ts +0 -52
- package/src/@claude-flow/shared/dist/hooks/index.js +0 -51
- package/src/@claude-flow/shared/dist/hooks/registry.d.ts +0 -133
- package/src/@claude-flow/shared/dist/hooks/registry.js +0 -277
- package/src/@claude-flow/shared/dist/hooks/safety/bash-safety.d.ts +0 -105
- package/src/@claude-flow/shared/dist/hooks/safety/bash-safety.js +0 -481
- package/src/@claude-flow/shared/dist/hooks/safety/file-organization.d.ts +0 -144
- package/src/@claude-flow/shared/dist/hooks/safety/file-organization.js +0 -328
- package/src/@claude-flow/shared/dist/hooks/safety/git-commit.d.ts +0 -158
- package/src/@claude-flow/shared/dist/hooks/safety/git-commit.js +0 -450
- package/src/@claude-flow/shared/dist/hooks/safety/index.d.ts +0 -17
- package/src/@claude-flow/shared/dist/hooks/safety/index.js +0 -17
- package/src/@claude-flow/shared/dist/hooks/session-hooks.d.ts +0 -234
- package/src/@claude-flow/shared/dist/hooks/session-hooks.js +0 -334
- package/src/@claude-flow/shared/dist/hooks/task-hooks.d.ts +0 -163
- package/src/@claude-flow/shared/dist/hooks/task-hooks.js +0 -326
- package/src/@claude-flow/shared/dist/hooks/types.d.ts +0 -267
- package/src/@claude-flow/shared/dist/hooks/types.js +0 -62
- package/src/@claude-flow/shared/dist/hooks/verify-exports.test.d.ts +0 -9
- package/src/@claude-flow/shared/dist/hooks/verify-exports.test.js +0 -93
- package/src/@claude-flow/shared/dist/index.d.ts +0 -20
- package/src/@claude-flow/shared/dist/index.js +0 -50
- package/src/@claude-flow/shared/dist/mcp/connection-pool.d.ts +0 -98
- package/src/@claude-flow/shared/dist/mcp/connection-pool.js +0 -364
- package/src/@claude-flow/shared/dist/mcp/index.d.ts +0 -69
- package/src/@claude-flow/shared/dist/mcp/index.js +0 -84
- package/src/@claude-flow/shared/dist/mcp/server.d.ts +0 -166
- package/src/@claude-flow/shared/dist/mcp/server.js +0 -593
- package/src/@claude-flow/shared/dist/mcp/session-manager.d.ts +0 -136
- package/src/@claude-flow/shared/dist/mcp/session-manager.js +0 -335
- package/src/@claude-flow/shared/dist/mcp/tool-registry.d.ts +0 -178
- package/src/@claude-flow/shared/dist/mcp/tool-registry.js +0 -439
- package/src/@claude-flow/shared/dist/mcp/transport/http.d.ts +0 -104
- package/src/@claude-flow/shared/dist/mcp/transport/http.js +0 -476
- package/src/@claude-flow/shared/dist/mcp/transport/index.d.ts +0 -102
- package/src/@claude-flow/shared/dist/mcp/transport/index.js +0 -238
- package/src/@claude-flow/shared/dist/mcp/transport/stdio.d.ts +0 -104
- package/src/@claude-flow/shared/dist/mcp/transport/stdio.js +0 -263
- package/src/@claude-flow/shared/dist/mcp/transport/websocket.d.ts +0 -133
- package/src/@claude-flow/shared/dist/mcp/transport/websocket.js +0 -396
- package/src/@claude-flow/shared/dist/mcp/types.d.ts +0 -438
- package/src/@claude-flow/shared/dist/mcp/types.js +0 -54
- package/src/@claude-flow/shared/dist/plugin-interface.d.ts +0 -544
- package/src/@claude-flow/shared/dist/plugin-interface.js +0 -23
- package/src/@claude-flow/shared/dist/plugin-loader.d.ts +0 -139
- package/src/@claude-flow/shared/dist/plugin-loader.js +0 -434
- package/src/@claude-flow/shared/dist/plugin-registry.d.ts +0 -183
- package/src/@claude-flow/shared/dist/plugin-registry.js +0 -457
- package/src/@claude-flow/shared/dist/plugins/index.d.ts +0 -10
- package/src/@claude-flow/shared/dist/plugins/index.js +0 -10
- package/src/@claude-flow/shared/dist/plugins/official/hive-mind-plugin.d.ts +0 -106
- package/src/@claude-flow/shared/dist/plugins/official/hive-mind-plugin.js +0 -241
- package/src/@claude-flow/shared/dist/plugins/official/index.d.ts +0 -10
- package/src/@claude-flow/shared/dist/plugins/official/index.js +0 -10
- package/src/@claude-flow/shared/dist/plugins/official/maestro-plugin.d.ts +0 -121
- package/src/@claude-flow/shared/dist/plugins/official/maestro-plugin.js +0 -355
- package/src/@claude-flow/shared/dist/plugins/types.d.ts +0 -93
- package/src/@claude-flow/shared/dist/plugins/types.js +0 -9
- package/src/@claude-flow/shared/dist/resilience/bulkhead.d.ts +0 -105
- package/src/@claude-flow/shared/dist/resilience/bulkhead.js +0 -206
- package/src/@claude-flow/shared/dist/resilience/circuit-breaker.d.ts +0 -132
- package/src/@claude-flow/shared/dist/resilience/circuit-breaker.js +0 -233
- package/src/@claude-flow/shared/dist/resilience/index.d.ts +0 -19
- package/src/@claude-flow/shared/dist/resilience/index.js +0 -19
- package/src/@claude-flow/shared/dist/resilience/rate-limiter.d.ts +0 -168
- package/src/@claude-flow/shared/dist/resilience/rate-limiter.js +0 -314
- package/src/@claude-flow/shared/dist/resilience/retry.d.ts +0 -91
- package/src/@claude-flow/shared/dist/resilience/retry.js +0 -159
- package/src/@claude-flow/shared/dist/security/index.d.ts +0 -10
- package/src/@claude-flow/shared/dist/security/index.js +0 -12
- package/src/@claude-flow/shared/dist/security/input-validation.d.ts +0 -73
- package/src/@claude-flow/shared/dist/security/input-validation.js +0 -201
- package/src/@claude-flow/shared/dist/security/secure-random.d.ts +0 -92
- package/src/@claude-flow/shared/dist/security/secure-random.js +0 -142
- package/src/@claude-flow/shared/dist/services/index.d.ts +0 -7
- package/src/@claude-flow/shared/dist/services/index.js +0 -7
- package/src/@claude-flow/shared/dist/services/v3-progress.service.d.ts +0 -124
- package/src/@claude-flow/shared/dist/services/v3-progress.service.js +0 -402
- package/src/@claude-flow/shared/dist/types/agent.types.d.ts +0 -137
- package/src/@claude-flow/shared/dist/types/agent.types.js +0 -6
- package/src/@claude-flow/shared/dist/types/index.d.ts +0 -11
- package/src/@claude-flow/shared/dist/types/index.js +0 -17
- package/src/@claude-flow/shared/dist/types/mcp.types.d.ts +0 -266
- package/src/@claude-flow/shared/dist/types/mcp.types.js +0 -7
- package/src/@claude-flow/shared/dist/types/memory.types.d.ts +0 -236
- package/src/@claude-flow/shared/dist/types/memory.types.js +0 -7
- package/src/@claude-flow/shared/dist/types/swarm.types.d.ts +0 -186
- package/src/@claude-flow/shared/dist/types/swarm.types.js +0 -65
- package/src/@claude-flow/shared/dist/types/task.types.d.ts +0 -178
- package/src/@claude-flow/shared/dist/types/task.types.js +0 -32
- package/src/@claude-flow/shared/dist/types.d.ts +0 -197
- package/src/@claude-flow/shared/dist/types.js +0 -21
- package/src/@claude-flow/shared/dist/utils/secure-logger.d.ts +0 -69
- package/src/@claude-flow/shared/dist/utils/secure-logger.js +0 -208
|
@@ -1,840 +1,849 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MoFlo Project Initializer
|
|
3
|
-
*
|
|
4
|
-
* One-stop setup that makes MoFlo work out of the box:
|
|
5
|
-
* 1. Generate moflo.yaml (project config)
|
|
6
|
-
* 2. Set up .claude/settings.json hooks
|
|
7
|
-
* 3. Create .claude/skills/flo/ skill (with /fl alias)
|
|
8
|
-
* 4. Append MoFlo section to CLAUDE.md
|
|
9
|
-
* 5. Initialize memory DB
|
|
10
|
-
* 6. Auto-index guidance + code map
|
|
11
|
-
*/
|
|
12
|
-
import * as fs from 'fs';
|
|
13
|
-
import * as path from 'path';
|
|
14
|
-
import { fileURLToPath } from 'url';
|
|
15
|
-
// ============================================================================
|
|
16
|
-
// Init
|
|
17
|
-
// ============================================================================
|
|
18
|
-
/**
|
|
19
|
-
* Discover guidance directories by checking top-level candidates AND walking
|
|
20
|
-
* the project tree for subproject .claude/guidance dirs (monorepo support).
|
|
21
|
-
*/
|
|
22
|
-
function discoverGuidanceDirs(root) {
|
|
23
|
-
const TOP_LEVEL = ['.claude/guidance', 'docs/guides', 'docs', 'architecture', 'adr', '.cursor/rules'];
|
|
24
|
-
const found = TOP_LEVEL.filter(d => fs.existsSync(path.join(root, d)));
|
|
25
|
-
// Walk up to 3 levels deep looking for .claude/guidance in subprojects
|
|
26
|
-
const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.reports', '.swarm', '.claude-flow', 'packages']);
|
|
27
|
-
function walk(dir, depth) {
|
|
28
|
-
if (depth > 3)
|
|
29
|
-
return;
|
|
30
|
-
try {
|
|
31
|
-
const entries = fs.readdirSync(path.join(root, dir), { withFileTypes: true });
|
|
32
|
-
for (const entry of entries) {
|
|
33
|
-
if (!entry.isDirectory() || SKIP.has(entry.name))
|
|
34
|
-
continue;
|
|
35
|
-
const rel = dir ? `${dir}/${entry.name}` : entry.name;
|
|
36
|
-
const guidancePath = `${rel}/.claude/guidance`;
|
|
37
|
-
if (fs.existsSync(path.join(root, guidancePath))) {
|
|
38
|
-
// Verify it has .md files
|
|
39
|
-
try {
|
|
40
|
-
const files = fs.readdirSync(path.join(root, guidancePath));
|
|
41
|
-
if (files.some(f => f.endsWith('.md')))
|
|
42
|
-
found.push(guidancePath);
|
|
43
|
-
}
|
|
44
|
-
catch { /* skip unreadable */ }
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
walk(rel, depth + 1);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
catch { /* skip unreadable directories */ }
|
|
52
|
-
}
|
|
53
|
-
walk('', 0);
|
|
54
|
-
return found;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Discover test directories by checking common locations and walking for
|
|
58
|
-
* colocated __tests__ dirs. Returns relative paths.
|
|
59
|
-
*/
|
|
60
|
-
export function discoverTestDirs(root) {
|
|
61
|
-
const TOP_LEVEL = ['tests', 'test', '__tests__', 'spec', 'e2e'];
|
|
62
|
-
const found = TOP_LEVEL.filter(d => fs.existsSync(path.join(root, d)));
|
|
63
|
-
// Walk up to 3 levels deep looking for __tests__ dirs inside src
|
|
64
|
-
const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.reports', '.swarm', '.claude-flow']);
|
|
65
|
-
function walk(dir, depth) {
|
|
66
|
-
if (depth > 3)
|
|
67
|
-
return;
|
|
68
|
-
try {
|
|
69
|
-
const entries = fs.readdirSync(path.join(root, dir), { withFileTypes: true });
|
|
70
|
-
for (const entry of entries) {
|
|
71
|
-
if (!entry.isDirectory() || SKIP.has(entry.name))
|
|
72
|
-
continue;
|
|
73
|
-
const rel = dir ? `${dir}/${entry.name}` : entry.name;
|
|
74
|
-
if (entry.name === '__tests__') {
|
|
75
|
-
found.push(rel);
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
walk(rel, depth + 1);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
catch { /* skip unreadable directories */ }
|
|
83
|
-
}
|
|
84
|
-
walk('', 0);
|
|
85
|
-
return found;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Discover source directories by walking the project tree.
|
|
89
|
-
* Finds directories named 'src' (or top-level 'packages', 'lib', etc.)
|
|
90
|
-
* that contain .ts/.tsx/.js/.jsx files. Skips node_modules, dist, etc.
|
|
91
|
-
*/
|
|
92
|
-
function discoverSrcDirs(root) {
|
|
93
|
-
const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.reports', '.swarm', '.claude-flow']);
|
|
94
|
-
// Top-level candidates that are always source roots if they exist
|
|
95
|
-
const TOP_LEVEL = ['packages', 'lib', 'app', 'apps', 'services', 'server', 'client'];
|
|
96
|
-
const found = [];
|
|
97
|
-
// Add top-level candidates first
|
|
98
|
-
for (const d of TOP_LEVEL) {
|
|
99
|
-
if (fs.existsSync(path.join(root, d)))
|
|
100
|
-
found.push(d);
|
|
101
|
-
}
|
|
102
|
-
// Walk up to 3 levels deep looking for 'src' and 'migrations' directories
|
|
103
|
-
const SRC_NAMES = new Set(['src', 'migrations']);
|
|
104
|
-
function walk(dir, depth) {
|
|
105
|
-
if (depth > 3)
|
|
106
|
-
return;
|
|
107
|
-
try {
|
|
108
|
-
const entries = fs.readdirSync(path.join(root, dir), { withFileTypes: true });
|
|
109
|
-
for (const entry of entries) {
|
|
110
|
-
if (!entry.isDirectory() || SKIP.has(entry.name))
|
|
111
|
-
continue;
|
|
112
|
-
const rel = dir ? `${dir}/${entry.name}` : entry.name;
|
|
113
|
-
if (SRC_NAMES.has(entry.name)) {
|
|
114
|
-
// Check it actually has source files
|
|
115
|
-
try {
|
|
116
|
-
const files = fs.readdirSync(path.join(root, rel));
|
|
117
|
-
const hasSource = files.some(f => /\.(ts|tsx|js|jsx)$/.test(f));
|
|
118
|
-
if (hasSource)
|
|
119
|
-
found.push(rel);
|
|
120
|
-
}
|
|
121
|
-
catch { /* skip unreadable */ }
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
walk(rel, depth + 1);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
catch { /* skip unreadable directories */ }
|
|
129
|
-
}
|
|
130
|
-
walk('', 0);
|
|
131
|
-
// Deduplicate: if 'packages' is found, don't also include 'packages/foo/src'
|
|
132
|
-
// since the code-map walker handles subdirs
|
|
133
|
-
return found.filter(d => {
|
|
134
|
-
return !found.some(other => other !== d && d.startsWith(other + '/'));
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Run interactive wizard to collect user preferences.
|
|
139
|
-
*/
|
|
140
|
-
async function runWizard(root) {
|
|
141
|
-
const { confirm, input } = await import('../prompt.js');
|
|
142
|
-
// Detect project structure
|
|
143
|
-
const detectedGuidance = discoverGuidanceDirs(root);
|
|
144
|
-
const detectedSrc = discoverSrcDirs(root);
|
|
145
|
-
// Ask questions
|
|
146
|
-
const guidance = await confirm({
|
|
147
|
-
message: detectedGuidance.length > 0
|
|
148
|
-
? `Found guidance docs in ${detectedGuidance.join(', ')}. Enable guidance indexing?`
|
|
149
|
-
: 'Do you have project guidance/documentation to index?',
|
|
150
|
-
default: true,
|
|
151
|
-
});
|
|
152
|
-
let guidanceDirs = detectedGuidance.length > 0 ? detectedGuidance : ['.claude/guidance'];
|
|
153
|
-
if (guidance) {
|
|
154
|
-
const answer = await input({
|
|
155
|
-
message: 'Guidance directories (comma-separated):',
|
|
156
|
-
default: guidanceDirs.join(', '),
|
|
157
|
-
});
|
|
158
|
-
guidanceDirs = answer.split(',').map((d) => d.trim()).filter(Boolean);
|
|
159
|
-
}
|
|
160
|
-
const codeMap = await confirm({
|
|
161
|
-
message: detectedSrc.length > 0
|
|
162
|
-
? `Found source in ${detectedSrc.join(', ')}. Enable code map for navigation?`
|
|
163
|
-
: 'Enable code map for codebase navigation?',
|
|
164
|
-
default: true,
|
|
165
|
-
});
|
|
166
|
-
let srcDirs = detectedSrc.length > 0 ? detectedSrc : ['src'];
|
|
167
|
-
if (codeMap) {
|
|
168
|
-
const answer = await input({
|
|
169
|
-
message: 'Source directories (comma-separated):',
|
|
170
|
-
default: srcDirs.join(', '),
|
|
171
|
-
});
|
|
172
|
-
srcDirs = answer.split(',').map((d) => d.trim()).filter(Boolean);
|
|
173
|
-
}
|
|
174
|
-
// Detect test directories
|
|
175
|
-
const detectedTests = discoverTestDirs(root);
|
|
176
|
-
const tests = await confirm({
|
|
177
|
-
message: detectedTests.length > 0
|
|
178
|
-
? `Found tests in ${detectedTests.join(', ')}. Enable test file indexing?`
|
|
179
|
-
: 'Enable test file indexing?',
|
|
180
|
-
default: true,
|
|
181
|
-
});
|
|
182
|
-
let testDirs = detectedTests.length > 0 ? detectedTests : ['tests'];
|
|
183
|
-
if (tests) {
|
|
184
|
-
const answer = await input({
|
|
185
|
-
message: 'Test directories (comma-separated):',
|
|
186
|
-
default: testDirs.join(', '),
|
|
187
|
-
});
|
|
188
|
-
testDirs = answer.split(',').map((d) => d.trim()).filter(Boolean);
|
|
189
|
-
}
|
|
190
|
-
const gates = await confirm({
|
|
191
|
-
message: 'Enable workflow gates (memory-first, task-create-before-agents)?',
|
|
192
|
-
default: true,
|
|
193
|
-
});
|
|
194
|
-
const stopHook = await confirm({
|
|
195
|
-
message: 'Enable session-end hook (saves session state)?',
|
|
196
|
-
default: true,
|
|
197
|
-
});
|
|
198
|
-
return { guidance, guidanceDirs, codeMap, srcDirs, tests, testDirs, gates, stopHook };
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Get default answers (--yes mode).
|
|
202
|
-
*/
|
|
203
|
-
function defaultAnswers(root) {
|
|
204
|
-
const guidanceDirs = discoverGuidanceDirs(root);
|
|
205
|
-
if (guidanceDirs.length === 0)
|
|
206
|
-
guidanceDirs.push('.claude/guidance');
|
|
207
|
-
const srcDirs = discoverSrcDirs(root);
|
|
208
|
-
if (srcDirs.length === 0)
|
|
209
|
-
srcDirs.push('src');
|
|
210
|
-
const testDirs = discoverTestDirs(root);
|
|
211
|
-
if (testDirs.length === 0)
|
|
212
|
-
testDirs.push('tests');
|
|
213
|
-
return { guidance: true, guidanceDirs, codeMap: true, srcDirs, tests: true, testDirs, gates: true, stopHook: true };
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Get minimal answers (--minimal mode).
|
|
217
|
-
*/
|
|
218
|
-
function minimalAnswers() {
|
|
219
|
-
return { guidance: false, guidanceDirs: [], codeMap: false, srcDirs: [], tests: false, testDirs: [], gates: false, stopHook: false };
|
|
220
|
-
}
|
|
221
|
-
export async function initMoflo(options) {
|
|
222
|
-
const { projectRoot, force, interactive, minimal } = options;
|
|
223
|
-
const steps = [];
|
|
224
|
-
// Collect answers based on mode
|
|
225
|
-
const answers = minimal
|
|
226
|
-
? minimalAnswers()
|
|
227
|
-
: interactive
|
|
228
|
-
? await runWizard(projectRoot)
|
|
229
|
-
: defaultAnswers(projectRoot);
|
|
230
|
-
// Step 1: moflo.yaml
|
|
231
|
-
steps.push(generateConfig(projectRoot, force, answers));
|
|
232
|
-
// Step 2: .claude/settings.json hooks
|
|
233
|
-
steps.push(generateHooks(projectRoot, force, answers));
|
|
234
|
-
// Step 3: .claude/skills/flo/ (with /fl alias)
|
|
235
|
-
steps.push(generateSkill(projectRoot, force));
|
|
236
|
-
// Step 4: CLAUDE.md MoFlo section
|
|
237
|
-
steps.push(generateClaudeMd(projectRoot, force));
|
|
238
|
-
// Step 5: .claude/scripts/ from moflo bin/
|
|
239
|
-
steps.push(syncScripts(projectRoot, force));
|
|
240
|
-
// Step 6: .gitignore entries
|
|
241
|
-
steps.push(updateGitignore(projectRoot));
|
|
242
|
-
// Step 7: .claude/guidance/moflo-bootstrap.md (subagent bootstrap protocol)
|
|
243
|
-
steps.push(syncBootstrapGuidance(projectRoot, force));
|
|
244
|
-
return { steps };
|
|
245
|
-
}
|
|
246
|
-
// ============================================================================
|
|
247
|
-
// Step 1: moflo.yaml
|
|
248
|
-
// ============================================================================
|
|
249
|
-
function generateConfig(root, force, answers) {
|
|
250
|
-
const configPath = path.join(root, 'moflo.yaml');
|
|
251
|
-
if (fs.existsSync(configPath) && !force) {
|
|
252
|
-
return { name: 'moflo.yaml', status: 'skipped', detail: 'Already exists (use --force to overwrite)' };
|
|
253
|
-
}
|
|
254
|
-
const projectName = path.basename(root);
|
|
255
|
-
const guidanceDirs = answers?.guidanceDirs ?? ['.claude/guidance'];
|
|
256
|
-
const srcDirs = answers?.srcDirs ?? ['src'];
|
|
257
|
-
const testDirs = answers?.testDirs ?? ['tests'];
|
|
258
|
-
const gatesEnabled = answers?.gates ?? true;
|
|
259
|
-
// Detect languages
|
|
260
|
-
const extensions = new Set();
|
|
261
|
-
for (const dir of srcDirs) {
|
|
262
|
-
const fullDir = path.join(root, dir);
|
|
263
|
-
if (fs.existsSync(fullDir)) {
|
|
264
|
-
try {
|
|
265
|
-
scanExtensions(fullDir, extensions, 0, 3);
|
|
266
|
-
}
|
|
267
|
-
catch { /* skip */ }
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
const detectedExts = extensions.size > 0
|
|
271
|
-
? [...extensions].sort()
|
|
272
|
-
: ['.ts', '.tsx', '.js', '.jsx'];
|
|
273
|
-
const yaml = `# MoFlo — Project Configuration
|
|
274
|
-
# Generated by: moflo init
|
|
275
|
-
# Docs: https://github.com/eric-cielo/moflo
|
|
276
|
-
|
|
277
|
-
project:
|
|
278
|
-
name: "${projectName}"
|
|
279
|
-
|
|
280
|
-
# Guidance/knowledge docs to index for semantic search
|
|
281
|
-
guidance:
|
|
282
|
-
directories:
|
|
283
|
-
${guidanceDirs.map(d => ` - ${d}`).join('\n')}
|
|
284
|
-
namespace: guidance
|
|
285
|
-
|
|
286
|
-
# Source directories for code navigation map
|
|
287
|
-
code_map:
|
|
288
|
-
directories:
|
|
289
|
-
${srcDirs.map(d => ` - ${d}`).join('\n')}
|
|
290
|
-
extensions: [${detectedExts.map(e => `"${e}"`).join(', ')}]
|
|
291
|
-
exclude: [node_modules, dist, .next, coverage, build, __pycache__, target, .git]
|
|
292
|
-
namespace: code-map
|
|
293
|
-
|
|
294
|
-
# Test file discovery and indexing
|
|
295
|
-
tests:
|
|
296
|
-
directories:
|
|
297
|
-
${testDirs.map(d => ` - ${d}`).join('\n')}
|
|
298
|
-
patterns: ["*.test.*", "*.spec.*", "*.test-*"]
|
|
299
|
-
extensions: [".ts", ".tsx", ".js", ".jsx"]
|
|
300
|
-
exclude: [node_modules, coverage, dist]
|
|
301
|
-
namespace: tests
|
|
302
|
-
|
|
303
|
-
# Workflow gates (enforced via Claude Code hooks)
|
|
304
|
-
gates:
|
|
305
|
-
memory_first: ${gatesEnabled}
|
|
306
|
-
task_create_first: ${gatesEnabled}
|
|
307
|
-
context_tracking: ${gatesEnabled}
|
|
308
|
-
|
|
309
|
-
# Auto-index on session start
|
|
310
|
-
auto_index:
|
|
311
|
-
guidance: ${answers?.guidance ?? true}
|
|
312
|
-
code_map: ${answers?.codeMap ?? true}
|
|
313
|
-
tests: ${answers?.tests ?? true}
|
|
314
|
-
|
|
315
|
-
# Memory backend
|
|
316
|
-
memory:
|
|
317
|
-
backend: sql.js
|
|
318
|
-
embedding_model: Xenova/all-MiniLM-L6-v2
|
|
319
|
-
namespace: default
|
|
320
|
-
|
|
321
|
-
# Hook toggles (all on by default — disable to slim down)
|
|
322
|
-
hooks:
|
|
323
|
-
pre_edit: true # Track file edits for learning
|
|
324
|
-
post_edit: true # Record edit outcomes, train neural patterns
|
|
325
|
-
pre_task: true # Get agent routing before task spawn
|
|
326
|
-
post_task: true # Record task results for learning
|
|
327
|
-
gate: ${gatesEnabled} # Workflow gate enforcement (memory-first, task-create-first)
|
|
328
|
-
route: true # Intelligent task routing on each prompt
|
|
329
|
-
stop_hook: ${answers?.stopHook ?? true} # Session-end persistence and metric export
|
|
330
|
-
session_restore: true # Restore session state on start
|
|
331
|
-
notification: true # Hook into Claude Code notifications
|
|
332
|
-
|
|
333
|
-
# MCP server options
|
|
334
|
-
mcp:
|
|
335
|
-
tool_defer: deferred # Defer 150+ tool schemas; loaded on demand via ToolSearch
|
|
336
|
-
auto_start: false # Auto-start MCP server on session begin
|
|
337
|
-
|
|
338
|
-
# Status line display (shown at bottom of Claude Code)
|
|
339
|
-
# mode: "compact" (default), "single-line", or "dashboard" (full multi-line)
|
|
340
|
-
status_line:
|
|
341
|
-
enabled: true
|
|
342
|
-
mode: compact
|
|
343
|
-
branding: "MoFlo V4"
|
|
344
|
-
show_git: true
|
|
345
|
-
show_session: true
|
|
346
|
-
show_swarm: true
|
|
347
|
-
show_agentdb: true
|
|
348
|
-
show_mcp: true
|
|
349
|
-
|
|
350
|
-
# Model preferences (haiku, sonnet, opus)
|
|
351
|
-
models:
|
|
352
|
-
default: opus # Model for general tasks
|
|
353
|
-
research: sonnet # Model for research/exploration agents
|
|
354
|
-
review: opus # Model for code review agents
|
|
355
|
-
test: sonnet # Model for test-writing agents
|
|
356
|
-
|
|
357
|
-
# Intelligent model routing (auto-selects haiku/sonnet/opus per task)
|
|
358
|
-
# When enabled, overrides the static model preferences above
|
|
359
|
-
# by analyzing task complexity and routing to the cheapest capable model.
|
|
360
|
-
model_routing:
|
|
361
|
-
enabled: false # Set to true to enable dynamic routing
|
|
362
|
-
confidence_threshold: 0.85 # Min confidence before escalating to a more capable model
|
|
363
|
-
cost_optimization: true # Prefer cheaper models when confidence is high
|
|
364
|
-
circuit_breaker: true # Penalize models that fail repeatedly
|
|
365
|
-
# Per-agent overrides (set to "inherit" to use routing, or a specific model to pin)
|
|
366
|
-
# agent_overrides:
|
|
367
|
-
# security-architect: opus # Always use opus for security
|
|
368
|
-
# researcher: sonnet # Pin research to sonnet
|
|
369
|
-
`;
|
|
370
|
-
fs.writeFileSync(configPath, yaml, 'utf-8');
|
|
371
|
-
return { name: 'moflo.yaml', status: 'created', detail: `Detected: ${srcDirs.join(', ')} | ${detectedExts.join(', ')}` };
|
|
372
|
-
}
|
|
373
|
-
function scanExtensions(dir, extensions, depth, maxDepth) {
|
|
374
|
-
if (depth > maxDepth)
|
|
375
|
-
return;
|
|
376
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
377
|
-
for (const entry of entries.slice(0, 100)) {
|
|
378
|
-
if (entry.isDirectory() && !['node_modules', '.git', 'dist', 'build'].includes(entry.name)) {
|
|
379
|
-
scanExtensions(path.join(dir, entry.name), extensions, depth + 1, maxDepth);
|
|
380
|
-
}
|
|
381
|
-
else if (entry.isFile()) {
|
|
382
|
-
const ext = path.extname(entry.name);
|
|
383
|
-
if (['.ts', '.tsx', '.js', '.jsx', '.py', '.go', '.rs', '.java', '.kt', '.swift', '.rb', '.cs'].includes(ext)) {
|
|
384
|
-
extensions.add(ext);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
// ============================================================================
|
|
390
|
-
// Step 2: .claude/settings.json hooks
|
|
391
|
-
// ============================================================================
|
|
392
|
-
function generateHooks(root, force, answers) {
|
|
393
|
-
const settingsPath = path.join(root, '.claude', 'settings.json');
|
|
394
|
-
const settingsDir = path.dirname(settingsPath);
|
|
395
|
-
if (!fs.existsSync(settingsDir)) {
|
|
396
|
-
fs.mkdirSync(settingsDir, { recursive: true });
|
|
397
|
-
}
|
|
398
|
-
let existing = {};
|
|
399
|
-
if (fs.existsSync(settingsPath)) {
|
|
400
|
-
try {
|
|
401
|
-
existing = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
402
|
-
}
|
|
403
|
-
catch { /* start fresh */ }
|
|
404
|
-
// Check if MoFlo hooks already set up
|
|
405
|
-
const settingsStr = JSON.stringify(existing);
|
|
406
|
-
const hasGateHooks = settingsStr.includes('flo gate') || settingsStr.includes('moflo gate');
|
|
407
|
-
if (hasGateHooks && !force) {
|
|
408
|
-
return { name: '.claude/settings.json', status: 'skipped', detail: 'MoFlo hooks already configured' };
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
// Build hooks config — all on by default (opinionated pit-of-success)
|
|
412
|
-
const hooks = {
|
|
413
|
-
"PreToolUse": [
|
|
414
|
-
{
|
|
415
|
-
"matcher": "^(Write|Edit|MultiEdit)$",
|
|
416
|
-
"hooks": [{
|
|
417
|
-
"type": "command",
|
|
418
|
-
"command": "npx flo hooks pre-edit",
|
|
419
|
-
"timeout": 5000
|
|
420
|
-
}]
|
|
421
|
-
},
|
|
422
|
-
{
|
|
423
|
-
"matcher": "^(Glob|Grep)$",
|
|
424
|
-
"hooks": [{
|
|
425
|
-
"type": "command",
|
|
426
|
-
"command": "npx flo gate check-before-scan",
|
|
427
|
-
"timeout": 3000
|
|
428
|
-
}]
|
|
429
|
-
},
|
|
430
|
-
{
|
|
431
|
-
"matcher": "^Read$",
|
|
432
|
-
"hooks": [{
|
|
433
|
-
"type": "command",
|
|
434
|
-
"command": "npx flo gate check-before-read",
|
|
435
|
-
"timeout": 3000
|
|
436
|
-
}]
|
|
437
|
-
},
|
|
438
|
-
{
|
|
439
|
-
"matcher": "^Task$",
|
|
440
|
-
"hooks": [
|
|
441
|
-
{
|
|
442
|
-
"type": "command",
|
|
443
|
-
"command": "npx flo gate check-before-agent",
|
|
444
|
-
"timeout": 3000
|
|
445
|
-
},
|
|
446
|
-
{
|
|
447
|
-
"type": "command",
|
|
448
|
-
"command": "npx flo hooks pre-task",
|
|
449
|
-
"timeout": 5000
|
|
450
|
-
}
|
|
451
|
-
]
|
|
452
|
-
},
|
|
453
|
-
{
|
|
454
|
-
"matcher": "^Bash$",
|
|
455
|
-
"hooks": [{
|
|
456
|
-
"type": "command",
|
|
457
|
-
"command": "npx flo gate check-dangerous-command",
|
|
458
|
-
"timeout": 2000
|
|
459
|
-
}]
|
|
460
|
-
}
|
|
461
|
-
],
|
|
462
|
-
"PostToolUse": [
|
|
463
|
-
{
|
|
464
|
-
"matcher": "^(Write|Edit|MultiEdit)$",
|
|
465
|
-
"hooks": [{
|
|
466
|
-
"type": "command",
|
|
467
|
-
"command": "npx flo hooks post-edit",
|
|
468
|
-
"timeout": 5000
|
|
469
|
-
}]
|
|
470
|
-
},
|
|
471
|
-
{
|
|
472
|
-
"matcher": "^Task$",
|
|
473
|
-
"hooks": [{
|
|
474
|
-
"type": "command",
|
|
475
|
-
"command": "npx flo hooks post-task",
|
|
476
|
-
"timeout": 5000
|
|
477
|
-
}]
|
|
478
|
-
},
|
|
479
|
-
{
|
|
480
|
-
"matcher": "^TaskCreate$",
|
|
481
|
-
"hooks": [{
|
|
482
|
-
"type": "command",
|
|
483
|
-
"command": "npx flo gate record-task-created",
|
|
484
|
-
"timeout": 2000
|
|
485
|
-
}]
|
|
486
|
-
},
|
|
487
|
-
{
|
|
488
|
-
"matcher": "^Bash$",
|
|
489
|
-
"hooks": [{
|
|
490
|
-
"type": "command",
|
|
491
|
-
"command": "npx flo gate check-bash-memory",
|
|
492
|
-
"timeout": 2000
|
|
493
|
-
}]
|
|
494
|
-
},
|
|
495
|
-
{
|
|
496
|
-
"matcher": "^mcp__moflo__memory_(search|retrieve)$",
|
|
497
|
-
"hooks": [{
|
|
498
|
-
"type": "command",
|
|
499
|
-
"command": "npx flo gate record-memory-searched",
|
|
500
|
-
"timeout": 2000
|
|
501
|
-
}]
|
|
502
|
-
}
|
|
503
|
-
],
|
|
504
|
-
"UserPromptSubmit": [
|
|
505
|
-
{
|
|
506
|
-
"hooks": [
|
|
507
|
-
{
|
|
508
|
-
"type": "command",
|
|
509
|
-
"command": "npx flo gate prompt-reminder",
|
|
510
|
-
"timeout": 2000
|
|
511
|
-
},
|
|
512
|
-
{
|
|
513
|
-
"type": "command",
|
|
514
|
-
"command": "npx flo hooks route",
|
|
515
|
-
"timeout": 5000
|
|
516
|
-
}
|
|
517
|
-
]
|
|
518
|
-
}
|
|
519
|
-
],
|
|
520
|
-
"SessionStart": [
|
|
521
|
-
{
|
|
522
|
-
"hooks": [
|
|
523
|
-
{
|
|
524
|
-
"type": "command",
|
|
525
|
-
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/scripts/session-start-launcher.mjs\"",
|
|
526
|
-
"timeout": 3000
|
|
527
|
-
}
|
|
528
|
-
]
|
|
529
|
-
}
|
|
530
|
-
],
|
|
531
|
-
"Stop": [
|
|
532
|
-
{
|
|
533
|
-
"hooks": [{
|
|
534
|
-
"type": "command",
|
|
535
|
-
"command": "npx flo hooks session-end",
|
|
536
|
-
"timeout": 5000
|
|
537
|
-
}]
|
|
538
|
-
}
|
|
539
|
-
],
|
|
540
|
-
"PreCompact": [
|
|
541
|
-
{
|
|
542
|
-
"hooks": [{
|
|
543
|
-
"type": "command",
|
|
544
|
-
"command": "npx flo gate compact-guidance",
|
|
545
|
-
"timeout": 3000
|
|
546
|
-
}]
|
|
547
|
-
}
|
|
548
|
-
],
|
|
549
|
-
"Notification": [
|
|
550
|
-
{
|
|
551
|
-
"hooks": [{
|
|
552
|
-
"type": "command",
|
|
553
|
-
"command": "npx flo hooks notification",
|
|
554
|
-
"timeout": 3000
|
|
555
|
-
}]
|
|
556
|
-
}
|
|
557
|
-
]
|
|
558
|
-
};
|
|
559
|
-
// Merge: preserve existing non-MoFlo hooks, add MoFlo hooks
|
|
560
|
-
existing.hooks = hooks;
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
//
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
return
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
const
|
|
786
|
-
const
|
|
787
|
-
if (
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
const
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
fs.
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
1
|
+
/**
|
|
2
|
+
* MoFlo Project Initializer
|
|
3
|
+
*
|
|
4
|
+
* One-stop setup that makes MoFlo work out of the box:
|
|
5
|
+
* 1. Generate moflo.yaml (project config)
|
|
6
|
+
* 2. Set up .claude/settings.json hooks
|
|
7
|
+
* 3. Create .claude/skills/flo/ skill (with /fl alias)
|
|
8
|
+
* 4. Append MoFlo section to CLAUDE.md
|
|
9
|
+
* 5. Initialize memory DB
|
|
10
|
+
* 6. Auto-index guidance + code map
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from 'fs';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Init
|
|
17
|
+
// ============================================================================
|
|
18
|
+
/**
|
|
19
|
+
* Discover guidance directories by checking top-level candidates AND walking
|
|
20
|
+
* the project tree for subproject .claude/guidance dirs (monorepo support).
|
|
21
|
+
*/
|
|
22
|
+
function discoverGuidanceDirs(root) {
|
|
23
|
+
const TOP_LEVEL = ['.claude/guidance', 'docs/guides', 'docs', 'architecture', 'adr', '.cursor/rules'];
|
|
24
|
+
const found = TOP_LEVEL.filter(d => fs.existsSync(path.join(root, d)));
|
|
25
|
+
// Walk up to 3 levels deep looking for .claude/guidance in subprojects
|
|
26
|
+
const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.reports', '.swarm', '.claude-flow', 'packages']);
|
|
27
|
+
function walk(dir, depth) {
|
|
28
|
+
if (depth > 3)
|
|
29
|
+
return;
|
|
30
|
+
try {
|
|
31
|
+
const entries = fs.readdirSync(path.join(root, dir), { withFileTypes: true });
|
|
32
|
+
for (const entry of entries) {
|
|
33
|
+
if (!entry.isDirectory() || SKIP.has(entry.name))
|
|
34
|
+
continue;
|
|
35
|
+
const rel = dir ? `${dir}/${entry.name}` : entry.name;
|
|
36
|
+
const guidancePath = `${rel}/.claude/guidance`;
|
|
37
|
+
if (fs.existsSync(path.join(root, guidancePath))) {
|
|
38
|
+
// Verify it has .md files
|
|
39
|
+
try {
|
|
40
|
+
const files = fs.readdirSync(path.join(root, guidancePath));
|
|
41
|
+
if (files.some(f => f.endsWith('.md')))
|
|
42
|
+
found.push(guidancePath);
|
|
43
|
+
}
|
|
44
|
+
catch { /* skip unreadable */ }
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
walk(rel, depth + 1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch { /* skip unreadable directories */ }
|
|
52
|
+
}
|
|
53
|
+
walk('', 0);
|
|
54
|
+
return found;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Discover test directories by checking common locations and walking for
|
|
58
|
+
* colocated __tests__ dirs. Returns relative paths.
|
|
59
|
+
*/
|
|
60
|
+
export function discoverTestDirs(root) {
|
|
61
|
+
const TOP_LEVEL = ['tests', 'test', '__tests__', 'spec', 'e2e'];
|
|
62
|
+
const found = TOP_LEVEL.filter(d => fs.existsSync(path.join(root, d)));
|
|
63
|
+
// Walk up to 3 levels deep looking for __tests__ dirs inside src
|
|
64
|
+
const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.reports', '.swarm', '.claude-flow']);
|
|
65
|
+
function walk(dir, depth) {
|
|
66
|
+
if (depth > 3)
|
|
67
|
+
return;
|
|
68
|
+
try {
|
|
69
|
+
const entries = fs.readdirSync(path.join(root, dir), { withFileTypes: true });
|
|
70
|
+
for (const entry of entries) {
|
|
71
|
+
if (!entry.isDirectory() || SKIP.has(entry.name))
|
|
72
|
+
continue;
|
|
73
|
+
const rel = dir ? `${dir}/${entry.name}` : entry.name;
|
|
74
|
+
if (entry.name === '__tests__') {
|
|
75
|
+
found.push(rel);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
walk(rel, depth + 1);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch { /* skip unreadable directories */ }
|
|
83
|
+
}
|
|
84
|
+
walk('', 0);
|
|
85
|
+
return found;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Discover source directories by walking the project tree.
|
|
89
|
+
* Finds directories named 'src' (or top-level 'packages', 'lib', etc.)
|
|
90
|
+
* that contain .ts/.tsx/.js/.jsx files. Skips node_modules, dist, etc.
|
|
91
|
+
*/
|
|
92
|
+
function discoverSrcDirs(root) {
|
|
93
|
+
const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.reports', '.swarm', '.claude-flow']);
|
|
94
|
+
// Top-level candidates that are always source roots if they exist
|
|
95
|
+
const TOP_LEVEL = ['packages', 'lib', 'app', 'apps', 'services', 'server', 'client'];
|
|
96
|
+
const found = [];
|
|
97
|
+
// Add top-level candidates first
|
|
98
|
+
for (const d of TOP_LEVEL) {
|
|
99
|
+
if (fs.existsSync(path.join(root, d)))
|
|
100
|
+
found.push(d);
|
|
101
|
+
}
|
|
102
|
+
// Walk up to 3 levels deep looking for 'src' and 'migrations' directories
|
|
103
|
+
const SRC_NAMES = new Set(['src', 'migrations']);
|
|
104
|
+
function walk(dir, depth) {
|
|
105
|
+
if (depth > 3)
|
|
106
|
+
return;
|
|
107
|
+
try {
|
|
108
|
+
const entries = fs.readdirSync(path.join(root, dir), { withFileTypes: true });
|
|
109
|
+
for (const entry of entries) {
|
|
110
|
+
if (!entry.isDirectory() || SKIP.has(entry.name))
|
|
111
|
+
continue;
|
|
112
|
+
const rel = dir ? `${dir}/${entry.name}` : entry.name;
|
|
113
|
+
if (SRC_NAMES.has(entry.name)) {
|
|
114
|
+
// Check it actually has source files
|
|
115
|
+
try {
|
|
116
|
+
const files = fs.readdirSync(path.join(root, rel));
|
|
117
|
+
const hasSource = files.some(f => /\.(ts|tsx|js|jsx)$/.test(f));
|
|
118
|
+
if (hasSource)
|
|
119
|
+
found.push(rel);
|
|
120
|
+
}
|
|
121
|
+
catch { /* skip unreadable */ }
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
walk(rel, depth + 1);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch { /* skip unreadable directories */ }
|
|
129
|
+
}
|
|
130
|
+
walk('', 0);
|
|
131
|
+
// Deduplicate: if 'packages' is found, don't also include 'packages/foo/src'
|
|
132
|
+
// since the code-map walker handles subdirs
|
|
133
|
+
return found.filter(d => {
|
|
134
|
+
return !found.some(other => other !== d && d.startsWith(other + '/'));
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Run interactive wizard to collect user preferences.
|
|
139
|
+
*/
|
|
140
|
+
async function runWizard(root) {
|
|
141
|
+
const { confirm, input } = await import('../prompt.js');
|
|
142
|
+
// Detect project structure
|
|
143
|
+
const detectedGuidance = discoverGuidanceDirs(root);
|
|
144
|
+
const detectedSrc = discoverSrcDirs(root);
|
|
145
|
+
// Ask questions
|
|
146
|
+
const guidance = await confirm({
|
|
147
|
+
message: detectedGuidance.length > 0
|
|
148
|
+
? `Found guidance docs in ${detectedGuidance.join(', ')}. Enable guidance indexing?`
|
|
149
|
+
: 'Do you have project guidance/documentation to index?',
|
|
150
|
+
default: true,
|
|
151
|
+
});
|
|
152
|
+
let guidanceDirs = detectedGuidance.length > 0 ? detectedGuidance : ['.claude/guidance'];
|
|
153
|
+
if (guidance) {
|
|
154
|
+
const answer = await input({
|
|
155
|
+
message: 'Guidance directories (comma-separated):',
|
|
156
|
+
default: guidanceDirs.join(', '),
|
|
157
|
+
});
|
|
158
|
+
guidanceDirs = answer.split(',').map((d) => d.trim()).filter(Boolean);
|
|
159
|
+
}
|
|
160
|
+
const codeMap = await confirm({
|
|
161
|
+
message: detectedSrc.length > 0
|
|
162
|
+
? `Found source in ${detectedSrc.join(', ')}. Enable code map for navigation?`
|
|
163
|
+
: 'Enable code map for codebase navigation?',
|
|
164
|
+
default: true,
|
|
165
|
+
});
|
|
166
|
+
let srcDirs = detectedSrc.length > 0 ? detectedSrc : ['src'];
|
|
167
|
+
if (codeMap) {
|
|
168
|
+
const answer = await input({
|
|
169
|
+
message: 'Source directories (comma-separated):',
|
|
170
|
+
default: srcDirs.join(', '),
|
|
171
|
+
});
|
|
172
|
+
srcDirs = answer.split(',').map((d) => d.trim()).filter(Boolean);
|
|
173
|
+
}
|
|
174
|
+
// Detect test directories
|
|
175
|
+
const detectedTests = discoverTestDirs(root);
|
|
176
|
+
const tests = await confirm({
|
|
177
|
+
message: detectedTests.length > 0
|
|
178
|
+
? `Found tests in ${detectedTests.join(', ')}. Enable test file indexing?`
|
|
179
|
+
: 'Enable test file indexing?',
|
|
180
|
+
default: true,
|
|
181
|
+
});
|
|
182
|
+
let testDirs = detectedTests.length > 0 ? detectedTests : ['tests'];
|
|
183
|
+
if (tests) {
|
|
184
|
+
const answer = await input({
|
|
185
|
+
message: 'Test directories (comma-separated):',
|
|
186
|
+
default: testDirs.join(', '),
|
|
187
|
+
});
|
|
188
|
+
testDirs = answer.split(',').map((d) => d.trim()).filter(Boolean);
|
|
189
|
+
}
|
|
190
|
+
const gates = await confirm({
|
|
191
|
+
message: 'Enable workflow gates (memory-first, task-create-before-agents)?',
|
|
192
|
+
default: true,
|
|
193
|
+
});
|
|
194
|
+
const stopHook = await confirm({
|
|
195
|
+
message: 'Enable session-end hook (saves session state)?',
|
|
196
|
+
default: true,
|
|
197
|
+
});
|
|
198
|
+
return { guidance, guidanceDirs, codeMap, srcDirs, tests, testDirs, gates, stopHook };
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Get default answers (--yes mode).
|
|
202
|
+
*/
|
|
203
|
+
function defaultAnswers(root) {
|
|
204
|
+
const guidanceDirs = discoverGuidanceDirs(root);
|
|
205
|
+
if (guidanceDirs.length === 0)
|
|
206
|
+
guidanceDirs.push('.claude/guidance');
|
|
207
|
+
const srcDirs = discoverSrcDirs(root);
|
|
208
|
+
if (srcDirs.length === 0)
|
|
209
|
+
srcDirs.push('src');
|
|
210
|
+
const testDirs = discoverTestDirs(root);
|
|
211
|
+
if (testDirs.length === 0)
|
|
212
|
+
testDirs.push('tests');
|
|
213
|
+
return { guidance: true, guidanceDirs, codeMap: true, srcDirs, tests: true, testDirs, gates: true, stopHook: true };
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Get minimal answers (--minimal mode).
|
|
217
|
+
*/
|
|
218
|
+
function minimalAnswers() {
|
|
219
|
+
return { guidance: false, guidanceDirs: [], codeMap: false, srcDirs: [], tests: false, testDirs: [], gates: false, stopHook: false };
|
|
220
|
+
}
|
|
221
|
+
export async function initMoflo(options) {
|
|
222
|
+
const { projectRoot, force, interactive, minimal } = options;
|
|
223
|
+
const steps = [];
|
|
224
|
+
// Collect answers based on mode
|
|
225
|
+
const answers = minimal
|
|
226
|
+
? minimalAnswers()
|
|
227
|
+
: interactive
|
|
228
|
+
? await runWizard(projectRoot)
|
|
229
|
+
: defaultAnswers(projectRoot);
|
|
230
|
+
// Step 1: moflo.yaml
|
|
231
|
+
steps.push(generateConfig(projectRoot, force, answers));
|
|
232
|
+
// Step 2: .claude/settings.json hooks
|
|
233
|
+
steps.push(generateHooks(projectRoot, force, answers));
|
|
234
|
+
// Step 3: .claude/skills/flo/ (with /fl alias)
|
|
235
|
+
steps.push(generateSkill(projectRoot, force));
|
|
236
|
+
// Step 4: CLAUDE.md MoFlo section
|
|
237
|
+
steps.push(generateClaudeMd(projectRoot, force));
|
|
238
|
+
// Step 5: .claude/scripts/ from moflo bin/
|
|
239
|
+
steps.push(syncScripts(projectRoot, force));
|
|
240
|
+
// Step 6: .gitignore entries
|
|
241
|
+
steps.push(updateGitignore(projectRoot));
|
|
242
|
+
// Step 7: .claude/guidance/moflo-bootstrap.md (subagent bootstrap protocol)
|
|
243
|
+
steps.push(syncBootstrapGuidance(projectRoot, force));
|
|
244
|
+
return { steps };
|
|
245
|
+
}
|
|
246
|
+
// ============================================================================
|
|
247
|
+
// Step 1: moflo.yaml
|
|
248
|
+
// ============================================================================
|
|
249
|
+
function generateConfig(root, force, answers) {
|
|
250
|
+
const configPath = path.join(root, 'moflo.yaml');
|
|
251
|
+
if (fs.existsSync(configPath) && !force) {
|
|
252
|
+
return { name: 'moflo.yaml', status: 'skipped', detail: 'Already exists (use --force to overwrite)' };
|
|
253
|
+
}
|
|
254
|
+
const projectName = path.basename(root);
|
|
255
|
+
const guidanceDirs = answers?.guidanceDirs ?? ['.claude/guidance'];
|
|
256
|
+
const srcDirs = answers?.srcDirs ?? ['src'];
|
|
257
|
+
const testDirs = answers?.testDirs ?? ['tests'];
|
|
258
|
+
const gatesEnabled = answers?.gates ?? true;
|
|
259
|
+
// Detect languages
|
|
260
|
+
const extensions = new Set();
|
|
261
|
+
for (const dir of srcDirs) {
|
|
262
|
+
const fullDir = path.join(root, dir);
|
|
263
|
+
if (fs.existsSync(fullDir)) {
|
|
264
|
+
try {
|
|
265
|
+
scanExtensions(fullDir, extensions, 0, 3);
|
|
266
|
+
}
|
|
267
|
+
catch { /* skip */ }
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const detectedExts = extensions.size > 0
|
|
271
|
+
? [...extensions].sort()
|
|
272
|
+
: ['.ts', '.tsx', '.js', '.jsx'];
|
|
273
|
+
const yaml = `# MoFlo — Project Configuration
|
|
274
|
+
# Generated by: moflo init
|
|
275
|
+
# Docs: https://github.com/eric-cielo/moflo
|
|
276
|
+
|
|
277
|
+
project:
|
|
278
|
+
name: "${projectName}"
|
|
279
|
+
|
|
280
|
+
# Guidance/knowledge docs to index for semantic search
|
|
281
|
+
guidance:
|
|
282
|
+
directories:
|
|
283
|
+
${guidanceDirs.map(d => ` - ${d}`).join('\n')}
|
|
284
|
+
namespace: guidance
|
|
285
|
+
|
|
286
|
+
# Source directories for code navigation map
|
|
287
|
+
code_map:
|
|
288
|
+
directories:
|
|
289
|
+
${srcDirs.map(d => ` - ${d}`).join('\n')}
|
|
290
|
+
extensions: [${detectedExts.map(e => `"${e}"`).join(', ')}]
|
|
291
|
+
exclude: [node_modules, dist, .next, coverage, build, __pycache__, target, .git]
|
|
292
|
+
namespace: code-map
|
|
293
|
+
|
|
294
|
+
# Test file discovery and indexing
|
|
295
|
+
tests:
|
|
296
|
+
directories:
|
|
297
|
+
${testDirs.map(d => ` - ${d}`).join('\n')}
|
|
298
|
+
patterns: ["*.test.*", "*.spec.*", "*.test-*"]
|
|
299
|
+
extensions: [".ts", ".tsx", ".js", ".jsx"]
|
|
300
|
+
exclude: [node_modules, coverage, dist]
|
|
301
|
+
namespace: tests
|
|
302
|
+
|
|
303
|
+
# Workflow gates (enforced via Claude Code hooks)
|
|
304
|
+
gates:
|
|
305
|
+
memory_first: ${gatesEnabled}
|
|
306
|
+
task_create_first: ${gatesEnabled}
|
|
307
|
+
context_tracking: ${gatesEnabled}
|
|
308
|
+
|
|
309
|
+
# Auto-index on session start
|
|
310
|
+
auto_index:
|
|
311
|
+
guidance: ${answers?.guidance ?? true}
|
|
312
|
+
code_map: ${answers?.codeMap ?? true}
|
|
313
|
+
tests: ${answers?.tests ?? true}
|
|
314
|
+
|
|
315
|
+
# Memory backend
|
|
316
|
+
memory:
|
|
317
|
+
backend: sql.js
|
|
318
|
+
embedding_model: Xenova/all-MiniLM-L6-v2
|
|
319
|
+
namespace: default
|
|
320
|
+
|
|
321
|
+
# Hook toggles (all on by default — disable to slim down)
|
|
322
|
+
hooks:
|
|
323
|
+
pre_edit: true # Track file edits for learning
|
|
324
|
+
post_edit: true # Record edit outcomes, train neural patterns
|
|
325
|
+
pre_task: true # Get agent routing before task spawn
|
|
326
|
+
post_task: true # Record task results for learning
|
|
327
|
+
gate: ${gatesEnabled} # Workflow gate enforcement (memory-first, task-create-first)
|
|
328
|
+
route: true # Intelligent task routing on each prompt
|
|
329
|
+
stop_hook: ${answers?.stopHook ?? true} # Session-end persistence and metric export
|
|
330
|
+
session_restore: true # Restore session state on start
|
|
331
|
+
notification: true # Hook into Claude Code notifications
|
|
332
|
+
|
|
333
|
+
# MCP server options
|
|
334
|
+
mcp:
|
|
335
|
+
tool_defer: deferred # Defer 150+ tool schemas; loaded on demand via ToolSearch
|
|
336
|
+
auto_start: false # Auto-start MCP server on session begin
|
|
337
|
+
|
|
338
|
+
# Status line display (shown at bottom of Claude Code)
|
|
339
|
+
# mode: "compact" (default), "single-line", or "dashboard" (full multi-line)
|
|
340
|
+
status_line:
|
|
341
|
+
enabled: true
|
|
342
|
+
mode: compact
|
|
343
|
+
branding: "MoFlo V4"
|
|
344
|
+
show_git: true
|
|
345
|
+
show_session: true
|
|
346
|
+
show_swarm: true
|
|
347
|
+
show_agentdb: true
|
|
348
|
+
show_mcp: true
|
|
349
|
+
|
|
350
|
+
# Model preferences (haiku, sonnet, opus)
|
|
351
|
+
models:
|
|
352
|
+
default: opus # Model for general tasks
|
|
353
|
+
research: sonnet # Model for research/exploration agents
|
|
354
|
+
review: opus # Model for code review agents
|
|
355
|
+
test: sonnet # Model for test-writing agents
|
|
356
|
+
|
|
357
|
+
# Intelligent model routing (auto-selects haiku/sonnet/opus per task)
|
|
358
|
+
# When enabled, overrides the static model preferences above
|
|
359
|
+
# by analyzing task complexity and routing to the cheapest capable model.
|
|
360
|
+
model_routing:
|
|
361
|
+
enabled: false # Set to true to enable dynamic routing
|
|
362
|
+
confidence_threshold: 0.85 # Min confidence before escalating to a more capable model
|
|
363
|
+
cost_optimization: true # Prefer cheaper models when confidence is high
|
|
364
|
+
circuit_breaker: true # Penalize models that fail repeatedly
|
|
365
|
+
# Per-agent overrides (set to "inherit" to use routing, or a specific model to pin)
|
|
366
|
+
# agent_overrides:
|
|
367
|
+
# security-architect: opus # Always use opus for security
|
|
368
|
+
# researcher: sonnet # Pin research to sonnet
|
|
369
|
+
`;
|
|
370
|
+
fs.writeFileSync(configPath, yaml, 'utf-8');
|
|
371
|
+
return { name: 'moflo.yaml', status: 'created', detail: `Detected: ${srcDirs.join(', ')} | ${detectedExts.join(', ')}` };
|
|
372
|
+
}
|
|
373
|
+
function scanExtensions(dir, extensions, depth, maxDepth) {
|
|
374
|
+
if (depth > maxDepth)
|
|
375
|
+
return;
|
|
376
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
377
|
+
for (const entry of entries.slice(0, 100)) {
|
|
378
|
+
if (entry.isDirectory() && !['node_modules', '.git', 'dist', 'build'].includes(entry.name)) {
|
|
379
|
+
scanExtensions(path.join(dir, entry.name), extensions, depth + 1, maxDepth);
|
|
380
|
+
}
|
|
381
|
+
else if (entry.isFile()) {
|
|
382
|
+
const ext = path.extname(entry.name);
|
|
383
|
+
if (['.ts', '.tsx', '.js', '.jsx', '.py', '.go', '.rs', '.java', '.kt', '.swift', '.rb', '.cs'].includes(ext)) {
|
|
384
|
+
extensions.add(ext);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
// ============================================================================
|
|
390
|
+
// Step 2: .claude/settings.json hooks
|
|
391
|
+
// ============================================================================
|
|
392
|
+
function generateHooks(root, force, answers) {
|
|
393
|
+
const settingsPath = path.join(root, '.claude', 'settings.json');
|
|
394
|
+
const settingsDir = path.dirname(settingsPath);
|
|
395
|
+
if (!fs.existsSync(settingsDir)) {
|
|
396
|
+
fs.mkdirSync(settingsDir, { recursive: true });
|
|
397
|
+
}
|
|
398
|
+
let existing = {};
|
|
399
|
+
if (fs.existsSync(settingsPath)) {
|
|
400
|
+
try {
|
|
401
|
+
existing = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
402
|
+
}
|
|
403
|
+
catch { /* start fresh */ }
|
|
404
|
+
// Check if MoFlo hooks already set up
|
|
405
|
+
const settingsStr = JSON.stringify(existing);
|
|
406
|
+
const hasGateHooks = settingsStr.includes('flo gate') || settingsStr.includes('moflo gate');
|
|
407
|
+
if (hasGateHooks && !force) {
|
|
408
|
+
return { name: '.claude/settings.json', status: 'skipped', detail: 'MoFlo hooks already configured' };
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
// Build hooks config — all on by default (opinionated pit-of-success)
|
|
412
|
+
const hooks = {
|
|
413
|
+
"PreToolUse": [
|
|
414
|
+
{
|
|
415
|
+
"matcher": "^(Write|Edit|MultiEdit)$",
|
|
416
|
+
"hooks": [{
|
|
417
|
+
"type": "command",
|
|
418
|
+
"command": "npx flo hooks pre-edit",
|
|
419
|
+
"timeout": 5000
|
|
420
|
+
}]
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
"matcher": "^(Glob|Grep)$",
|
|
424
|
+
"hooks": [{
|
|
425
|
+
"type": "command",
|
|
426
|
+
"command": "npx flo gate check-before-scan",
|
|
427
|
+
"timeout": 3000
|
|
428
|
+
}]
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
"matcher": "^Read$",
|
|
432
|
+
"hooks": [{
|
|
433
|
+
"type": "command",
|
|
434
|
+
"command": "npx flo gate check-before-read",
|
|
435
|
+
"timeout": 3000
|
|
436
|
+
}]
|
|
437
|
+
},
|
|
438
|
+
{
|
|
439
|
+
"matcher": "^Task$",
|
|
440
|
+
"hooks": [
|
|
441
|
+
{
|
|
442
|
+
"type": "command",
|
|
443
|
+
"command": "npx flo gate check-before-agent",
|
|
444
|
+
"timeout": 3000
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
"type": "command",
|
|
448
|
+
"command": "npx flo hooks pre-task",
|
|
449
|
+
"timeout": 5000
|
|
450
|
+
}
|
|
451
|
+
]
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
"matcher": "^Bash$",
|
|
455
|
+
"hooks": [{
|
|
456
|
+
"type": "command",
|
|
457
|
+
"command": "npx flo gate check-dangerous-command",
|
|
458
|
+
"timeout": 2000
|
|
459
|
+
}]
|
|
460
|
+
}
|
|
461
|
+
],
|
|
462
|
+
"PostToolUse": [
|
|
463
|
+
{
|
|
464
|
+
"matcher": "^(Write|Edit|MultiEdit)$",
|
|
465
|
+
"hooks": [{
|
|
466
|
+
"type": "command",
|
|
467
|
+
"command": "npx flo hooks post-edit",
|
|
468
|
+
"timeout": 5000
|
|
469
|
+
}]
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
"matcher": "^Task$",
|
|
473
|
+
"hooks": [{
|
|
474
|
+
"type": "command",
|
|
475
|
+
"command": "npx flo hooks post-task",
|
|
476
|
+
"timeout": 5000
|
|
477
|
+
}]
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
"matcher": "^TaskCreate$",
|
|
481
|
+
"hooks": [{
|
|
482
|
+
"type": "command",
|
|
483
|
+
"command": "npx flo gate record-task-created",
|
|
484
|
+
"timeout": 2000
|
|
485
|
+
}]
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
"matcher": "^Bash$",
|
|
489
|
+
"hooks": [{
|
|
490
|
+
"type": "command",
|
|
491
|
+
"command": "npx flo gate check-bash-memory",
|
|
492
|
+
"timeout": 2000
|
|
493
|
+
}]
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
"matcher": "^mcp__moflo__memory_(search|retrieve)$",
|
|
497
|
+
"hooks": [{
|
|
498
|
+
"type": "command",
|
|
499
|
+
"command": "npx flo gate record-memory-searched",
|
|
500
|
+
"timeout": 2000
|
|
501
|
+
}]
|
|
502
|
+
}
|
|
503
|
+
],
|
|
504
|
+
"UserPromptSubmit": [
|
|
505
|
+
{
|
|
506
|
+
"hooks": [
|
|
507
|
+
{
|
|
508
|
+
"type": "command",
|
|
509
|
+
"command": "npx flo gate prompt-reminder",
|
|
510
|
+
"timeout": 2000
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
"type": "command",
|
|
514
|
+
"command": "npx flo hooks route",
|
|
515
|
+
"timeout": 5000
|
|
516
|
+
}
|
|
517
|
+
]
|
|
518
|
+
}
|
|
519
|
+
],
|
|
520
|
+
"SessionStart": [
|
|
521
|
+
{
|
|
522
|
+
"hooks": [
|
|
523
|
+
{
|
|
524
|
+
"type": "command",
|
|
525
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/.claude/scripts/session-start-launcher.mjs\"",
|
|
526
|
+
"timeout": 3000
|
|
527
|
+
}
|
|
528
|
+
]
|
|
529
|
+
}
|
|
530
|
+
],
|
|
531
|
+
"Stop": [
|
|
532
|
+
{
|
|
533
|
+
"hooks": [{
|
|
534
|
+
"type": "command",
|
|
535
|
+
"command": "npx flo hooks session-end",
|
|
536
|
+
"timeout": 5000
|
|
537
|
+
}]
|
|
538
|
+
}
|
|
539
|
+
],
|
|
540
|
+
"PreCompact": [
|
|
541
|
+
{
|
|
542
|
+
"hooks": [{
|
|
543
|
+
"type": "command",
|
|
544
|
+
"command": "npx flo gate compact-guidance",
|
|
545
|
+
"timeout": 3000
|
|
546
|
+
}]
|
|
547
|
+
}
|
|
548
|
+
],
|
|
549
|
+
"Notification": [
|
|
550
|
+
{
|
|
551
|
+
"hooks": [{
|
|
552
|
+
"type": "command",
|
|
553
|
+
"command": "npx flo hooks notification",
|
|
554
|
+
"timeout": 3000
|
|
555
|
+
}]
|
|
556
|
+
}
|
|
557
|
+
]
|
|
558
|
+
};
|
|
559
|
+
// Merge: preserve existing non-MoFlo hooks, add MoFlo hooks
|
|
560
|
+
existing.hooks = hooks;
|
|
561
|
+
// Ensure statusLine is always present (required for dashboard display).
|
|
562
|
+
// The executor.ts / settings-generator.ts code path adds this, but
|
|
563
|
+
// moflo-init.ts uses its own generateHooks() which was missing it.
|
|
564
|
+
if (!existing.statusLine) {
|
|
565
|
+
existing.statusLine = {
|
|
566
|
+
type: 'command',
|
|
567
|
+
command: 'node "$CLAUDE_PROJECT_DIR/.claude/helpers/statusline.cjs"',
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
fs.writeFileSync(settingsPath, JSON.stringify(existing, null, 2), 'utf-8');
|
|
571
|
+
return { name: '.claude/settings.json', status: existing.hooks ? 'updated' : 'created', detail: '14 hooks configured (gates, lifecycle, routing, session)' };
|
|
572
|
+
}
|
|
573
|
+
// ============================================================================
|
|
574
|
+
// Step 3: .claude/skills/flo/ skill (with /fl alias)
|
|
575
|
+
// ============================================================================
|
|
576
|
+
function generateSkill(root, force) {
|
|
577
|
+
const skillDir = path.join(root, '.claude', 'skills', 'flo');
|
|
578
|
+
const skillFile = path.join(skillDir, 'SKILL.md');
|
|
579
|
+
const aliasDir = path.join(root, '.claude', 'skills', 'fl');
|
|
580
|
+
const aliasFile = path.join(aliasDir, 'SKILL.md');
|
|
581
|
+
if (fs.existsSync(skillFile) && !force) {
|
|
582
|
+
return { name: '.claude/skills/flo/', status: 'skipped', detail: 'Already exists' };
|
|
583
|
+
}
|
|
584
|
+
if (!fs.existsSync(skillDir)) {
|
|
585
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
586
|
+
}
|
|
587
|
+
// Copy static SKILL.md from moflo package instead of generating it
|
|
588
|
+
let skillContent = '';
|
|
589
|
+
// Resolve this file's directory in ESM-safe way
|
|
590
|
+
let thisDir;
|
|
591
|
+
try {
|
|
592
|
+
thisDir = path.dirname(fileURLToPath(import.meta.url));
|
|
593
|
+
}
|
|
594
|
+
catch {
|
|
595
|
+
// Fallback for CJS or environments where import.meta.url is unavailable
|
|
596
|
+
thisDir = typeof __dirname !== 'undefined' ? __dirname : '';
|
|
597
|
+
}
|
|
598
|
+
const staticSkillCandidates = [
|
|
599
|
+
// Installed via npm (most common)
|
|
600
|
+
path.join(root, 'node_modules', 'moflo', '.claude', 'skills', 'flo', 'SKILL.md'),
|
|
601
|
+
// Running from moflo repo itself (dev)
|
|
602
|
+
...(thisDir ? [path.join(thisDir, '..', '..', '..', '..', '.claude', 'skills', 'flo', 'SKILL.md')] : []),
|
|
603
|
+
];
|
|
604
|
+
for (const candidate of staticSkillCandidates) {
|
|
605
|
+
try {
|
|
606
|
+
if (fs.existsSync(candidate)) {
|
|
607
|
+
skillContent = fs.readFileSync(candidate, 'utf-8');
|
|
608
|
+
break;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
catch { /* skip inaccessible paths */ }
|
|
612
|
+
}
|
|
613
|
+
if (!skillContent) {
|
|
614
|
+
return { name: '.claude/skills/flo/', status: 'error', detail: 'Could not find SKILL.md in moflo package' };
|
|
615
|
+
}
|
|
616
|
+
fs.writeFileSync(skillFile, skillContent, 'utf-8');
|
|
617
|
+
// Create /fl alias (same content)
|
|
618
|
+
if (!fs.existsSync(aliasDir)) {
|
|
619
|
+
fs.mkdirSync(aliasDir, { recursive: true });
|
|
620
|
+
}
|
|
621
|
+
fs.writeFileSync(aliasFile, skillContent.replace('name: flo', 'name: fl'), 'utf-8');
|
|
622
|
+
// Clean up old /mf skill directory if it exists
|
|
623
|
+
const oldSkillDir = path.join(root, '.claude', 'skills', 'mf');
|
|
624
|
+
if (fs.existsSync(oldSkillDir)) {
|
|
625
|
+
fs.rmSync(oldSkillDir, { recursive: true });
|
|
626
|
+
}
|
|
627
|
+
return { name: '.claude/skills/flo/', status: 'created', detail: '/flo skill ready (alias: /fl)' };
|
|
628
|
+
}
|
|
629
|
+
// ============================================================================
|
|
630
|
+
// Step 4: CLAUDE.md MoFlo section
|
|
631
|
+
// ============================================================================
|
|
632
|
+
// Markers for idempotent CLAUDE.md injection — keep in sync with claudemd-generator.ts
|
|
633
|
+
const MOFLO_MARKER = '<!-- MOFLO:INJECTED:START -->';
|
|
634
|
+
const MOFLO_MARKER_END = '<!-- MOFLO:INJECTED:END -->';
|
|
635
|
+
// Also detect legacy markers so we can replace them
|
|
636
|
+
const LEGACY_MARKERS = ['<!-- MOFLO:START -->', '<!-- MOFLO:SUBAGENT-PROTOCOL:START -->'];
|
|
637
|
+
const LEGACY_MARKERS_END = ['<!-- MOFLO:END -->', '<!-- MOFLO:SUBAGENT-PROTOCOL:END -->'];
|
|
638
|
+
function generateClaudeMd(root, force) {
|
|
639
|
+
const claudeMdPath = path.join(root, 'CLAUDE.md');
|
|
640
|
+
let existing = '';
|
|
641
|
+
if (fs.existsSync(claudeMdPath)) {
|
|
642
|
+
existing = fs.readFileSync(claudeMdPath, 'utf-8');
|
|
643
|
+
// Check for current or legacy markers
|
|
644
|
+
const allStartMarkers = [MOFLO_MARKER, ...LEGACY_MARKERS];
|
|
645
|
+
const allEndMarkers = [MOFLO_MARKER_END, ...LEGACY_MARKERS_END];
|
|
646
|
+
for (let i = 0; i < allStartMarkers.length; i++) {
|
|
647
|
+
if (existing.includes(allStartMarkers[i])) {
|
|
648
|
+
if (!force && allStartMarkers[i] === MOFLO_MARKER) {
|
|
649
|
+
return { name: 'CLAUDE.md', status: 'skipped', detail: 'MoFlo section already present' };
|
|
650
|
+
}
|
|
651
|
+
// Remove existing section for replacement
|
|
652
|
+
const startIdx = existing.indexOf(allStartMarkers[i]);
|
|
653
|
+
const endIdx = existing.indexOf(allEndMarkers[i]);
|
|
654
|
+
if (endIdx > startIdx) {
|
|
655
|
+
existing = existing.substring(0, startIdx) + existing.substring(endIdx + allEndMarkers[i].length);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
// Minimal injection — just enough for Claude to work with moflo.
|
|
661
|
+
// All detailed docs live in .claude/guidance/shipped/moflo.md.
|
|
662
|
+
const mofloSection = `
|
|
663
|
+
${MOFLO_MARKER}
|
|
664
|
+
## MoFlo — AI Agent Orchestration
|
|
665
|
+
|
|
666
|
+
This project uses [MoFlo](https://github.com/eric-cielo/moflo) for AI-assisted development workflows.
|
|
667
|
+
|
|
668
|
+
### FIRST ACTION ON EVERY PROMPT: Search Memory
|
|
669
|
+
|
|
670
|
+
Your first tool call for every new user prompt MUST be a memory search. Do this BEFORE Glob, Grep, Read, or any file exploration.
|
|
671
|
+
|
|
672
|
+
\`\`\`
|
|
673
|
+
mcp__moflo__memory_search — query: "<task description>", namespace: "guidance" or "patterns" or "code-map"
|
|
674
|
+
\`\`\`
|
|
675
|
+
|
|
676
|
+
Search \`guidance\` and \`patterns\` namespaces on every prompt. Search \`code-map\` when navigating the codebase.
|
|
677
|
+
When the user asks you to remember something: \`mcp__moflo__memory_store\` with namespace \`knowledge\`.
|
|
678
|
+
|
|
679
|
+
### Workflow Gates (enforced automatically)
|
|
680
|
+
|
|
681
|
+
- **Memory-first**: Must search memory before Glob/Grep/Read
|
|
682
|
+
- **TaskCreate-first**: Must call TaskCreate before spawning Agent tool
|
|
683
|
+
|
|
684
|
+
### MCP Tools (preferred over CLI)
|
|
685
|
+
|
|
686
|
+
| Tool | Purpose |
|
|
687
|
+
|------|---------|
|
|
688
|
+
| \`mcp__moflo__memory_search\` | Semantic search across indexed knowledge |
|
|
689
|
+
| \`mcp__moflo__memory_store\` | Store patterns and decisions |
|
|
690
|
+
| \`mcp__moflo__hooks_route\` | Route task to optimal agent type |
|
|
691
|
+
| \`mcp__moflo__hooks_pre-task\` | Record task start |
|
|
692
|
+
| \`mcp__moflo__hooks_post-task\` | Record task completion for learning |
|
|
693
|
+
|
|
694
|
+
### CLI Fallback
|
|
695
|
+
|
|
696
|
+
\`\`\`bash
|
|
697
|
+
npx flo-search "[query]" --namespace guidance # Semantic search
|
|
698
|
+
npx flo doctor --fix # Health check
|
|
699
|
+
\`\`\`
|
|
700
|
+
|
|
701
|
+
### Full Reference
|
|
702
|
+
|
|
703
|
+
For CLI commands, hooks, agents, swarm config, memory commands, and moflo.yaml options, see:
|
|
704
|
+
\`.claude/guidance/shipped/moflo.md\`
|
|
705
|
+
${MOFLO_MARKER_END}
|
|
706
|
+
`;
|
|
707
|
+
const finalContent = existing.trimEnd() + '\n' + mofloSection;
|
|
708
|
+
fs.writeFileSync(claudeMdPath, finalContent, 'utf-8');
|
|
709
|
+
return {
|
|
710
|
+
name: 'CLAUDE.md',
|
|
711
|
+
status: existing ? 'updated' : 'created',
|
|
712
|
+
detail: 'MoFlo section injected (~35 lines)',
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
// ============================================================================
|
|
716
|
+
// Step 5: .claude/scripts/ — sync from moflo bin/
|
|
717
|
+
// These scripts are used by session-start hooks for indexing, code map, etc.
|
|
718
|
+
// Always overwrite to keep them in sync with the installed moflo version.
|
|
719
|
+
// ============================================================================
|
|
720
|
+
const SCRIPT_MAP = {
|
|
721
|
+
'hooks.mjs': 'hooks.mjs',
|
|
722
|
+
'session-start-launcher.mjs': 'session-start-launcher.mjs',
|
|
723
|
+
'index-guidance.mjs': 'index-guidance.mjs',
|
|
724
|
+
'build-embeddings.mjs': 'build-embeddings.mjs',
|
|
725
|
+
'generate-code-map.mjs': 'generate-code-map.mjs',
|
|
726
|
+
'semantic-search.mjs': 'semantic-search.mjs',
|
|
727
|
+
'index-tests.mjs': 'index-tests.mjs',
|
|
728
|
+
};
|
|
729
|
+
function syncScripts(root, force) {
|
|
730
|
+
const scriptsDir = path.join(root, '.claude', 'scripts');
|
|
731
|
+
if (!fs.existsSync(scriptsDir)) {
|
|
732
|
+
fs.mkdirSync(scriptsDir, { recursive: true });
|
|
733
|
+
}
|
|
734
|
+
// Find moflo bin/ directory
|
|
735
|
+
let syncThisDir;
|
|
736
|
+
try {
|
|
737
|
+
syncThisDir = path.dirname(fileURLToPath(import.meta.url));
|
|
738
|
+
}
|
|
739
|
+
catch {
|
|
740
|
+
syncThisDir = typeof __dirname !== 'undefined' ? __dirname : '';
|
|
741
|
+
}
|
|
742
|
+
const candidates = [
|
|
743
|
+
path.join(root, 'node_modules', 'moflo', 'bin'),
|
|
744
|
+
// When running from moflo repo itself
|
|
745
|
+
...(syncThisDir ? [path.join(syncThisDir, '..', '..', '..', '..', 'bin')] : []),
|
|
746
|
+
];
|
|
747
|
+
const binDir = candidates.find(d => { try {
|
|
748
|
+
return fs.existsSync(d);
|
|
749
|
+
}
|
|
750
|
+
catch {
|
|
751
|
+
return false;
|
|
752
|
+
} });
|
|
753
|
+
if (!binDir) {
|
|
754
|
+
return { name: '.claude/scripts/', status: 'skipped', detail: 'moflo bin/ not found' };
|
|
755
|
+
}
|
|
756
|
+
let copied = 0;
|
|
757
|
+
for (const [dest, src] of Object.entries(SCRIPT_MAP)) {
|
|
758
|
+
const srcPath = path.join(binDir, src);
|
|
759
|
+
const destPath = path.join(scriptsDir, dest);
|
|
760
|
+
if (!fs.existsSync(srcPath))
|
|
761
|
+
continue;
|
|
762
|
+
// Always overwrite scripts to keep in sync (they're derived, not user-edited)
|
|
763
|
+
if (!fs.existsSync(destPath) || force || isStale(srcPath, destPath)) {
|
|
764
|
+
fs.copyFileSync(srcPath, destPath);
|
|
765
|
+
copied++;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
if (copied === 0) {
|
|
769
|
+
return { name: '.claude/scripts/', status: 'skipped', detail: 'Scripts already up to date' };
|
|
770
|
+
}
|
|
771
|
+
return { name: '.claude/scripts/', status: 'updated', detail: `${copied} scripts synced from moflo` };
|
|
772
|
+
}
|
|
773
|
+
function isStale(srcPath, destPath) {
|
|
774
|
+
try {
|
|
775
|
+
return fs.statSync(srcPath).mtimeMs > fs.statSync(destPath).mtimeMs;
|
|
776
|
+
}
|
|
777
|
+
catch {
|
|
778
|
+
return true;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
// ============================================================================
|
|
782
|
+
// Step 6: .gitignore
|
|
783
|
+
// ============================================================================
|
|
784
|
+
function updateGitignore(root) {
|
|
785
|
+
const gitignorePath = path.join(root, '.gitignore');
|
|
786
|
+
const entries = ['.claude-orc/', '.swarm/', '.moflo/'];
|
|
787
|
+
if (!fs.existsSync(gitignorePath)) {
|
|
788
|
+
// Create .gitignore with common defaults + MoFlo entries
|
|
789
|
+
const defaultEntries = ['node_modules/', 'dist/', '.env', '.env.*', ''];
|
|
790
|
+
const content = '# Dependencies\n' + defaultEntries.join('\n') + '\n# MoFlo state\n' + entries.join('\n') + '\n';
|
|
791
|
+
fs.writeFileSync(gitignorePath, content, 'utf-8');
|
|
792
|
+
return { name: '.gitignore', status: 'created', detail: 'Created with node_modules, .env, and MoFlo entries' };
|
|
793
|
+
}
|
|
794
|
+
const existing = fs.readFileSync(gitignorePath, 'utf-8');
|
|
795
|
+
const toAdd = entries.filter(e => !existing.includes(e));
|
|
796
|
+
if (toAdd.length === 0) {
|
|
797
|
+
return { name: '.gitignore', status: 'skipped', detail: 'Entries already present' };
|
|
798
|
+
}
|
|
799
|
+
fs.appendFileSync(gitignorePath, '\n# MoFlo state (gitignored)\n' + toAdd.join('\n') + '\n');
|
|
800
|
+
return { name: '.gitignore', status: 'updated', detail: `Added: ${toAdd.join(', ')}` };
|
|
801
|
+
}
|
|
802
|
+
// ============================================================================
|
|
803
|
+
// Step 7: .claude/guidance/moflo-bootstrap.md
|
|
804
|
+
// Copies the agent bootstrap guidance to the project so subagents can read it
|
|
805
|
+
// from disk without requiring memory search.
|
|
806
|
+
// ============================================================================
|
|
807
|
+
function syncBootstrapGuidance(root, force) {
|
|
808
|
+
const guidanceDir = path.join(root, '.claude', 'guidance');
|
|
809
|
+
const targetFile = path.join(guidanceDir, 'moflo-bootstrap.md');
|
|
810
|
+
// Find the source bootstrap file from the moflo package
|
|
811
|
+
let sourceDir;
|
|
812
|
+
try {
|
|
813
|
+
sourceDir = path.dirname(fileURLToPath(import.meta.url));
|
|
814
|
+
}
|
|
815
|
+
catch {
|
|
816
|
+
sourceDir = typeof __dirname !== 'undefined' ? __dirname : '';
|
|
817
|
+
}
|
|
818
|
+
const candidates = [
|
|
819
|
+
path.join(root, 'node_modules', 'moflo', '.claude', 'guidance', 'agent-bootstrap.md'),
|
|
820
|
+
// When running from moflo repo itself
|
|
821
|
+
...(sourceDir ? [path.join(sourceDir, '..', '..', '..', '..', '.claude', 'guidance', 'agent-bootstrap.md')] : []),
|
|
822
|
+
];
|
|
823
|
+
const sourceFile = candidates.find(f => { try {
|
|
824
|
+
return fs.existsSync(f);
|
|
825
|
+
}
|
|
826
|
+
catch {
|
|
827
|
+
return false;
|
|
828
|
+
} });
|
|
829
|
+
if (!sourceFile) {
|
|
830
|
+
return { name: 'guidance/moflo-bootstrap.md', status: 'skipped', detail: 'Source bootstrap not found' };
|
|
831
|
+
}
|
|
832
|
+
// Check if target exists and is up to date
|
|
833
|
+
if (fs.existsSync(targetFile) && !force) {
|
|
834
|
+
if (!isStale(sourceFile, targetFile)) {
|
|
835
|
+
return { name: 'guidance/moflo-bootstrap.md', status: 'skipped', detail: 'Already up to date' };
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
// Read source and prepend header
|
|
839
|
+
const content = fs.readFileSync(sourceFile, 'utf-8');
|
|
840
|
+
const header = `<!-- AUTO-GENERATED by moflo init. Do not edit — changes will be overwritten on next init. -->\n<!-- Source: moflo/.claude/guidance/agent-bootstrap.md -->\n<!-- To customize, create .claude/guidance/agent-bootstrap.md for project-specific rules. -->\n\n`;
|
|
841
|
+
fs.mkdirSync(guidanceDir, { recursive: true });
|
|
842
|
+
fs.writeFileSync(targetFile, header + content, 'utf-8');
|
|
843
|
+
return {
|
|
844
|
+
name: 'guidance/moflo-bootstrap.md',
|
|
845
|
+
status: fs.existsSync(targetFile) ? 'updated' : 'created',
|
|
846
|
+
detail: 'Subagent bootstrap protocol'
|
|
847
|
+
};
|
|
848
|
+
}
|
|
840
849
|
//# sourceMappingURL=moflo-init.js.map
|