(* ---- helper tactics for lemma below. -------------- *)
(* Convert a goal of the form  Par (XX ++ G) dom(XX ++ G) a b ==> Par G D a b *)
Ltac ind_hyp a k1 k2 :=
match goal with
[ H : ∀ a' : tm, Ctx ?G → Par ?G ?D a a' → Typing ?G a' ?A ∧ DefEq ?G empty a a' ?A,
H1 : Par ?G ?D a ?a',
H2 : Ctx ?G |- _ ] =>
move: (@H a' H2 H1) => [k1 k2]
end.
Ltac ind_hyp_open x B k1 k2 :=
match goal with
[ H : forall x, x `notin` ?L -> forall a', Ctx ([(x, ?s)] ++ ?G) -> Par ([(x, ?s)] ++ ?G) ?D (open_tm_wrt_tm B (a_Var_f x)) a' -> ?P,
H1 : Ctx ?G,
H10 :  forall x : atom, x `notin` ?L0 → Par ?G ?D0 (open_tm_wrt_tm B (a_Var_f x)) (open_tm_wrt_tm ?B' (a_Var_f x))
|- _ ] =>
move: (H x ltac:(auto) (open_tm_wrt_tm B' (a_Var_f x)) ltac:(auto)
(context_Par_irrelevance ([(x, s)] ++ G) (dom ([(x,s)] ++ G)) (H10 x ltac:(auto)))) => [k0 k1]
end.

(* Specifications: *)
(*  This lemma is not true in the presence of Eta-reduction in Par. Instead, we should prove preservation for the head_reduction relation that does not include eta.   (* Extend to D insteadn of just dom G??? *)
Lemma type_reduction_mutual:
(forall G a A,     Typing G a A    ->
forall a', Ctx G -> Par G (dom G) a a'-> Typing G a' A /\ DefEq G empty a a' A) /\
(forall G phi,     PropWff G phi   -> forall A B T, Ctx G -> phi = Eq A B T ->
(forall A' B' T', Par G (dom G) A A' -> Par G (dom G) B B' -> Par G (dom G) T T' ->
PropWff G (Eq A' B' T') /\ Iso G empty phi (Eq A' B' T'))) /\
(forall G D p1 p2, Iso G D p1 p2   -> True) /\
(forall G D A B T, DefEq G D A B T -> True) /\
(forall G1,        Ctx G1 -> True).