moflo 4.9.21 → 4.9.23

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.
Files changed (194) hide show
  1. package/.claude/agents/analysis/analyze-code-quality.md +0 -121
  2. package/.claude/agents/analysis/code-analyzer.md +5 -26
  3. package/.claude/agents/architecture/system-design/arch-system-design.md +0 -119
  4. package/.claude/agents/base-template-generator.md +0 -1
  5. package/.claude/agents/core/coder.md +0 -22
  6. package/.claude/agents/core/planner.md +0 -16
  7. package/.claude/agents/core/researcher.md +0 -16
  8. package/.claude/agents/core/reviewer.md +0 -17
  9. package/.claude/agents/core/tester.md +0 -19
  10. package/.claude/agents/custom/test-long-runner.md +0 -2
  11. package/.claude/agents/development/dev-backend-api.md +0 -167
  12. package/.claude/agents/development/dev-database.md +43 -0
  13. package/.claude/agents/development/dev-frontend.md +42 -0
  14. package/.claude/agents/devops/ci-cd/ops-cicd-github.md +0 -112
  15. package/.claude/agents/documentation/api-docs/docs-api-openapi.md +0 -111
  16. package/.claude/agents/security/security-auditor.md +45 -0
  17. package/.claude/guidance/shipped/moflo-cli-reference.md +19 -16
  18. package/.claude/guidance/shipped/moflo-core-guidance.md +0 -2
  19. package/.claude/guidance/shipped/moflo-guidance-rules.md +5 -5
  20. package/.claude/guidance/shipped/moflo-spell-runner.md +1 -0
  21. package/.claude/guidance/shipped/moflo-spell-scheduling.md +225 -0
  22. package/.claude/guidance/shipped/moflo-spell-troubleshooting.md +1 -0
  23. package/.claude/helpers/gate.cjs +70 -3
  24. package/.claude/skills/fl/execution-modes.md +38 -15
  25. package/.claude/skills/fl/phases.md +67 -0
  26. package/.claude/skills/spell-schedule/SKILL.md +18 -5
  27. package/README.md +1 -1
  28. package/bin/gate.cjs +70 -3
  29. package/bin/index-guidance.mjs +32 -6
  30. package/bin/lib/retired-files.mjs +146 -0
  31. package/bin/session-start-launcher.mjs +116 -8
  32. package/dist/src/cli/appliance/rvfa-builder.js +1 -1
  33. package/dist/src/cli/commands/agent.js +3 -9
  34. package/dist/src/cli/commands/daemon.js +13 -17
  35. package/dist/src/cli/commands/hooks.js +4 -9
  36. package/dist/src/cli/commands/index.js +2 -0
  37. package/dist/src/cli/commands/retire.js +111 -0
  38. package/dist/src/cli/commands/spell-schedule.js +237 -49
  39. package/dist/src/cli/hooks/reasoningbank/index.js +7 -7
  40. package/dist/src/cli/init/executor.js +26 -54
  41. package/dist/src/cli/init/helpers-generator.js +66 -3
  42. package/dist/src/cli/init/settings-generator.js +17 -6
  43. package/dist/src/cli/mcp-tools/agent-tools.js +9 -27
  44. package/dist/src/cli/mcp-tools/hooks-tools.js +23 -21
  45. package/dist/src/cli/mcp-tools/memory-tools.js +16 -5
  46. package/dist/src/cli/memory/bridge-embedder.js +26 -6
  47. package/dist/src/cli/memory/bridge-entries.js +33 -15
  48. package/dist/src/cli/memory/controllers/semantic-router.js +18 -12
  49. package/dist/src/cli/memory/sona-optimizer.js +6 -6
  50. package/dist/src/cli/neural/domain/services/learning-service.js +3 -3
  51. package/dist/src/cli/services/agent-router.js +2 -5
  52. package/dist/src/cli/services/daemon-autostart-lifecycle.js +62 -0
  53. package/dist/src/cli/services/daemon-dashboard.js +187 -18
  54. package/dist/src/cli/services/daemon-readiness.js +19 -31
  55. package/dist/src/cli/services/ephemeral-namespace-purge.js +61 -33
  56. package/dist/src/cli/services/headless-worker-executor.js +7 -94
  57. package/dist/src/cli/services/hook-block-hash.js +4 -0
  58. package/dist/src/cli/services/worker-daemon.js +40 -66
  59. package/dist/src/cli/shared/events/example-usage.js +6 -6
  60. package/dist/src/cli/shared/hooks/task-hooks.js +8 -8
  61. package/dist/src/cli/spells/core/runner.js +12 -0
  62. package/dist/src/cli/spells/scheduler/scheduler.js +24 -9
  63. package/dist/src/cli/spells/schema/validator.js +2 -1
  64. package/dist/src/cli/spells/schema/validators/top-level.js +18 -0
  65. package/dist/src/cli/version.js +1 -1
  66. package/package.json +5 -2
  67. package/retired-files.json +1989 -0
  68. package/src/cli/data/model-registry.json +2 -2
  69. package/.claude/agents/consensus/byzantine-coordinator.md +0 -63
  70. package/.claude/agents/consensus/crdt-synchronizer.md +0 -997
  71. package/.claude/agents/consensus/gossip-coordinator.md +0 -63
  72. package/.claude/agents/consensus/performance-benchmarker.md +0 -851
  73. package/.claude/agents/consensus/quorum-manager.md +0 -823
  74. package/.claude/agents/consensus/raft-manager.md +0 -63
  75. package/.claude/agents/consensus/security-manager.md +0 -622
  76. package/.claude/agents/data/ml/data-ml-model.md +0 -193
  77. package/.claude/agents/github/code-review-swarm.md +0 -538
  78. package/.claude/agents/github/github-modes.md +0 -172
  79. package/.claude/agents/github/issue-tracker.md +0 -311
  80. package/.claude/agents/github/multi-repo-swarm.md +0 -551
  81. package/.claude/agents/github/pr-manager.md +0 -183
  82. package/.claude/agents/github/project-board-sync.md +0 -508
  83. package/.claude/agents/github/release-manager.md +0 -360
  84. package/.claude/agents/github/release-swarm.md +0 -580
  85. package/.claude/agents/github/repo-architect.md +0 -391
  86. package/.claude/agents/github/swarm-issue.md +0 -566
  87. package/.claude/agents/github/swarm-pr.md +0 -414
  88. package/.claude/agents/github/sync-coordinator.md +0 -426
  89. package/.claude/agents/github/workflow-automation.md +0 -606
  90. package/.claude/agents/goal/code-goal-planner.md +0 -440
  91. package/.claude/agents/goal/goal-planner.md +0 -168
  92. package/.claude/agents/hive-mind/collective-intelligence-coordinator.md +0 -127
  93. package/.claude/agents/hive-mind/queen-coordinator.md +0 -198
  94. package/.claude/agents/hive-mind/scout-explorer.md +0 -233
  95. package/.claude/agents/hive-mind/swarm-memory-manager.md +0 -184
  96. package/.claude/agents/hive-mind/worker-specialist.md +0 -208
  97. package/.claude/agents/neural/safla-neural.md +0 -73
  98. package/.claude/agents/optimization/benchmark-suite.md +0 -665
  99. package/.claude/agents/optimization/load-balancer.md +0 -431
  100. package/.claude/agents/optimization/performance-monitor.md +0 -672
  101. package/.claude/agents/optimization/resource-allocator.md +0 -674
  102. package/.claude/agents/optimization/topology-optimizer.md +0 -808
  103. package/.claude/agents/reasoning/goal-planner.md +0 -67
  104. package/.claude/agents/sona/sona-learning-optimizer.md +0 -74
  105. package/.claude/agents/sparc/architecture.md +0 -472
  106. package/.claude/agents/sparc/pseudocode.md +0 -318
  107. package/.claude/agents/sparc/refinement.md +0 -525
  108. package/.claude/agents/sparc/specification.md +0 -276
  109. package/.claude/agents/specialized/mobile/spec-mobile-react-native.md +0 -225
  110. package/.claude/agents/swarm/adaptive-coordinator.md +0 -391
  111. package/.claude/agents/swarm/hierarchical-coordinator.md +0 -321
  112. package/.claude/agents/swarm/mesh-coordinator.md +0 -383
  113. package/.claude/agents/testing/production-validator.md +0 -395
  114. package/.claude/agents/testing/tdd-london-swarm.md +0 -244
  115. package/.claude/agents/v3/adr-architect.md +0 -184
  116. package/.claude/agents/v3/aidefence-guardian.md +0 -277
  117. package/.claude/agents/v3/claims-authorizer.md +0 -208
  118. package/.claude/agents/v3/collective-intelligence-coordinator.md +0 -988
  119. package/.claude/agents/v3/ddd-domain-expert.md +0 -220
  120. package/.claude/agents/v3/injection-analyst.md +0 -232
  121. package/.claude/agents/v3/memory-specialist.md +0 -987
  122. package/.claude/agents/v3/performance-engineer.md +0 -1225
  123. package/.claude/agents/v3/pii-detector.md +0 -146
  124. package/.claude/agents/v3/reasoningbank-learner.md +0 -213
  125. package/.claude/agents/v3/security-architect-aidefence.md +0 -405
  126. package/.claude/agents/v3/security-architect.md +0 -865
  127. package/.claude/agents/v3/security-auditor.md +0 -771
  128. package/.claude/agents/v3/sparc-orchestrator.md +0 -182
  129. package/.claude/agents/v3/swarm-memory-manager.md +0 -142
  130. package/.claude/agents/v3/v3-integration-architect.md +0 -205
  131. package/.claude/commands/claude-flow-help.md +0 -103
  132. package/.claude/commands/claude-flow-memory.md +0 -107
  133. package/.claude/commands/claude-flow-swarm.md +0 -205
  134. package/.claude/commands/flo-simplify.md +0 -101
  135. package/.claude/commands/github/README.md +0 -11
  136. package/.claude/commands/github/code-review-swarm.md +0 -514
  137. package/.claude/commands/github/code-review.md +0 -25
  138. package/.claude/commands/github/github-modes.md +0 -146
  139. package/.claude/commands/github/github-swarm.md +0 -113
  140. package/.claude/commands/github/issue-tracker.md +0 -284
  141. package/.claude/commands/github/issue-triage.md +0 -25
  142. package/.claude/commands/github/multi-repo-swarm.md +0 -519
  143. package/.claude/commands/github/pr-enhance.md +0 -26
  144. package/.claude/commands/github/pr-manager.md +0 -164
  145. package/.claude/commands/github/project-board-sync.md +0 -471
  146. package/.claude/commands/github/release-manager.md +0 -332
  147. package/.claude/commands/github/release-swarm.md +0 -544
  148. package/.claude/commands/github/repo-analyze.md +0 -25
  149. package/.claude/commands/github/repo-architect.md +0 -361
  150. package/.claude/commands/github/swarm-issue.md +0 -482
  151. package/.claude/commands/github/swarm-pr.md +0 -285
  152. package/.claude/commands/github/sync-coordinator.md +0 -294
  153. package/.claude/commands/github/workflow-automation.md +0 -442
  154. package/.claude/commands/hooks/README.md +0 -11
  155. package/.claude/commands/hooks/overview.md +0 -58
  156. package/.claude/commands/hooks/post-edit.md +0 -117
  157. package/.claude/commands/hooks/post-task.md +0 -112
  158. package/.claude/commands/hooks/pre-edit.md +0 -113
  159. package/.claude/commands/hooks/pre-task.md +0 -111
  160. package/.claude/commands/hooks/session-end.md +0 -118
  161. package/.claude/commands/hooks/setup.md +0 -103
  162. package/.claude/commands/sparc/analyzer.md +0 -42
  163. package/.claude/commands/sparc/architect.md +0 -43
  164. package/.claude/commands/sparc/ask.md +0 -86
  165. package/.claude/commands/sparc/batch-executor.md +0 -44
  166. package/.claude/commands/sparc/code.md +0 -78
  167. package/.claude/commands/sparc/coder.md +0 -44
  168. package/.claude/commands/sparc/debug.md +0 -72
  169. package/.claude/commands/sparc/debugger.md +0 -44
  170. package/.claude/commands/sparc/designer.md +0 -43
  171. package/.claude/commands/sparc/devops.md +0 -98
  172. package/.claude/commands/sparc/docs-writer.md +0 -69
  173. package/.claude/commands/sparc/documenter.md +0 -44
  174. package/.claude/commands/sparc/innovator.md +0 -44
  175. package/.claude/commands/sparc/integration.md +0 -72
  176. package/.claude/commands/sparc/mcp.md +0 -106
  177. package/.claude/commands/sparc/memory-manager.md +0 -44
  178. package/.claude/commands/sparc/optimizer.md +0 -44
  179. package/.claude/commands/sparc/orchestrator.md +0 -116
  180. package/.claude/commands/sparc/post-deployment-monitoring-mode.md +0 -72
  181. package/.claude/commands/sparc/refinement-optimization-mode.md +0 -72
  182. package/.claude/commands/sparc/researcher.md +0 -44
  183. package/.claude/commands/sparc/reviewer.md +0 -44
  184. package/.claude/commands/sparc/security-review.md +0 -69
  185. package/.claude/commands/sparc/sparc-modes.md +0 -139
  186. package/.claude/commands/sparc/sparc.md +0 -99
  187. package/.claude/commands/sparc/spec-pseudocode.md +0 -69
  188. package/.claude/commands/sparc/spell-manager.md +0 -44
  189. package/.claude/commands/sparc/supabase-admin.md +0 -337
  190. package/.claude/commands/sparc/swarm-coordinator.md +0 -44
  191. package/.claude/commands/sparc/tdd.md +0 -44
  192. package/.claude/commands/sparc/tester.md +0 -44
  193. package/.claude/commands/sparc/tutorial.md +0 -68
  194. package/.claude/commands/sparc.md +0 -151
