Okay, I'm not up for much right now. I'm just going to sketch stuff out according to what I was thinking about as I worked yesterday.
So, the flex methods conceptually exist in a matrix which I have only partially filled in. There are three parts of a Command that can accommodate an IO type. There are arguments, environment variables, and values based on arguments and environment variables, but not explicitly passed.
So, between those two axes, let's see what behaviors need to be considered.
- All Output values need to depend on a non-strict superset of the keys required by the rest of the command. If this condition is violated, then two different commands will contend for the same output.
- All extra values need to depend on a non-strict superset of the keys required by the rest of the command.
Actually, oh no. This is some kind of variance thing. extra values require a flipped treatment from arg values, because adding Input values to a command is problematic, but adding Output values is... Okay, so, it needs to be a superset, but it shouldn't really break anything except for some mental models in the event that it's a strict superset. A strict superset should probably generate a warning, however, because I'm pretty sure it violates some convenient simplifications that usually hold.
So, really what has to happen for extra Input values (and this is not implemented yet), is that every associated key must be used by an arg or env value. Like, Dynamic values have to track two sets of keys, say "provided" and "required". "Provided" plays the role of the current key set, but what's different is that not all new keys go in there. The instantiation logic now needs a validation step, that checks whether all "required" keys are "provided". This should be accomplished via a private variable and a public wrapper, so that combinator logic can bypass the validation.
Thinking about adding all of this metadata, I'm a little tempted to factor out the metadata into its own class and writing methods to implement the field manipulation. The latter part is definitely a good idea. I'm not sure about the former.
Anyway, the existing logic is at its best when it comes to the args. Considering the case of environment variables, maybe the thing to do for now is to require that, if they're used, they get passed all of the keys they use.
I think to make this work, I need additional fields or wrappers for Invocation, but I'm not sure what the best implementation is. Now that I have this new perspective, I'm going to need to take some time to plan things out.
I'm feeling wiped out right now, so I'm not going to draw this out.