/-- The diagram used to define `P⁺`, composed with `F`, is isomorphic
to the diagram used to define `P ⋙ F`. -/
def diagramCompIso (X : C) : J.diagram P X ⋙ F ≅ J.diagram (P ⋙ F) X :=
  NatIso.ofComponents
    (fun W => by
      refine' _ ≪≫ HasLimit.isoOfNatIso (W.unop.multicospanComp _ _).symm
      refine'
        (isLimitOfPreserves F (limit.isLimit _)).conePointUniqueUpToIso (limit.isLimit _))
    (by
      intro A B f
      -- porting note: this used to work with `ext`
      -- See https://github.com/leanprover-community/mathlib4/issues/5229
      apply Multiequalizer.hom_ext
      dsimp
      

Proof state:
case h
C : Type u
inst✝⁵ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w₁
inst✝⁴ : Category.{max v u, w₁} D
E : Type w₂
inst✝³ : Category.{max v u, w₂} E
F : D ⥤ E
inst✝² : ∀ (α β : Type (max v u)) (fst snd : β → α), HasLimitsOfShape (WalkingMulticospan fst snd) D
inst✝¹ : ∀ (α β : Type (max v u)) (fst snd : β → α), HasLimitsOfShape (WalkingMulticospan fst snd) E
inst✝ : (X : C) → (W : Cover J X) → (P : Cᵒᵖ ⥤ D) → PreservesLimit (MulticospanIndex.multicospan (Cover.index W P)) F
P : Cᵒᵖ ⥤ D
X : C
A B : (Cover J X)ᵒᵖ
f : A ⟶ B
⊢ ∀ (a : (Cover.index B.unop (P ⋙ F)).L),
    (F.map
            (Multiequalizer.lift (Cover.index B.unop P) (multiequalizer (Cover.index A.unop P))
              (fun I => Multiequalizer.ι (Cover.index A.unop P) (Cover.Arrow.map I f.unop))
              (_ :
                ∀ (I : (Cover.index B.unop P).R),
                  Multiequalizer.ι (Cover.index A.unop P)
                        (MulticospanIndex.fstTo (Cover.index A.unop P) (Cover.Relation.map I f.unop)) ≫
                      MulticospanIndex.fst (Cover.index A.unop P) (Cover.Relation.map I f.unop) =
                    Multiequalizer.ι (Cover.index A.unop P)
                        (MulticospanIndex.sndTo (Cover.index A.unop P) (Cover.Relation.map I f.unop)) ≫
                      MulticospanIndex.snd (Cover.index A.unop P) (Cover.Relation.map I f.unop))) ≫
          (IsLimit.conePointUniqueUpToIso
                (isLimitOfPreserves F (limit.isLimit (MulticospanIndex.multicospan (Cover.index B.unop P))))
                (limit.isLimit (MulticospanIndex.multicospan (Cover.index B.unop P) ⋙ F))).hom ≫
            (HasLimit.isoOfNatIso (Cover.multicospanComp F P B.unop).symm).hom) ≫
        Multiequalizer.ι (Cover.index B.unop (P ⋙ F)) a =
      (((IsLimit.conePointUniqueUpToIso
                (isLimitOfPreserves F (limit.isLimit (MulticospanIndex.multicospan (Cover.index A.unop P))))
                (limit.isLimit (MulticospanIndex.multicospan (Cover.index A.unop P) ⋙ F))).hom ≫
            (HasLimit.isoOfNatIso (Cover.multicospanComp F P A.unop).symm).hom) ≫
          Multiequalizer.lift (Cover.index B.unop (P ⋙ F)) (multiequalizer (Cover.index A.unop (P ⋙ F)))
            (fun I => Multiequalizer.ι (Cover.index A.unop (P ⋙ F)) (Cover.Arrow.map I f.unop))
            (_ :
              ∀ (I : (Cover.index B.unop (P ⋙ F)).R),
                Multiequalizer.ι (Cover.index A.unop (P ⋙ F))
                      (MulticospanIndex.fstTo (Cover.index A.unop (P ⋙ F)) (Cover.Relation.map I f.unop)) ≫
                    MulticospanIndex.fst (Cover.index A.unop (P ⋙ F)) (Cover.Relation.map I f.unop) =
                  Multiequalizer.ι (Cover.index A.unop (P ⋙ F))
                      (MulticospanIndex.sndTo (Cover.index A.unop (P ⋙ F)) (Cover.Relation.map I f.unop)) ≫
                    MulticospanIndex.snd (Cover.index A.unop (P ⋙ F)) (Cover.Relation.map I f.unop))) ≫
        Multiequalizer.ι (Cover.index B.unop (P ⋙ F)) a

Next tactic:
simp only [Functor.mapCone_π_app, Multiequalizer.multifork_π_app_left, Iso.symm_hom,
        Multiequalizer.lift_ι, eqToHom_refl, Category.comp_id,
        limit.conePointUniqueUpToIso_hom_comp,
        GrothendieckTopology.Cover.multicospanComp_hom_inv_left, HasLimit.isoOfNatIso_hom_π,
        Category.assoc]