I think you can safely claim that you aren't a beginner anymore.
Imports
This style:
from typing import Callable
from typing import Generic
from typing import NewType
from typing import Optional
from typing import Sequence
from typing import TYPE_CHECKING
from typing import TypeVar
is kind of nasty. I've seen it recommended before by some linters but not others. isort by default does the opposite, and tuple-imports as in
from typing import Callable, Generic, ...
This is a matter of taste. You apparently prefer the line-separated style because it improves diffs, which is nominally true; but you can have your cake and eat it too:
from typing import (
    Callable,
    Generic,
    NewType,
    ...
Entry point
I hope that when you say viv.main you actually mean viv.__main__, which is a built-in package structure better suited to main entry.
Separate away your argparse definitions from your main method.
Logic-by-exception
Pythonistas variously claim that logic-by-exception is either endemic to the language or standard practice. I find it gross and avoidable. So things like this:
        try:
            # this will capture escaped 'foo' with or without <requirement>
            _, package_ref, requirement = package.split("'", 2)
        except ValueError:  # not enough values to unpack - i.e. escaped string not found
            pass
        else:
            return package_ref, requirement or None
are better expressed as
# this will capture escaped 'foo' with or without <requirement>
parts = package.split("'", 2)
if len(parts) == 3:
    _, package_ref, requirement = parts
    return package_ref, requirement or None
# ...
Or if you want to be even fancier, read about PEP636 structural pattern matching. Similar story for your KeyError.
Command-line switch inference
I find this:
        package_ref can be 1 of the following
         1. Local directory (which must contain a viv.toml, or viv will report an error).
         2. Project or archive URL.
         3. Local Repo.
         4. A known alias to any of the above
to make life harder for everyone - the programmer and the user. This kind of clever attempt at inference kneecaps validation and requires heuristics. You're better off having four mutually exclusive command-line arguments. Then, if the user passes something that doesn't smell like a URL, you can error out before sending the request to the HTTP stack (among other things). You ask:
I hadn't even considered passing a flag for distinguishing package types - do you envisage one flag for every package, or only one flag for each kind and an array of packages on the command line (collect)?
It's up to you. I think a simple and understandable style would be e.g.
--url http://a --url http://b --local ~/me.git
Asserts
As in another review, don't assert in production code. Raise exceptions instead (and not AssertionError!)
First: the syntax sucks. Lots of discussion - PEP679 included - partially covers this. Python made a massive and to my mind inexplicable mistake, when they were designing Python 3: they correctly required parens on print, and for whatever blessed reason, didn't similarly require parens on assert. assert syntax has some really nasty pitfalls that will silently do the wrong thing and ruin your day.
Second: as already mentioned in the other review, assert can be trivially disabled on the command line, and it should not be possible to disable your sanity checks. If you want to guard against programmer errors, great: do that in a unit test instead, which is more thorough, powerful and well-suited to the task. This is related to a pattern - that can become an anti-pattern if you're not careful - seen more commonly in C-likes: tailoring the program at compile time with the use of precompiler macros to a given environment or program flavour. This creates a complexity explosion - the programmer needs to understand not only the runtime state of the program, but the compile-time state of the program, and that can complicate debugging and deployment.
Third: intent matters. The intent of an assert, as communicated to future self and other programmers, is that of a non-production test. This is a matter of convention and industrially shared understanding.
Built-in exit
Don't raise SystemExit where you've done it - instead, just exit().
You say:
raise SystemExitis done because apparently if you run python with the -S flag or if site modules are not present, exit won't exist without explicit import whereas raise SystemExit should always work - explanation on YouTube here
Ehhhhhhhh. See the command-line docs and the site docs for further reading. I've not once seen an environment where this has been omitted. This is such a narrow and unlikely technicality that in my opinion the cure is worse than the disease.
If you're going for a general-use package intended for distribution with egg/setuptools/etc., proper use of a __main__ file and a reusable main() function that does not exit - and just returns an integer - will offer the end user enough of workaround in the unlikely case that the environment is non-standard and missing the exit symbol.