/-- Sufficient conditions for a class to be the age of a countably-generated structure. -/
theorem exists_cg_is_age_of (hn : K.Nonempty)
    (h : ∀ M N : Bundled.{w} L.Structure, Nonempty (M ≃[L] N) → (M ∈ K ↔ N ∈ K))
    (hc : (Quotient.mk' '' K).Countable)
    (fg : ∀ M : Bundled.{w} L.Structure, M ∈ K → Structure.FG L M) (hp : Hereditary K)
    (jep : JointEmbedding K) : ∃ M : Bundled.{w} L.Structure, Structure.CG L M ∧ L.age M = K := by
  obtain ⟨F, hF⟩ := hc.exists_eq_range (hn.image _)
  simp only [Set.ext_iff, Quotient.forall, mem_image, mem_range, Quotient.eq'] at hF
  simp_rw [Quotient.eq_mk_iff_out] at hF
  have hF' : ∀ n : ℕ, (F n).out ∈ K := by
    intro n
    obtain ⟨P, hP1, hP2⟩ := (hF (F n).out).2 ⟨n, Setoid.refl _⟩
    -- Porting note: fix hP2 because `Quotient.out (Quotient.mk' x) ≈ a` was not simplified
    -- to `x ≈ a` in hF
    replace hP2 := Setoid.trans (Setoid.symm (Quotient.mk_out P)) hP2
    exact (h _ _ hP2).1 hP1
  choose P hPK hP hFP using fun (N : K) (n : ℕ) => jep N N.2 (F (n + 1)).out (hF' _)
  let G : ℕ → K := @Nat.rec (fun _ => K) ⟨(F 0).out, hF' 0⟩ fun n N => ⟨P N n, hPK N n⟩
  -- Poting note: was
  -- let f : ∀ i j, i ≤ j → G i ↪[L] G j := DirectedSystem.natLeRec fun n => (hP _ n).some
  let f : ∀ (i j : ℕ), i ≤ j → (G i).val ↪[L] (G j).val := by
    refine DirectedSystem.natLERec (G' := fun i => (G i).val) (L := L) ?_
    dsimp only
    exact (fun n => (hP _ n).some)
  have : DirectedSystem (fun n ↦ (G n).val) fun i j h ↦ ↑(f i j h) := by
    dsimp; 

Proof state:
L : Language
K : Set (Bundled (Structure L))
M : Type w
inst✝¹ : Structure L M
N : Type w
inst✝ : Structure L N
hn : Set.Nonempty K
h : ∀ (M N : Bundled (Structure L)), Nonempty (↑M ≃[L] ↑N) → (M ∈ K ↔ N ∈ K)
hc : Set.Countable (Quotient.mk' '' K)
fg : ∀ M ∈ K, Structure.FG L ↑M
hp : Hereditary K
jep : JointEmbedding K
F : ℕ → Quotient equivSetoid
hF : ∀ (a : Bundled (Structure L)), (∃ x ∈ K, Quotient.out (Quotient.mk' x) ≈ a) ↔ ∃ y, Quotient.out (F y) ≈ a
hF' : ∀ (n : ℕ), Quotient.out (F n) ∈ K
P : ↑K → ℕ → Bundled (Structure L)
hPK : ∀ (N : ↑K) (n : ℕ), P N n ∈ K
hP : ∀ (N : ↑K) (n : ℕ), (fun M N => Nonempty (↑M ↪[L] ↑N)) (↑N) (P N n)
hFP : ∀ (N : ↑K) (n : ℕ), (fun M N => Nonempty (↑M ↪[L] ↑N)) (Quotient.out (F (n + 1))) (P N n)
G : ℕ → ↑K :=
  Nat.rec { val := Quotient.out (F 0), property := (_ : Quotient.out (F 0) ∈ K) } fun n N =>
    { val := P N n, property := (_ : P N n ∈ K) }
f : (i j : ℕ) → i ≤ j → ↑↑(G i) ↪[L] ↑↑(G j) :=
  DirectedSystem.natLERec
    (id fun n =>
      Nonempty.some
        (_ :
          (fun M N => Nonempty (↑M ↪[L] ↑N))
            (↑(Nat.rec { val := Quotient.out (F 0), property := (_ : Quotient.out (F 0) ∈ K) }
                (fun n N => { val := P N n, property := (_ : P N n ∈ K) }) n))
            (P
              (Nat.rec { val := Quotient.out (F 0), property := (_ : Quotient.out (F 0) ∈ K) }
                (fun n N => { val := P N n, property := (_ : P N n ∈ K) }) n)
              n)))
⊢ DirectedSystem
    (fun n =>
      ↑↑(Nat.rec { val := Quotient.out (F 0), property := (_ : Quotient.out (F 0) ∈ K) }
            (fun n N => { val := P N n, property := (_ : P N n ∈ K) }) n))
    fun i j h =>
    ⇑(DirectedSystem.natLERec
        (fun n =>
          Nonempty.some
            (_ :
              (fun M N => Nonempty (↑M ↪[L] ↑N))
                (↑(Nat.rec { val := Quotient.out (F 0), property := (_ : Quotient.out (F 0) ∈ K) }
                    (fun n N => { val := P N n, property := (_ : P N n ∈ K) }) n))
                (P
                  (Nat.rec { val := Quotient.out (F 0), property := (_ : Quotient.out (F 0) ∈ K) }
                    (fun n N => { val := P N n, property := (_ : P N n ∈ K) }) n)
                  n)))
        i j h)

Next tactic:
infer_instance