fix pycompose and added pydeploy
diff --git a/MANIFEST.in b/MANIFEST.in
index 0fc73b9..747f15c 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -9,8 +9,6 @@
 include samples/demo.py
 include LICENSE.txt
 include README.md
-include CLA-CORPORATE.md
-include CLA-INDIVIDUAL.md
 
 include tox.ini .travis.yml
 include travis/*.sh
diff --git a/runone.sh b/runone.sh
new file mode 100755
index 0000000..e9a8d54
--- /dev/null
+++ b/runone.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+tox -e py36 -- pytest -s "tests/test_conductor.py::TestBlockingInvocations::test_action_activation_id"
\ No newline at end of file
diff --git a/samples/demo.json b/samples/demo.json
new file mode 100644
index 0000000..afb2041
--- /dev/null
+++ b/samples/demo.json
@@ -0,0 +1,175 @@
+{
+    "composition": {
+        "type": "let",
+        ".combinator": {},
+        "declarations": {
+            "params": null
+        },
+        "components": [
+            {
+                "type": "function",
+                "function": {
+                    "exec": {
+                        "kind": "python:3",
+                        "code": "def set_params(env, args):\n    env['params'] = args\n",
+                        "functionName": "set_params"
+                    }
+                },
+                ".combinator": {}
+            },
+            {
+                "type": "ensure",
+                ".combinator": {},
+                "body": {
+                    "type": "function",
+                    "function": {
+                        "exec": {
+                            "kind": "python:3",
+                            "code": "def set_params(env, args):\n    env['params'] = args\n",
+                            "functionName": "set_params"
+                        }
+                    },
+                    ".combinator": {}
+                },
+                "finalizer": {
+                    "type": "when_nosave",
+                    ".combinator": {},
+                    "test": {
+                        "type": "mask",
+                        ".combinator": {},
+                        "components": [
+                            {
+                                "type": "action",
+                                "name": "/_/authenticate",
+                                ".combinator": {},
+                                "path": ".test"
+                            }
+                        ]
+                    },
+                    "consequent": {
+                        "type": "ensure",
+                        ".combinator": {},
+                        "body": {
+                            "type": "function",
+                            "function": {
+                                "exec": {
+                                    "kind": "python:3",
+                                    "code": "def get_params(env, args):\n    return env['params']\n",
+                                    "functionName": "get_params"
+                                }
+                            },
+                            ".combinator": {}
+                        },
+                        "finalizer": {
+                            "type": "mask",
+                            ".combinator": {},
+                            "components": [
+                                {
+                                    "type": "action",
+                                    "name": "/_/success",
+                                    ".combinator": {},
+                                    "path": ".consequent"
+                                }
+                            ]
+                        }
+                    },
+                    "alternate": {
+                        "type": "ensure",
+                        ".combinator": {},
+                        "body": {
+                            "type": "function",
+                            "function": {
+                                "exec": {
+                                    "kind": "python:3",
+                                    "code": "def get_params(env, args):\n    return env['params']\n",
+                                    "functionName": "get_params"
+                                }
+                            },
+                            ".combinator": {}
+                        },
+                        "finalizer": {
+                            "type": "mask",
+                            ".combinator": {},
+                            "components": [
+                                {
+                                    "type": "action",
+                                    "name": "/_/failure",
+                                    ".combinator": {},
+                                    "path": ".alternate"
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        ],
+        "path": ""
+    },
+    "ast": {
+        "type": "when",
+        ".combinator": {},
+        "test": {
+            "type": "action",
+            "name": "/_/authenticate",
+            ".combinator": {},
+            "action": {
+                "exec": {
+                    "kind": "python:3",
+                    "code": "import types\nimport marshal\nimport base64\n__code__= types.FunctionType(marshal.loads(base64.b64decode(bytearray('4wEAAAAAAAAAAQAAAAMAAABTAAAAcxAAAABkAXwAZAIZAGQDawJpAVMAKQRO2gV2YWx1ZdoIcGFzc3dvcmTaBmFiYzEyM6kAKQHaBGFyZ3NyBAAAAHIEAAAA2gg8c3RyaW5nPtoIPGxhbWJkYT4FAAAAcwAAAAA=', 'ASCII'))), {})\ndef main(args):\n    return __code__(args)\n"
+                }
+            }
+        },
+        "consequent": {
+            "type": "action",
+            "name": "/_/success",
+            ".combinator": {},
+            "action": {
+                "exec": {
+                    "kind": "python:3",
+                    "code": "import types\nimport marshal\nimport base64\n__code__= types.FunctionType(marshal.loads(base64.b64decode(bytearray('4wEAAAAAAAAAAQAAAAIAAABTAAAAcwgAAABkAWQCaQFTACkDTtoHbWVzc2FnZdoHc3VjY2Vzc6kAKQHaBGFyZ3NyAwAAAHIDAAAA2gg8c3RyaW5nPtoIPGxhbWJkYT4GAAAAcwAAAAA=', 'ASCII'))), {})\ndef main(args):\n    return __code__(args)\n"
+                }
+            }
+        },
+        "alternate": {
+            "type": "action",
+            "name": "/_/failure",
+            ".combinator": {},
+            "action": {
+                "exec": {
+                    "kind": "python:3",
+                    "code": "import types\nimport marshal\nimport base64\n__code__= types.FunctionType(marshal.loads(base64.b64decode(bytearray('4wEAAAAAAAAAAQAAAAIAAABTAAAAcwgAAABkAWQCaQFTACkDTtoHbWVzc2FnZdoHZmFpbHVyZakAKQHaBGFyZ3NyAwAAAHIDAAAA2gg8c3RyaW5nPtoIPGxhbWJkYT4HAAAAcwAAAAA=', 'ASCII'))), {})\ndef main(args):\n    return __code__(args)\n"
+                }
+            }
+        }
+    },
+    "version": "0.15.1",
+    "actions": [
+        {
+            "name": "/_/authenticate",
+            "action": {
+                "exec": {
+                    "kind": "python:3",
+                    "code": "import types\nimport marshal\nimport base64\n__code__= types.FunctionType(marshal.loads(base64.b64decode(bytearray('4wEAAAAAAAAAAQAAAAMAAABTAAAAcxAAAABkAXwAZAIZAGQDawJpAVMAKQRO2gV2YWx1ZdoIcGFzc3dvcmTaBmFiYzEyM6kAKQHaBGFyZ3NyBAAAAHIEAAAA2gg8c3RyaW5nPtoIPGxhbWJkYT4FAAAAcwAAAAA=', 'ASCII'))), {})\ndef main(args):\n    return __code__(args)\n"
+                }
+            }
+        },
+        {
+            "name": "/_/success",
+            "action": {
+                "exec": {
+                    "kind": "python:3",
+                    "code": "import types\nimport marshal\nimport base64\n__code__= types.FunctionType(marshal.loads(base64.b64decode(bytearray('4wEAAAAAAAAAAQAAAAIAAABTAAAAcwgAAABkAWQCaQFTACkDTtoHbWVzc2FnZdoHc3VjY2Vzc6kAKQHaBGFyZ3NyAwAAAHIDAAAA2gg8c3RyaW5nPtoIPGxhbWJkYT4GAAAAcwAAAAA=', 'ASCII'))), {})\ndef main(args):\n    return __code__(args)\n"
+                }
+            }
+        },
+        {
+            "name": "/_/failure",
+            "action": {
+                "exec": {
+                    "kind": "python:3",
+                    "code": "import types\nimport marshal\nimport base64\n__code__= types.FunctionType(marshal.loads(base64.b64decode(bytearray('4wEAAAAAAAAAAQAAAAIAAABTAAAAcwgAAABkAWQCaQFTACkDTtoHbWVzc2FnZdoHZmFpbHVyZakAKQHaBGFyZ3NyAwAAAHIDAAAA2gg8c3RyaW5nPtoIPGxhbWJkYT4HAAAAcwAAAAA=', 'ASCII'))), {})\ndef main(args):\n    return __code__(args)\n"
+                }
+            }
+        }
+    ]
+}
\ No newline at end of file
diff --git a/samples/demo.py b/samples/demo.py
index 26ae516..5287aa1 100644
--- a/samples/demo.py
+++ b/samples/demo.py
@@ -2,6 +2,6 @@
 
 def main():
     return composer.when(
-        composer.action('authenticate',  { 'action': lambda env, args: { 'value': args['password'] == 'abc123' } }),
-        composer.action('success', { 'action': lambda env, args: { 'message': 'success' } }),
-        composer.action('failure', { 'action': lambda env, args: { 'message': 'failure' } }))
+        composer.action('authenticate',  { 'action': lambda args: { 'value': args['password'] == 'abc123' } }),
+        composer.action('success', { 'action': lambda args: { 'message': 'success' } }),
+        composer.action('failure', { 'action': lambda args: { 'message': 'failure' } }))
diff --git a/settarget.sh b/settarget.sh
new file mode 100755
index 0000000..9cd3e9f
--- /dev/null
+++ b/settarget.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+bx login -o villard@us.ibm.com -s composer-test
+bx wsk property get
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 3825a9c..0789c8d 100644
--- a/setup.py
+++ b/setup.py
@@ -38,7 +38,8 @@
     zip_safe=False,
     entry_points = {
         'console_scripts': [
-            'pycompose = composer.__main__:main'
+            'pycompose = pycompose.__main__:main',
+            'pydeploy = pydeploy.__main__:main'
         ]
     },
     classifiers=[
diff --git a/src/composer/__main__.py b/src/composer/__main__.py
deleted file mode 100644
index 0242d4b..0000000
--- a/src/composer/__main__.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env python3
-
-import argparse
-import json
-import composer
-# from composer import __version__
-
-def main():
-    parser = argparse.ArgumentParser(description='process compositions', prog='pycompose', usage='%(prog)s composition.py command [flags]')
-    parser.add_argument('file', metavar='composition', type=str, help='the composition')
-    parser.add_argument('-v', '--version', action='store_true', help='output the composer version')
-    parser.add_argument('--ast', action='store_true', help='output ast')
-
-
-    args = parser.parse_args()
-
-    if args.version:
-        print(composer.__version__)
-        return
-
-    filename = args.file
-    with open(filename, encoding='UTF-8') as f:
-        source = f.read()
-
-    main = '''exec(code + "\\n__out__['value'] = main()", {'__out__':__out__})'''
-    
-    try:
-        out = {'value': None}
-        exec(main, {'code': source, '__out__': out})        
-    
-        composition = out['value']
-        composition = composition.compile()
-
-        if args.ast:
-            composition = str(composition['ast'])
-        else:
-            composition['ast'] = str(composition['ast'])
-            composition['composition'] = str(composition['composition'])
-
-        print(composition)
-    except Exception as err:
-        print(err)
-        return 
-    
-if __name__ == '__main__':
-    main()
diff --git a/src/composer/composer.py b/src/composer/composer.py
index 7232cd2..a58300d 100644
--- a/src/composer/composer.py
+++ b/src/composer/composer.py
@@ -437,7 +437,12 @@
     
     elif 'action' in options and callable(options['action']):
         if options['action'].__name__ == '<lambda>':
-            exc = str(base64.b64encode(marshal.dumps(options['action'].__code__)), 'ASCII')
+            l = str(base64.b64encode(marshal.dumps(options['action'].__code__)), 'ASCII')
+            exc = '''import types\nimport marshal\nimport base64
+__code__= types.FunctionType(marshal.loads(base64.b64decode(bytearray(\''''+ l +'''\', 'ASCII'))), {})
+def main(args):
+    return __code__(args)
+'''
         else:    
             try:
                 exc = inspect.getsource(options['action'])
@@ -451,7 +456,7 @@
     
     composition = { 'type': 'action', 'name': name, '.combinator': lambda: combinators['action']}
     if exc is not None:
-        composition['action'] = exc
+        composition['action'] = { 'exec': exc }
 
     return Composition(composition)
 
diff --git a/src/conductor/conductor.py b/src/conductor/conductor.py
index f051f17..92e484e 100644
--- a/src/conductor/conductor.py
+++ b/src/conductor/conductor.py
@@ -30,8 +30,7 @@
 def synthesize(composition): # dict
     code = '# generated by composer v'+composition['version']+' and conductor v'+__version__+'\n\nimport os\nimport functools\nimport json\nimport inspect\nimport re\nimport base64\nimport marshal\nimport types\nimport requests\nimport urllib.parse'
     code += '\n\n' + inspect.getsource(composer.ComposerError)
-    code += '\ncomposition=json.loads(\''+escape(str(composition['composition']))+'\')'
-
+    code += '\ncomposition=json.loads(\''+escape(json.dumps(composition['composition'], default=composer.serialize, ensure_ascii=True))+'\')'
     code += '\n' + inspect.getsource(conductor)
     code += '\n' + inspect.getsource(openwhisk)
     code += '\n' + inspect.getsource(Compositions)
@@ -101,7 +100,7 @@
         wsk = openwhisk.Client(options)
     except:
         wsk = Client(options)
-
+    
     wsk.compositions = Compositions(wsk)
     return wsk
 
@@ -109,10 +108,11 @@
     ''' management class for compositions '''
     def __init__(self, wsk):
         self.actions = wsk.actions
-        
+       
     def deploy(self, composition, overwrite):
-        actions = composition['actions'] if 'actions' in composition else []
+        actions = composition.get('actions', [])
         actions.append(synthesize(composition))
+        
         for action in actions:
             if overwrite:
                 try:
@@ -120,6 +120,7 @@
                 except Exception:
                     pass
             self.actions.create(action)
+            
         return actions
 
 def conductor(composition): # main.
diff --git a/src/pycompose/__main__.py b/src/pycompose/__main__.py
new file mode 100644
index 0000000..ed836fa
--- /dev/null
+++ b/src/pycompose/__main__.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+
+import argparse
+import json
+import composer
+
+def main():
+    parser = argparse.ArgumentParser(description='comppile compositions', prog='pycompose', usage='%(prog)s composition.py command [flags]')
+    parser.add_argument('file', metavar='composition', type=str, help='the composition')
+    parser.add_argument('-v', '--version', action='version', version='%(prog)s '+ composer.__version__)
+    parser.add_argument('--ast', action='store_true', help='output ast')
+
+    args = parser.parse_args()
+
+    filename = args.file
+    with open(filename, encoding='UTF-8') as f:
+        source = f.read()
+
+    main = '''exec(code + "\\n__out__['value'] = main()", {'__out__':__out__})'''
+    
+    try:
+        out = {'value': None}
+        exec(main, {'code': source, '__out__': out})        
+    
+        composition = out['value']
+        composition = composition.compile()
+
+        if args.ast:
+            composition = composition['ast']
+        
+        print(json.dumps(composition, default=composer.serialize, ensure_ascii=True))
+    except Exception as err:
+        print(err)
+        return 
+    
+if __name__ == '__main__':
+    main()
diff --git a/src/pydeploy/__main__.py b/src/pydeploy/__main__.py
new file mode 100644
index 0000000..6ed6a56
--- /dev/null
+++ b/src/pydeploy/__main__.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python3
+
+import argparse
+import json
+import composer
+import conductor
+import sys
+
+def keyValue(a):
+    parts = a.partition('=')
+    if parts[1] != '=':
+        raise 'Annotation syntax must be "KEY=VALUE"'
+    return { 'key': parts[0], 'value': parts[2] }
+
+def keyValueFromFile(a):
+    parts = a.partition('=')
+    if parts[1] != '=':
+        raise 'Annotation syntax must be "KEY=FILE"'
+
+    with open(parts[2], encoding='UTF-8') as f:
+        value = json.load(f)
+
+    return { 'key': parts[0], 'value': value }
+
+
+def main():
+    parser = argparse.ArgumentParser(description='deploy composition', prog='pydeploy', usage='%(prog)s composition composition.json [flags]')
+    parser.add_argument('name', metavar='composition', type=str, help='the composition')
+    parser.add_argument('file', metavar='composition', type=str, help='the composition')
+    parser.add_argument('--apihost', action='store', metavar='HOST', help='API HOST')
+    parser.add_argument('-i', '--insecure', action='store_true', help='bypass certificate checking')
+    parser.add_argument('-u', '--auth', metavar='KEY', help='authorization KEY')
+    parser.add_argument('-v', '--version', action='version', version='%(prog)s '+ composer.__version__)
+    parser.add_argument('-a', '--annotation', action='append', nargs=1, help='add KEY annotation with VALUE')
+    parser.add_argument('-A', '--annotation-file', action='append', nargs=1, help='add KEY annotation with FILE content')
+    parser.add_argument('-w', '--overwrite',  action='store_true', help='overwrite actions if already defined')
+    
+    args = parser.parse_args()
+    
+    try:
+        filename = args.file
+
+        with open(filename, encoding='UTF-8') as f:
+            composition = json.load(f)
+    
+        if 'ast' not in composition:
+            raise 'Composition must have a field "ast" of type dictionary'
+        if 'composition' not in composition:
+            raise 'Composition must have a field "composition" of type dictionary'
+        if 'version' not in composition:
+            raise 'Composition must have a field "composition" of type dictionary'
+        if 'actions' in composition:
+            if not isinstance(composition['actions'], list):
+                raise 'Optional field "actions" must be an array'
+        
+        composition['annotations'] = []
+
+        if args.annotation is not None:
+            composition['annotations'].extend([keyValue(a[0]) for a in args.annotation])
+
+        if args.annotation is not None:
+            composition['annotations'].extend([keyValueFromFile(a[0]) for a in args.annotation_file])
+         
+    except Exception as err:
+        print(err)
+        sys,exit(422 - 256) # Unprocessable Entity
+        
+    
+    options = { 'ignore_certs': args.insecure }
+    if args.apihost is not None:
+        options['apihost'] = args.apihost
+    if args.auth is not None:
+        options['api_key'] = args.auth
+
+    try:
+        composition['name'] = composer.parse_action_name(args.name)
+    except Exception as err:
+        print(err)
+        sys,exit(400 - 256) # Bad Request
+    
+    try:
+        actions = conductor.openwhisk(options).compositions.deploy(composition, args.overwrite)
+        names = ' '.join([n['name'] for n in actions])
+        print('ok: created action'+ ('s' if len(names) > 1 else '') + '' + names)
+    except Exception as err:    
+        print(err.error)
+        sys.exit(500 - 256)
+
+if __name__ == '__main__':
+    main()
+