/-- If `a₁ a₂ : A ⟶ Y` is a kernel pair for `g : Y ⟶ Z`, then `a₁ ×[Z] X` and `a₂ ×[Z] X`
(`A ×[Z] X ⟶ Y ×[Z] X`) is a kernel pair for `Y ×[Z] X ⟶ X`. -/
protected theorem pullback {X Y Z A : C} {g : Y ⟶ Z} {a₁ a₂ : A ⟶ Y} (h : IsKernelPair g a₁ a₂)
    (f : X ⟶ Z) [HasPullback f g] [HasPullback f (a₁ ≫ g)] :
    IsKernelPair (pullback.fst : pullback f g ⟶ X)
      (pullback.map f _ f _ (𝟙 X) a₁ (𝟙 Z) (by simp) <| Category.comp_id _)
      (pullback.map _ _ _ _ (𝟙 X) a₂ (𝟙 Z) (by simp) <| (Category.comp_id _).trans h.1.1) := by
  refine' ⟨⟨by rw [pullback.lift_fst, pullback.lift_fst]⟩, ⟨PullbackCone.isLimitAux _
    (fun s => pullback.lift (s.fst ≫ pullback.fst)
      (h.lift (s.fst ≫ pullback.snd) (s.snd ≫ pullback.snd) _ ) _) (fun s => _) (fun s => _)
        (fun s m hm => _)⟩⟩
  · simp_rw [Category.assoc, ← pullback.condition, ← Category.assoc, s.condition]
  · simp only [assoc, lift_fst_assoc, pullback.condition]
  · ext <;> simp
  · ext
    · simp [s.condition]
    · simp
  · apply pullback.hom_ext
    · simpa using hm WalkingCospan.left =≫ pullback.fst
    · 

Proof state:
case refine'_5.h₁
C : Type u
inst✝² : Category.{v, u} C
R X✝ Y✝ Z✝ : C
f✝ : X✝ ⟶ Y✝
a b : R ⟶ X✝
X Y Z A : C
g : Y ⟶ Z
a₁ a₂ : A ⟶ Y
h : IsKernelPair g a₁ a₂
f : X ⟶ Z
inst✝¹ : HasPullback f g
inst✝ : HasPullback f (a₁ ≫ g)
s : PullbackCone pullback.fst pullback.fst
m :
  s.pt ⟶
    (PullbackCone.mk (pullback.map f (a₁ ≫ g) f g (𝟙 X) a₁ (𝟙 Z) (_ : f ≫ 𝟙 Z = 𝟙 X ≫ f) (_ : (a₁ ≫ g) ≫ 𝟙 Z = a₁ ≫ g))
        (pullback.map f (a₁ ≫ g) f g (𝟙 X) a₂ (𝟙 Z) (_ : f ≫ 𝟙 Z = 𝟙 X ≫ f) (_ : (a₁ ≫ g) ≫ 𝟙 Z = a₂ ≫ g))
        (_ :
          pullback.map f (a₁ ≫ g) f g (𝟙 X) a₁ (𝟙 Z) (_ : f ≫ 𝟙 Z = 𝟙 X ≫ f) (_ : (a₁ ≫ g) ≫ 𝟙 Z = a₁ ≫ g) ≫
              pullback.fst =
            pullback.map f (a₁ ≫ g) f g (𝟙 X) a₂ (𝟙 Z) (_ : f ≫ 𝟙 Z = 𝟙 X ≫ f) (_ : (a₁ ≫ g) ≫ 𝟙 Z = a₂ ≫ g) ≫
              pullback.fst)).pt
hm :
  ∀ (j : WalkingCospan),
    m ≫
        (PullbackCone.mk
                (pullback.map f (a₁ ≫ g) f g (𝟙 X) a₁ (𝟙 Z) (_ : f ≫ 𝟙 Z = 𝟙 X ≫ f) (_ : (a₁ ≫ g) ≫ 𝟙 Z = a₁ ≫ g))
                (pullback.map f (a₁ ≫ g) f g (𝟙 X) a₂ (𝟙 Z) (_ : f ≫ 𝟙 Z = 𝟙 X ≫ f) (_ : (a₁ ≫ g) ≫ 𝟙 Z = a₂ ≫ g))
                (_ :
                  pullback.map f (a₁ ≫ g) f g (𝟙 X) a₁ (𝟙 Z) (_ : f ≫ 𝟙 Z = 𝟙 X ≫ f) (_ : (a₁ ≫ g) ≫ 𝟙 Z = a₁ ≫ g) ≫
                      pullback.fst =
                    pullback.map f (a₁ ≫ g) f g (𝟙 X) a₂ (𝟙 Z) (_ : f ≫ 𝟙 Z = 𝟙 X ≫ f) (_ : (a₁ ≫ g) ≫ 𝟙 Z = a₂ ≫ g) ≫
                      pullback.fst)).π.app
          j =
      s.π.app j
⊢ m ≫ pullback.snd =
    (fun s =>
          pullback.lift (PullbackCone.fst s ≫ pullback.fst)
            (lift h (PullbackCone.fst s ≫ pullback.snd) (PullbackCone.snd s ≫ pullback.snd)
              (_ : (PullbackCone.fst s ≫ pullback.snd) ≫ g = (PullbackCone.snd s ≫ pullback.snd) ≫ g))
            (_ :
              (PullbackCone.fst s ≫ pullback.fst) ≫ f =
                lift h (PullbackCone.fst s ≫ pullback.snd) (PullbackCone.snd s ≫ pullback.snd)
                    (_ : (PullbackCone.fst s ≫ pullback.snd) ≫ g = (PullbackCone.snd s ≫ pullback.snd) ≫ g) ≫
                  a₁ ≫ g))
        s ≫
      pullback.snd

Next tactic:
apply PullbackCone.IsLimit.hom_ext h.isLimit