Maybe it will sound strange, but what is this task REALLY about? I mean - I can see two problems here, but no clear information about which problem is a real problem and - if it is - what is the expected behavior.
Problems I can see are:
1) Type of returned value changes depending on the value source (list for user provided or list for default)
2) It's impossible to set list as 'default'
I understand that this task concentrates on 1st one, however changing behavior described in 2nd would - in my oppinion - fix 1st one too - am I right? User would "define" the returned type by defining the 'default' as a list or string.
But - if we assume that we only discuss 1st problem here - what is the expected behavior? Provided workaround is suggesting that we expect string, but - basing on current nargs behavior and "intuition" - I'd rather expect to get a list, when I define nargs with "*" or "+". This sounds "natural" for me.
Could someone explain me the problem and the expected behavior in a clear way?
Sorry if I'm not clear, but it's my first post here and maybe I've missed something in the description or I assume something that is not true (especially that the task is quite old... ;) ).

The real issue is that the choices flag does not work with a default flag and * nargs.
The following works as expected:
>>> parser.add_argument('chosen', nargs='*', default=['a'])
>>> print(parser.parse_args())
Namespace(chosen=['a'])
>>> print(parser.parse_args(['a', 'b']))
Namespace(chosen=['a', 'b'])
Introducing a choices constraint breaks down when using the defaults:
>>> parser.add_argument('chosen', nargs='*', default=['a'], choices=['a', 'b'])
>>> print(parser.parse_args(['a']))
Namespace(chosen=['a'])
>>> print(parser.parse_args())
error: argument chosen: invalid choice: ['a'] (choose from 'a', 'b')
I would expect instead to have Namespace.chosen populated with the default list as before, but the choices constraint check does not validate correctly.
I think that changing the choices constraint logic to iterate over the default values if nargs results in a list would be a possible solution.

I've added 2 more tests,
one with default='c', which worked before.
one with default=['a','b'], which only works with this change.
http://bugs.python.org/issue16878 is useful reference, since it documents
the differences between nargs="?" and nargs="*", and their handling of
their defaults.

There's a complicating issue - should these default values be passed through the type function?
In most cases in `_get_values`, the string first goes through `_get_value`, and then to `_check_value`.
For example the 'else:' case:
value = [self._get_value(action, v) for v in arg_strings]
for v in value:
self._check_value(action, v)
The '*' positional case could coded the same way, allowing:
parser.add_argument('foo',
nargs='*',
type=int,
choices=range(5),
default=['0',1,'2'])
and objecting to
default=[6,'7','a'] # out of range string or int or invalid value
This does impose a further constraint on the 'type' function, that it accepts a converted value. e.g. int(1) is as valid as int('1').
But we need to be careful that this case is handled in a way that is consistent with other defaults (including the recent change that delayed evaluating defaults till the end).