Is it safe to rely on the order of an INSERT's OUTPUT clause?
Can I rely on the returned identity values from the dbo.Target table
  insert to be returned in the order they existed in the 1) VALUES
  clause and 2) #Target table, so that I can correlate them by their
  position in the output rowset back to the original input?


No, you can't rely on anything to be guaranteed without an actual documented guarantee. The documentation explicitly states there is no such guarantee.


  SQL Server does not guarantee the order in which rows are processed
  and returned by DML statements using the OUTPUT clause. It is up to
  the application to include an appropriate WHERE clause that can
  guarantee the desired semantics, or understand that when multiple rows
  may qualify for the DML operation, there is no guaranteed order.


This would rely on a lot of undocumented assumptions


The order the rows are output from the constant scan is in the same order as the values clause (I've never seen them differ but AFAIK this is not guaranteed).
The order the rows are inserted will be the same as the order they are output from the constant scan (definitely not always the case).
If using a "wide" (per index) execution plan the values from the output clause will be pulled from the clustered index update operator and not that of any secondary indexes.
That the order is guaranteed to be preserved thereafter - e.g. when packaging rows up for transmission over the network.
That even if the order appears predictable now implementation changes to features such as parallel insert won't change the order in the future (currently if the OUTPUT clause is specified in the INSERT…SELECT statement to return results to the client, then parallel plans are disabled in general, including INSERTs)


An example of point two failing (assuming clustered PK of (Color, Action)) can be seen if you add 600 rows to the VALUES clause. Then the plan has a sort operator before the insert so losing your original order in the VALUES clause.

There is a documented way of achieving your goal though and this is to add a numbering to the source and use MERGE instead of INSERT

MERGE dbo.Target
USING (VALUES (1, 'Blue', 'New', 1234),
              (2, 'Blue', 'Cancel', 4567),
              (3, 'Red', 'New', 5678) ) t (SourceId, Color, Action, Code)
ON 1 = 0
WHEN NOT MATCHED THEN
  INSERT (Color,
          Action,
          Code)
  VALUES (Color,
          Action,
          Code)
OUTPUT t.SourceId,
       inserted.TargetId; 




@a_horse_with_no_name


  Is the merge really necessary? Couldn't you just do an insert into ...
  select ... from (values (..)) t (...) order by sourceid?


Yes you could. Ordering guarantees in SQL Server… states that 


  INSERT queries that use SELECT with ORDER BY to populate rows
  guarantees how identity values are computed but not the order in which
  the rows are inserted


So you could use

INSERT dbo.Target (Color, Action, Code)
OUTPUT inserted.TargetId
SELECT t.Color, t.Action, t.Code
FROM
(VALUES (1, 'Blue', 'New', 1234),
        (2, 'Blue', 'Cancel', 4567),
        (3, 'Red', 'New', 5678) ) t (SourceId, Color, Action, Code)
ORDER BY t.SourceId




This would guarantee that the identity values are assigned in order of t.SourceId but not that they are output in any particular order or that the identity column values assigned have no gaps (e.g. if a concurrent insert is attempted).