[proofplan]
The oscillation of $g \circ f$ on a subinterval depends on both the oscillation of $f$ (which determines the range of inputs to $g$) and the modulus of continuity of $g$. We classify subintervals into "good" (small oscillation of $f$, so uniform continuity of $g$ controls $g \circ f$) and "bad" (large oscillation of $f$, controlled only by the crude bound $2M$). The [Riemann criterion](/theorems/281) for $f$ limits the total length of bad subintervals, making both contributions sum to less than $\varepsilon$.
[/proofplan]
[step:Establish uniform continuity of $g$ and set up the partition from the Riemann criterion for $f$]
Since $g$ is continuous on $[A,B]$, the [Heine-Cantor theorem](/theorems/280) gives uniform continuity: for every $\eta > 0$, there exists $\sigma > 0$ such that $|s - t| < \sigma$ implies $|g(s) - g(t)| < \eta$ for all $s, t \in [A,B]$. Let $M = \sup_{t \in [A,B]} |g(t)|$, which is finite because $g$ is continuous on a compact interval.
Fix $\varepsilon > 0$. Set $\eta = \varepsilon/(2(b-a))$ and let $\sigma > 0$ be the corresponding modulus of continuity. Since $f$ is Riemann integrable, the [Riemann criterion](/theorems/281) provides a partition $P = \{a_0, \ldots, a_m\}$ of $[a,b]$ with
\begin{align*}
U(P, f) - L(P, f) < \frac{\sigma \varepsilon}{4M}.
\end{align*}
[/step]
[step:Classify subintervals by the oscillation of $f$ and bound the total length of bad subintervals]
Define the oscillation of $f$ on $[a_j, a_{j+1}]$ by $\omega_j(f) = \sup_{[a_j, a_{j+1}]} f - \inf_{[a_j, a_{j+1}]} f$. Partition the index set $\{0, \ldots, m-1\}$ into
\begin{align*}
G &= \{j : \omega_j(f) < \sigma\}, \\
B &= \{j : \omega_j(f) \geq \sigma\}.
\end{align*}
For indices in $B$, the oscillation is at least $\sigma$, so
\begin{align*}
\sigma \sum_{j \in B} (a_{j+1} - a_j) \leq \sum_{j \in B} (a_{j+1} - a_j)\,\omega_j(f) \leq U(P, f) - L(P, f) < \frac{\sigma \varepsilon}{4M}.
\end{align*}
Dividing by $\sigma > 0$:
\begin{align*}
\sum_{j \in B} (a_{j+1} - a_j) < \frac{\varepsilon}{4M}.
\end{align*}
[guided]
Why classify subintervals? On a "good" subinterval ($\omega_j(f) < \sigma$), the function $f$ maps the entire subinterval into an interval of length less than $\sigma$, so uniform continuity of $g$ gives $\omega_j(g \circ f) < \eta$. On a "bad" subinterval ($\omega_j(f) \geq \sigma$), we can only use the crude bound $\omega_j(g \circ f) \leq 2M$.
The Riemann criterion for $f$ controls the total contribution of bad subintervals. Since $\omega_j(f) \geq \sigma$ for $j \in B$:
\begin{align*}
\sigma \sum_{j \in B} (a_{j+1} - a_j)
\leq \sum_{j \in B} (a_{j+1} - a_j)\,\omega_j(f)
\leq U(P,f) - L(P,f) < \frac{\sigma \varepsilon}{4M}.
\end{align*}
Dividing by $\sigma$ gives $\sum_{j \in B} (a_{j+1} - a_j) < \varepsilon/(4M)$, which bounds the total length of the "bad" subintervals. The choice $\sigma\varepsilon/(4M)$ in the Riemann criterion was engineered precisely so that multiplying by $2M$ (the crude oscillation bound) gives $\varepsilon/2$.
[/guided]
[/step]
[step:Combine the good and bad contributions to verify the Riemann criterion for $g \circ f$]
For $j \in G$: since $\omega_j(f) < \sigma$, the function $f$ maps $[a_j, a_{j+1}]$ into an interval of length less than $\sigma$ within $[A,B]$. Uniform continuity of $g$ with modulus $\sigma$ then gives $\omega_j(g \circ f) < \eta = \varepsilon/(2(b-a))$.
For $j \in B$: the values of $g \circ f$ lie in $[-M, M]$, so $\omega_j(g \circ f) \leq 2M$.
Combining:
\begin{align*}
U(P, g \circ f) - L(P, g \circ f) &= \sum_{j \in G} (a_{j+1} - a_j)\,\omega_j(g \circ f) + \sum_{j \in B} (a_{j+1} - a_j)\,\omega_j(g \circ f) \\
&< \frac{\varepsilon}{2(b-a)} \sum_{j \in G} (a_{j+1} - a_j) + 2M \sum_{j \in B} (a_{j+1} - a_j) \\
&\leq \frac{\varepsilon}{2(b-a)} \cdot (b-a) + 2M \cdot \frac{\varepsilon}{4M} = \frac{\varepsilon}{2} + \frac{\varepsilon}{2} = \varepsilon.
\end{align*}
Since $\varepsilon > 0$ was arbitrary, the [Riemann criterion](/theorems/281) is satisfied and $g \circ f$ is Riemann integrable.
[/step]