@@ -1,13 +1,21 @@
1
1
  /**
2
2
  * Worker Daemon Service
3
- * Node.js-based background worker system that auto-runs like shell daemons
3
+ * Node.js-based background worker system that auto-runs like shell daemons.
4
4
  *
5
- * Workers:
6
- * - map: Codebase mapping (5 min interval)
7
- * - audit: Security analysis (10 min interval)
5
+ * Default workers:
6
+ * - map: Codebase mapping (15 min interval)
8
7
  * - optimize: Performance optimization (15 min interval)
9
8
  * - consolidate: Memory consolidation (30 min interval)
10
9
  * - testgaps: Test coverage analysis (20 min interval)
10
+ *
11
+ * Manual-trigger-only workers (disabled by default, no scheduled run):
12
+ * ultralearn, refactor, deepdive, benchmark, preload.
13
+ *
14
+ * The `audit`, `predict`, and `document` workers were removed in #970 —
15
+ * they were default-disabled with no surfacing layer for findings, and the
16
+ * dashboard rendered them as "disabled" rows that read as broken. If a
17
+ * security or doc scan returns it should land as an opt-in `flo doctor`
18
+ * one-shot with a real findings UI, not as a recurring background worker.
11
19
  */
12
20
  import { EventEmitter } from 'events';
