/-- If `E` is a cone of shape `K` of sheaves, which is a limit on the level of presheaves,
this definition shows that the limit presheaf satisfies the multifork variant of the sheaf
condition, at a given covering `W`.

This is used below in `isSheaf_of_isLimit` to show that the limit presheaf is indeed a sheaf.
-/
def isLimitMultiforkOfIsLimit (F : K ⥤ Sheaf J D) (E : Cone (F ⋙ sheafToPresheaf J D))
    (hE : IsLimit E) (X : C) (W : J.Cover X) : IsLimit (W.multifork E.pt) :=
  Multifork.IsLimit.mk _
    (fun S => (isLimitOfPreserves ((evaluation Cᵒᵖ D).obj (op X)) hE).lift <|
      multiforkEvaluationCone F E X W S)
    (by
      intro S i
      apply (isLimitOfPreserves ((evaluation Cᵒᵖ D).obj (op i.Y)) hE).hom_ext
      intro k
      dsimp [Multifork.ofι]
      erw [Category.assoc, (E.π.app k).naturality]
      dsimp
      rw [← Category.assoc]
      erw [(isLimitOfPreserves ((evaluation Cᵒᵖ D).obj (op X)) hE).fac
        (multiforkEvaluationCone F E X W S)]
      dsimp [multiforkEvaluationCone, Presheaf.isLimitOfIsSheaf]
      

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w
inst✝² : Category.{max v u, w} D
K : Type z
inst✝¹ : Category.{z', z} K
inst✝ : HasLimitsOfShape K D
F : K ⥤ Sheaf J D
E : Cone (F ⋙ sheafToPresheaf J D)
hE : IsLimit E
X : C
W : GrothendieckTopology.Cover J X
S : Multifork (GrothendieckTopology.Cover.index W E.pt)
i : (GrothendieckTopology.Cover.index W E.pt).L
k : K
⊢ Presheaf.IsSheaf.amalgamate (_ : Presheaf.IsSheaf J (F.obj k).val) W
        (fun I =>
          Multifork.ι
            (Multifork.ofι (GrothendieckTopology.Cover.index W (F.obj k).val) S.pt
              (fun i => Multifork.ι S i ≫ (E.π.app k).app (op i.Y))
              (_ :
                ∀ (i : (GrothendieckTopology.Cover.index W (F.obj k).val).R),
                  (fun i => Multifork.ι S i ≫ (E.π.app k).app (op i.Y))
                        (MulticospanIndex.fstTo (GrothendieckTopology.Cover.index W (F.obj k).val) i) ≫
                      MulticospanIndex.fst (GrothendieckTopology.Cover.index W (F.obj k).val) i =
                    (fun i => Multifork.ι S i ≫ (E.π.app k).app (op i.Y))
                        (MulticospanIndex.sndTo (GrothendieckTopology.Cover.index W (F.obj k).val) i) ≫
                      MulticospanIndex.snd (GrothendieckTopology.Cover.index W (F.obj k).val) i))
            I)
        (_ :
          ∀ (I : GrothendieckTopology.Cover.Relation W),
            Multifork.ι
                  (Multifork.ofι (GrothendieckTopology.Cover.index W (F.obj k).val) S.pt
                    (fun i => Multifork.ι S i ≫ (E.π.app k).app (op i.Y))
                    (_ :
                      ∀ (i : (GrothendieckTopology.Cover.index W (F.obj k).val).R),
                        (fun i => Multifork.ι S i ≫ (E.π.app k).app (op i.Y))
                              (MulticospanIndex.fstTo (GrothendieckTopology.Cover.index W (F.obj k).val) i) ≫
                            MulticospanIndex.fst (GrothendieckTopology.Cover.index W (F.obj k).val) i =
                          (fun i => Multifork.ι S i ≫ (E.π.app k).app (op i.Y))
                              (MulticospanIndex.sndTo (GrothendieckTopology.Cover.index W (F.obj k).val) i) ≫
                            MulticospanIndex.snd (GrothendieckTopology.Cover.index W (F.obj k).val) i))
                  (MulticospanIndex.fstTo (GrothendieckTopology.Cover.index W (F.obj k).val) I) ≫
                MulticospanIndex.fst (GrothendieckTopology.Cover.index W (F.obj k).val) I =
              Multifork.ι
                  (Multifork.ofι (GrothendieckTopology.Cover.index W (F.obj k).val) S.pt
                    (fun i => Multifork.ι S i ≫ (E.π.app k).app (op i.Y))
                    (_ :
                      ∀ (i : (GrothendieckTopology.Cover.index W (F.obj k).val).R),
                        (fun i => Multifork.ι S i ≫ (E.π.app k).app (op i.Y))
                              (MulticospanIndex.fstTo (GrothendieckTopology.Cover.index W (F.obj k).val) i) ≫
                            MulticospanIndex.fst (GrothendieckTopology.Cover.index W (F.obj k).val) i =
                          (fun i => Multifork.ι S i ≫ (E.π.app k).app (op i.Y))
                              (MulticospanIndex.sndTo (GrothendieckTopology.Cover.index W (F.obj k).val) i) ≫
                            MulticospanIndex.snd (GrothendieckTopology.Cover.index W (F.obj k).val) i))
                  (MulticospanIndex.sndTo (GrothendieckTopology.Cover.index W (F.obj k).val) I) ≫
                MulticospanIndex.snd (GrothendieckTopology.Cover.index W (F.obj k).val) I) ≫
      (F.obj k).val.map i.f.op =
    Multifork.ι S i ≫ (E.π.app k).app (op i.Y)

Next tactic:
erw [Presheaf.IsSheaf.amalgamate_map]