13
21
  import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
@@ -21,18 +29,32 @@ import { attachSignalHandlers } from '../shared/resilience/signal-handlers.js';
21
29
  import { calculateDelay } from '../production/retry.js';
22
30
  import { CircuitBreaker } from '../production/circuit-breaker.js';
23
31
  import { errorDetail } from '../shared/utils/error-detail.js';
32
+ /**
33
+ * Runtime allow-list of known {@link WorkerType} values. Used by
34
+ * `initializeWorkerStates` to silently drop entries from a stale
35
+ * `daemon-state.json` after a worker is removed from the union (#970).
36
+ * Keep in sync with the `WorkerType` definition above.
37
+ */
38
+ const KNOWN_WORKER_TYPES = new Set([
39
+ 'ultralearn',
40
+ 'optimize',
41
+ 'consolidate',
42
+ 'map',
43
+ 'preload',
44
+ 'deepdive',
45
+ 'refactor',
46
+ 'benchmark',
47
+ 'testgaps',
48
+ ]);
49
+ function isKnownWorkerType(value) {
50
+ return typeof value === 'string' && KNOWN_WORKER_TYPES.has(value);
51
+ }
24
52
  // Default worker configurations with improved intervals (P0 fix: map 5min -> 15min)
25
53
  const DEFAULT_WORKERS = [
26
54
  { type: 'map', intervalMs: 15 * 60 * 1000, offsetMs: 0, priority: 'normal', description: 'Codebase mapping', enabled: true },
27
- // Default-disabled until the perf regression in #631 is remediated. The
28
- // worker averages 238 s/run on real installs, saturating cores back-to-back
29
- // when scheduled at the 10-minute interval. Re-enable here when #631 ships.
30
- { type: 'audit', intervalMs: 10 * 60 * 1000, offsetMs: 2 * 60 * 1000, priority: 'critical', description: 'Security analysis', enabled: false },
31
55
  { type: 'optimize', intervalMs: 15 * 60 * 1000, offsetMs: 4 * 60 * 1000, priority: 'high', description: 'Performance optimization', enabled: true },
32
56
  { type: 'consolidate', intervalMs: 30 * 60 * 1000, offsetMs: 6 * 60 * 1000, priority: 'low', description: 'Memory consolidation', enabled: true },
33
57
  { type: 'testgaps', intervalMs: 20 * 60 * 1000, offsetMs: 8 * 60 * 1000, priority: 'normal', description: 'Test coverage analysis', enabled: true },
34
- { type: 'predict', intervalMs: 10 * 60 * 1000, offsetMs: 0, priority: 'low', description: 'Predictive preloading', enabled: false },
35
- { type: 'document', intervalMs: 60 * 60 * 1000, offsetMs: 0, priority: 'low', description: 'Auto-documentation', enabled: false },
36
58
  ];
37
59
  // Worker timeout (5 minutes max per worker)
38
60
  const DEFAULT_WORKER_TIMEOUT_MS = 5 * 60 * 1000;
@@ -326,9 +348,16 @@ export class WorkerDaemon extends EventEmitter {
326
348
  if (typeof saved.config?.workerTimeoutMs === 'number' && saved.config.workerTimeoutMs > 0) {
327
349
  this.config.workerTimeoutMs = saved.config.workerTimeoutMs;
328
350
  }
329
- // Restore worker runtime states (runCount, successCount, etc.)
351
+ // Restore worker runtime states (runCount, successCount, etc.).
352
+ // Unknown worker types (left over from a prior moflo version where
353
+ // `audit`/`predict`/`document` existed) are silently dropped — see
354
+ // KNOWN_WORKER_TYPES + #970 — so consumers upgrading don't crash on
355
+ // stale state, and the orphan entries don't get re-persisted on the
356
+ // next saveState.
330
357
  if (saved.workers) {
331
358
  for (const [type, state] of Object.entries(saved.workers)) {
359
+ if (!isKnownWorkerType(type))
360
+ continue;
332
361
  const savedState = state;
333
362
  const lastRunValue = savedState.lastRun;
334
363
  const restoredState = {
@@ -749,18 +778,12 @@ export class WorkerDaemon extends EventEmitter {
749
778
  switch (workerConfig.type) {
750
779
  case 'map':
751
780
  return this.runMapWorker();
752
- case 'audit':
753
- return this.runAuditWorkerLocal();
754
781
  case 'optimize':
755
782
  return this.runOptimizeWorkerLocal();
756
783
  case 'consolidate':
757
784
  return this.runConsolidateWorker();
758
785
  case 'testgaps':
759
786
  return this.runTestGapsWorkerLocal();
760
- case 'predict':
761
- return this.runPredictWorkerLocal();
762
- case 'document':
763
- return this.runDocumentWorkerLocal();
764
787
  case 'ultralearn':
765
788
  return this.runUltralearnWorkerLocal();
766
789
  case 'refactor':
@@ -797,31 +820,6 @@ export class WorkerDaemon extends EventEmitter {
797
820
  writeFileSync(metricsFile, JSON.stringify(map, null, 2));
798
821
  return map;
799
822
  }
800
- /**
801
- * Local audit worker (fallback when headless unavailable)
802
- */
803
- async runAuditWorkerLocal() {
804
- // Basic security checks
805
- const auditFile = join(this.projectRoot, '.moflo', 'metrics', 'security-audit.json');
806
- const metricsDir = join(this.projectRoot, '.moflo', 'metrics');
807
- if (!existsSync(metricsDir)) {
808
- mkdirSync(metricsDir, { recursive: true });
809
- }
810
- const audit = {
811
- timestamp: new Date().toISOString(),
812
- mode: 'local',
813
- checks: {
814
- envFilesProtected: !existsSync(join(this.projectRoot, '.env.local')),
815
- gitIgnoreExists: existsSync(join(this.projectRoot, '.gitignore')),
816
- noHardcodedSecrets: true, // Would need actual scanning
817
- },
818
- riskLevel: 'low',
819
- recommendations: [],
820
- note: 'Install Claude Code CLI for AI-powered security analysis',
821
- };
822
- writeFileSync(auditFile, JSON.stringify(audit, null, 2));
823
- return audit;
824
- }
825
823
  /**
826
824
  * Local optimize worker (fallback when headless unavailable)
827
825
  */
@@ -883,30 +881,6 @@ export class WorkerDaemon extends EventEmitter {
883
881
  writeFileSync(testGapsFile, JSON.stringify(result, null, 2));
884
882
  return result;
885
883
  }
886
- /**
887
- * Local predict worker (fallback when headless unavailable)
888
- */
889
- async runPredictWorkerLocal() {
890
- return {
891
- timestamp: new Date().toISOString(),
892
- mode: 'local',
893
- predictions: [],
894
- preloaded: [],
895
- note: 'Install Claude Code CLI for AI-powered predictions',
896
- };
897
- }
898
- /**
899
- * Local document worker (fallback when headless unavailable)
900
- */
901
- async runDocumentWorkerLocal() {
902
- return {
903
- timestamp: new Date().toISOString(),
904
- mode: 'local',
905
- filesDocumented: 0,
906
- suggestedDocs: [],
907
- note: 'Install Claude Code CLI for AI-powered documentation generation',
908
- };
909
- }
910
884
  /**
911
885
  * Local ultralearn worker (fallback when headless unavailable)
912
886
  */
@@ -36,20 +36,20 @@ async function main() {
36
36
  // 3. Record Agent Lifecycle Events
37
37
  // =========================================================================
38
38
  console.log('3. Recording Agent Lifecycle Events...');
39
- // Agent 1: Queen Coordinator
40
- await eventStore.append(createAgentSpawnedEvent('agent-1', 'queen-coordinator', 'coordination', [
39
+ // Agent 1: Coordinator
40
+ await eventStore.append(createAgentSpawnedEvent('agent-1', 'coordinator', 'coordination', [
41
41
  'orchestration',
42
42
  'task-assignment',
43
43
  ]));
44
44
  await eventStore.append(createAgentStartedEvent('agent-1'));
45
- // Agent 2: Security Architect
46
- await eventStore.append(createAgentSpawnedEvent('agent-2', 'security-architect', 'security', [
45
+ // Agent 2: Security Auditor
46
+ await eventStore.append(createAgentSpawnedEvent('agent-2', 'security-auditor', 'security', [
47
47
  'threat-modeling',
48
48
  'security-design',
49
49
  ]));
50
50
  await eventStore.append(createAgentStartedEvent('agent-2'));
51
- // Agent 3: Core Architect
52
- await eventStore.append(createAgentSpawnedEvent('agent-3', 'core-architect', 'core', ['ddd-design', 'architecture']));
51
+ // Agent 3: Architect
52
+ await eventStore.append(createAgentSpawnedEvent('agent-3', 'architect', 'core', ['ddd-design', 'architecture']));
53
53
  await eventStore.append(createAgentStartedEvent('agent-3'));
54
54
  console.log(' Agent events recorded\n');
55
55
  // =========================================================================
@@ -144,27 +144,27 @@ export class TaskHooksManager {
144
144
  },
145
145
  {
146
146
  keywords: ['security', 'vulnerability', 'cve', 'threat'],
147
- agent: 'security-architect',
147
+ agent: 'security-auditor',
148
148
  capabilities: ['security-analysis', 'vulnerability-detection', 'threat-modeling'],
149
149
  },
150
150
  {
151
- keywords: ['performance', 'optimize', 'speed', 'memory'],
152
- agent: 'performance-engineer',
151
+ keywords: ['performance', 'optimize', 'speed', 'memory', 'profile', 'benchmark'],
152
+ agent: 'reviewer',
153
153
  capabilities: ['performance-optimization', 'profiling', 'benchmarking'],
154
154
  },
155
155
  {
156
156
  keywords: ['architect', 'design', 'structure', 'pattern'],
157
- agent: 'core-architect',
157
+ agent: 'architect',
158
158
  capabilities: ['architecture-design', 'pattern-application', 'system-design'],
159
159
  },
160
160
  {
161
- keywords: ['memory', 'storage', 'database', 'cache'],
162
- agent: 'memory-specialist',
161
+ keywords: ['storage', 'database', 'cache', 'persistence'],
162
+ agent: 'researcher',
163
163
  capabilities: ['memory-management', 'data-persistence', 'caching'],
164
164
  },
165
165
  {
166
- keywords: ['swarm', 'coordinate', 'orchestrate', 'agent'],
167
- agent: 'swarm-specialist',
166
+ keywords: ['swarm', 'coordinate', 'orchestrate', 'agent', 'hive'],
167
+ agent: 'coordinator',
168
168
  capabilities: ['swarm-coordination', 'agent-orchestration', 'distributed-systems'],
169
169
  },
170
170
  ];
@@ -150,6 +150,18 @@ export class SpellCaster {
150
150
  message: err.message,
151
151
  }], definition.name);
152
152
  }
153
+ // Per-spell sandbox requirement (#878) — "more strict wins": the spell
154
+ // can opt in to sandboxing even when the global config is off, and the
155
+ // runner refuses to cast if no OS sandbox is active.
156
+ if (definition.sandbox?.required === true && !effectiveSandbox.useOsSandbox) {
157
+ return this.failureResult(spellId, startTime, [{
158
+ code: 'SANDBOX_REQUIRED',
159
+ message: `Spell "${definition.name}" requires an OS sandbox but none is active ` +
160
+ `(${effectiveSandbox.displayStatus}). Enable sandboxing by setting ` +
161
+ `\`sandbox.enabled: true\` in moflo.yaml (and \`sandbox.tier: auto\` ` +
162
+ `or \`full\`), or remove \`sandbox.required: true\` from the spell.`,
163
+ }], definition.name);
164
+ }
153
165
  return this.executeSteps(definition, resolvedArgs, spellId, options, startTime, effectiveSandbox);
154
166
  }
155
167
  async dryRun(definition, resolvedArgs, options = {}) {
@@ -369,15 +369,30 @@ export class SpellScheduler {
369
369
  duration: completedAt - now,
370
370
  };
371
371
  await this.memory.write(NAMESPACE_EXECUTIONS, executionId, finalRecord);
372
- this.emit({
373
- type: result.success ? 'schedule:completed' : 'schedule:failed',
374
- scheduleId: schedule.id,
375
- spellName: schedule.spellName,
376
- message: result.success
377
- ? `Completed in ${finalRecord.duration}ms`
378
- : `Failed: ${finalRecord.error}`,
379
- timestamp: completedAt,
380
- });
372
+ // SANDBOX_REQUIRED (#878) is a configuration mismatch, not a runtime
373
+ // failure surface it as a skip so dashboards/oncall don't page on a
374
+ // missing sandbox the user can resolve in moflo.yaml.
375
+ const sandboxRequiredErr = result.errors.find(e => e.code === 'SANDBOX_REQUIRED');
376
+ if (!result.success && sandboxRequiredErr) {
377
+ this.emit({
378
+ type: 'schedule:skipped',
379
+ scheduleId: schedule.id,
380
+ spellName: schedule.spellName,
381
+ message: sandboxRequiredErr.message,
382
+ timestamp: completedAt,
383
+ });
384
+ }
385
+ else {
386
+ this.emit({
387
+ type: result.success ? 'schedule:completed' : 'schedule:failed',
388
+ scheduleId: schedule.id,
389
+ spellName: schedule.spellName,
390
+ message: result.success
391
+ ? `Completed in ${finalRecord.duration}ms`
392
+ : `Failed: ${finalRecord.error}`,
393
+ timestamp: completedAt,
394
+ });
395
+ }
381
396
  }
382
397
  catch (err) {
383
398
  const completedAt = Date.now();
@@ -16,7 +16,7 @@
16
16
  import { isValidMofloLevel } from '../core/capability-validator.js';
17
17
  import { MOFLO_LEVEL_ORDER } from '../types/step-command.types.js';
18
18
  import { validateSchedule } from '../scheduler/cron-parser.js';
19
- import { validateTopLevel, validateArguments, matchesArgumentType } from './validators/top-level.js';
19
+ import { validateTopLevel, validateArguments, matchesArgumentType, validateSandbox } from './validators/top-level.js';
20
20
  import { validateSteps } from './validators/steps.js';
21
21
  import { validatePrerequisites } from './validators/prerequisites.js';
22
22
  import { validateVariableReferences } from './validators/references.js';
@@ -27,6 +27,7 @@ import { detectCircularJumps } from './validators/jumps.js';
27
27
  export function validateSpellDefinition(def, options) {
28
28
  const errors = [];
29
29
  validateTopLevel(def, errors);
30
+ validateSandbox(def, errors);
30
31
  if (def.mofloLevel !== undefined && !isValidMofloLevel(def.mofloLevel)) {
31
32
  errors.push({
32
33
  path: 'mofloLevel',
@@ -58,6 +58,24 @@ export function validateArguments(args, errors) {
58
58
  }
59
59
  }
60
60
  }
61
+ /**
62
+ * Validate the optional `sandbox` block on a spell definition.
63
+ * Accepts: missing, `{}`, `{ required: boolean }`.
64
+ * Rejects: non-object value, non-boolean `required`.
65
+ */
66
+ export function validateSandbox(def, errors) {
67
+ const sandbox = def.sandbox;
68
+ if (sandbox === undefined)
69
+ return;
70
+ if (sandbox === null || typeof sandbox !== 'object' || Array.isArray(sandbox)) {
71
+ errors.push({ path: 'sandbox', message: 'sandbox must be an object' });
72
+ return;
73
+ }
74
+ const { required } = sandbox;
75
+ if (required !== undefined && typeof required !== 'boolean') {
76
+ errors.push({ path: 'sandbox.required', message: 'sandbox.required must be a boolean' });
77
+ }
78
+ }
61
79
  /** Check whether a value matches a declared ArgumentType. */
62
80
  export function matchesArgumentType(value, type) {
63
81
  switch (type) {
@@ -2,5 +2,5 @@
2
2
  * Auto-generated by build. Do not edit manually.
3
3
  * Source of truth: root package.json → scripts/sync-version.mjs
4
4
  */
5
- export const VERSION = '4.9.21';
5
+ export const VERSION = '4.9.23';
6
6
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moflo",
3
- "version": "4.9.21",
3
+ "version": "4.9.23",
4
4
  "description": "MoFlo — AI agent orchestration for Claude Code. A standalone, opinionated toolkit with semantic memory, learned routing, gates, spells, and the /flo issue-execution skill.",
5
5
  "main": "dist/src/cli/index.js",
6
6
  "type": "module",
@@ -29,6 +29,7 @@
29
29
  "src/cli/spells/definitions/**/*.yaml",
30
30
  "!**/*.test.js",
31
31
  "!**/*.spec.js",
32
+ "!**/*.perf.js",
32
33
  "!**/__tests__/**",
33
34
  ".claude/commands/**/*.md",
34
35
  ".claude/agents/**/*.md",
@@ -39,6 +40,7 @@
39
40
  "!.claude/**/*.map",
40
41
  "README.md",
41
42
  "LICENSE",
43
+ "retired-files.json",
42
44
  "scripts/prune-native-binaries.mjs",
43
45
  "scripts/post-install-notice.mjs",
44
46
  "scripts/post-install-bootstrap.mjs"
@@ -53,6 +55,7 @@
53
55
  "test:ui": "vitest --ui",
54
56
  "test:smoke": "node harness/consumer-smoke/run.mjs",
55
57
  "test:smoke:populated": "node harness/consumer-smoke/run-populated.mjs",
58
+ "bench": "vitest run --config vitest.bench.config.ts",
56
59
  "lint": "eslint src/ bin/ .claude/scripts/ --ext .ts,.tsx,.mts,.cts,.js,.mjs,.cjs --max-warnings 0",
57
60
  "security:audit": "npm audit --omit=dev --audit-level high",
58
61
  "security:fix": "npm audit fix",
@@ -81,7 +84,7 @@
81
84
  "@typescript-eslint/eslint-plugin": "^7.18.0",
82
85
  "@typescript-eslint/parser": "^7.18.0",
83
86
  "eslint": "^8.0.0",
84
- "moflo": "^4.9.20",
87
+ "moflo": "^4.9.22",
85
88
  "tsx": "^4.21.0",
86
89
  "typescript": "^5.9.3",
87
90
  "vitest": "^4.0.0"