% ============================================================================ % Appendix C — Mathematical derivations % Written by Agent L (Appendices B/C instance), 2026-11-03. Derivations and % proofs referenced by Part IV (sections/part04_methodology.tex); notation % follows Part IV. Each derivation is checked against the implementation in % econometrics/structural_change.py, bibliometrics/03_citation_impact.py, % bibliometrics/04_diversity_cagr.py, knowledge_graph/02_category_flows.py, % taxonomy/classify.py, taxonomy/validate_sample.py and % experiments/emerging_detection.py; where the code and the usual textbook % convention differ, the code's convention is stated and the difference noted. % ============================================================================ \section{Mathematical derivations} \label{sec:appC} Part~IV defines the statistics of this study and states their properties; this appendix supplies the derivations behind those statements, in the order in which Part~IV uses them. Each subsection fixes the object as implemented, derives the property that the main text relies on, and records any point at which the implementation departs from the convention of the cited source. The derivations are elementary and self-contained; their purpose is not novelty but the assurance that the quantities tabulated in Part~IX are what the text says they are. Throughout, $n$ is the length of a monthly series, $y_t = \log(N_t + 1)$ its logarithm, and $\mathbf{1}[\cdot]$ the indicator function. \subsection{The interrupted time series as a linear regression} \label{sec:appC-its} \paragraph{Design matrix.} Equation~\eqref{eq:its} of Part~IV is the linear model $y = X\beta + \varepsilon$ with $y \in \R^n$ and $X \in \R^{n \times 15}$ whose columns are, for $t = 0, \dots, n-1$ and event index $t_e$, \begin{equation} x_t \;=\; \bigl(1,\; t,\; \mathbf{1}[t \ge t_e],\; (t - t_e)\,\mathbf{1}[t \ge t_e],\; \mathbf{1}[\mathrm{month}(t) = 2],\; \dots,\; \mathbf{1}[\mathrm{month}(t) = 12]\bigr)^{\top}, \label{eq:appC-design} \end{equation} exactly the data frame built by \texttt{\_design()} in \texttt{econometrics/structural\_change.py} (columns \texttt{const}, \texttt{t}, \texttt{post}, \texttt{t\_post}, \texttt{m2}, \dots, \texttt{m12}). The post-event trend is centred at $t_e$ rather than at zero so that $\beta_2$ is the level change \emph{at} the event month and not the extrapolated intercept difference at $t = 0$; with an uncentred post-trend the two parametrisations are related by $\beta_2^{\mathrm{unc}} = \beta_2 - \beta_3 t_e$, and only the centred one has the interpretation used in the text. The eleven month dummies are linearly independent of the constant because January is omitted; the full-column-rank condition requires at least one observation in every month of the year, satisfied by any series of twelve months or more, and at least two post-event months with $t > t_e$ (with a single one the centred post-trend column is identically zero and $\beta_2$ and $\beta_3$ are not separately identified), guaranteed by the driver's rule that twelve months follow every event. The ordinary least-squares estimator is $\hat\beta = (X^{\top}X)^{-1} X^{\top}y$ and the residuals $\hat\varepsilon = y - X\hat\beta$. \paragraph{The HAC covariance estimator.} Under the assumption that $\varepsilon_t$ is a stationary, serially correlated and possibly heteroskedastic sequence with $\E[x_t \varepsilon_t] = 0$, the asymptotic covariance of $\sqrt{n}(\hat\beta - \beta)$ is $Q^{-1}\Omega Q^{-1}$ with $Q = \lim n^{-1}X^{\top}X$ and $\Omega = \sum_{\ell=-\infty}^{\infty} \Gamma_\ell$, where $\Gamma_\ell = \E[x_t \varepsilon_t \varepsilon_{t-\ell} x_{t-\ell}^{\top}]$ is the autocovariance of the score at lag $\ell$. The estimator of \citet{newey1987hac} replaces the infinite sum by a kernel-weighted finite one, \begin{equation} \hat\Omega_L \;=\; \hat\Gamma_0 + \sum_{\ell=1}^{L} w_\ell\,\bigl(\hat\Gamma_\ell + \hat\Gamma_\ell^{\top}\bigr), \qquad \hat\Gamma_\ell = \frac{1}{n}\sum_{t=\ell}^{n-1} \hat\varepsilon_t \hat\varepsilon_{t-\ell}\, x_t x_{t-\ell}^{\top}, \qquad w_\ell = 1 - \frac{\ell}{L+1}, \label{eq:appC-nw} \end{equation} and the variance estimate is $\hat V = n\,(X^{\top}X)^{-1} \hat\Omega_L (X^{\top}X)^{-1}$, which is the expression of Part~IV once the factors of $n$ are absorbed into the un-normalised $\hat\Gamma_\ell$. The Bartlett weights $w_\ell$ are what make $\hat\Omega_L$ positive semi-definite for every sample: $\hat\Omega_L$ can be written as $\frac{1}{n(L+1)}\sum_{t} \bigl(\sum_{s=t-L}^{t} \hat u_s\bigr)\bigl(\sum_{s=t-L}^{t} \hat u_s\bigr)^{\top}$ up to end effects, with $\hat u_s = x_s \hat\varepsilon_s$, a sum of outer products, whereas the truncated sum with $w_\ell \equiv 1$ is not guaranteed to be positive semi-definite. The implementation calls \texttt{statsmodels} with \texttt{cov\_type="HAC"} and \texttt{maxlags=6}, so $L = 6$ and $w_\ell = 1 - \ell/7$ as stated in Part~IV, without the small-sample degrees-of-freedom correction and with $p$-values from the normal approximation to the $t$-ratio, which is the library's default for robust covariances. With $n$ of the order of one hundred and fifteen columns in $X$, the constant included, the difference between the normal and the $t_{n-15}$ reference distribution is immaterial at the magnitudes of the $t$-statistics reported; what matters is the placebo rank of the next paragraph, which does not depend on any reference distribution. \paragraph{The placebo $p$-value as a rank statistic.} Let $\mathcal{T}' = \{t' : 24 \le t' \le n - 13\}$ be the candidate event indices (the implementation's \texttt{min\_pre = 24} and \texttt{min\_post = 12}) and, for each $t' \in \mathcal{T}'$, let $t^{(2)}_{t'} = \hat\beta_2(t') / \widehat{\mathrm{se}}(\hat\beta_2(t'))$ be the HAC $t$-ratio of the level change when the model \eqref{eq:appC-design} is fitted with $t_e = t'$. The placebo value of the true event $t_e \in \mathcal{T}'$ is \begin{equation} p^{\mathrm{plac}} \;=\; \frac{1}{|\mathcal{T}'|}\sum_{t' \in \mathcal{T}'} \mathbf{1}\bigl[\,|t^{(2)}_{t'}| \ge |t^{(2)}_{t_e}|\,\bigr] \;=\; \frac{\mathrm{rank}\bigl(|t^{(2)}_{t_e}|\bigr)}{|\mathcal{T}'|}, \end{equation} where $\mathrm{rank}$ is the descending rank of the true event's absolute $t$-ratio among the $|\mathcal{T}'|$ values, ties counted as not better (\texttt{>=}). Three properties follow directly. Because $t_e \in \mathcal{T}'$, the sum contains the term $t' = t_e$, so $p^{\mathrm{plac}} \ge 1/|\mathcal{T}'|$, which for the default window ($n = 101$, hence $|\mathcal{T}'| = 65$) is about $0.015$: a placebo rank cannot be smaller, however large the true statistic, and a reported value of $1/|\mathcal{T}'|$ means ``largest of all candidate dates'', not ``significant at that level''. Because the statistic is a rank, it is invariant to any monotone transformation of the $|t|$-ratios and in particular does not depend on the HAC bandwidth through anything but the ordering it induces. And if the candidate dates were exchangeable under a null hypothesis of no break anywhere, $p^{\mathrm{plac}}$ would be a valid permutation-type $p$-value with $P(p^{\mathrm{plac}} \le \alpha) \le \alpha$; they are not exchangeable, since all $|\mathcal{T}'|$ regressions share the same $n$ observations and adjacent candidates give nearly identical fits, so the value is reported as a rank and read as such. The same construction gives the placebo rank of the slope change from $t^{(3)}_{t'}$. The driver additionally computes the rank restricted to the baseline candidates $\{t' < t_e\}$, which answers the protocol's original question (is the reference date special relative to the pre-period?) and is reported next to the full-range rank. \subsection{Bai--Perron multiple breaks by dynamic programming} \label{sec:appC-bp} \paragraph{Segment costs and additivity.} For a segment $[i, j)$ of the series with $j - i \ge h$, define \begin{equation} S(i, j) \;=\; \min_{a, b \in \R}\ \sum_{t=i}^{j-1} (y_t - a - b\,t)^2, \label{eq:appC-segcost} \end{equation} the residual sum of squares of a linear trend fitted to the segment alone (the implementation solves the two-parameter least-squares problem for each segment with \texttt{numpy.linalg.lstsq}; with \texttt{trend=False} the regressor $t$ is dropped and $S(i,j)$ is the centred sum of squares). The model with $m$ breaks $0 < \tau_1 < \dots < \tau_m < n$ assigns its own $(a, b)$ to each of the $m+1$ segments $[\tau_{k-1}, \tau_k)$ with $\tau_0 = 0$ and $\tau_{m+1} = n$. Because the parameters of different segments are distinct and each observation enters exactly one segment, the residual sum of squares of the whole model separates, \begin{equation} \mathrm{SSR}(\tau_1, \dots, \tau_m) \;=\; \sum_{k=1}^{m+1} S(\tau_{k-1}, \tau_k), \label{eq:appC-additive} \end{equation} and the global minimisation over $\tau$ decomposes: the optimal partition of the first $j$ observations into $m+1$ segments contains, as its first $m$ segments, an optimal partition of the first $\tau_m$ observations into $m$ segments. This is the principle of optimality, and it is the only property of the cost that the dynamic programme uses; it holds for any cost that is a sum over segments of a function of the segment alone, which is why the same recursion serves the piecewise-constant model of Section~\ref{sec:appC-pelt}. It fails for a model with parameters shared across segments (a common slope, or the seasonal dummies of the ITS), which is why the segmented regression carries no seasonal terms and the series is seasonally adjusted beforehand by subtracting the baseline-period month means (\texttt{run\_structural\_change.py}). \paragraph{The recursion.} Let $C_m(j)$ be the minimum of \eqref{eq:appC-additive} over partitions of observations $0, \dots, j-1$ into $m+1$ admissible segments. Then \begin{equation} C_0(j) = S(0, j), \qquad C_m(j) = \min_{\,mh \le i \le j-h} \bigl\{ C_{m-1}(i) + S(i, j) \bigr\}, \qquad j \ge (m+1)h, \label{eq:appC-dp} \end{equation} the lower limit of $i$ ensuring that $m$ segments of length at least $h$ fit before the last break and the upper limit that the last segment has length at least $h$. The argument minimiser $i^{\ast}_m(j)$ is stored, and the breaks of the $m$-break solution for the full series are recovered backward: $\tau_m = i^{\ast}_m(n)$, $\tau_{m-1} = i^{\ast}_{m-1}(\tau_m)$, and so on, which is what the dictionary \texttt{B[m][j]} of the implementation accumulates forward instead. This is the dynamic programme that \citet{bai2003computation} propose for the global minimiser of \citet{bai1998breaks}; the earlier literature used it for the piecewise-constant case, and its correctness requires nothing beyond \eqref{eq:appC-additive} and the induction on $m$: if $C_{m-1}(i)$ is the true minimum for every $i$, then any partition of $[0, j)$ into $m+1$ segments has a last segment $[i, j)$ and a prefix partition of cost at least $C_{m-1}(i)$, so its cost is at least the right-hand side of \eqref{eq:appC-dp}, which is attained. \paragraph{Complexity.} The table of segment costs has one entry per admissible pair $(i, j)$, that is $\binom{n-h+1}{2} + O(n)$ entries, of order $n^2/2$. The recursion \eqref{eq:appC-dp} evaluates, for each $m \le M$ and each $j$, a minimum over at most $n$ candidates, so its cost is $O(n^2 M)$ operations; the back-tracking costs $O(M)$. The implementation fills the cost table by solving each segment's least-squares problem independently, at a cost proportional to the segment length, so the table costs $O(n^3)$ rather than the $O(n^2)$ obtainable by updating running sums as in \citet{bai2003computation}; for $n$ of the order of one hundred, as here, the difference is a fraction of a second and the simpler code was preferred for its transparency. Trimming enters only through the admissibility condition $j - i \ge h$; with $h = \max\{8, \lfloor 0.15\,n \rfloor\}$ and $M = 3$, the default window of $n = 101$ months gives $h = 15$ and a feasible region $(m+1)h \le n$ for every $m \le 3$, so all four candidate models exist. \paragraph{Information criteria as implemented.} For $m = 0, \dots, M$ let $\mathrm{SSR}_m = C_m(n)$ and let $p_m = k(m+1) + m$ be the parameter count, with $k = 2$ for the trend model ($k = 1$ for the mean model): one intercept and one slope per segment, plus the $m$ break positions, counted as parameters by convention. The two criteria computed by the code are \begin{align} \mathrm{BIC}(m) &= n \log\frac{\mathrm{SSR}_m}{n} + p_m \log n, \label{eq:appC-bic}\\ \mathrm{LWZ}(m) &= n \log\frac{\mathrm{SSR}_m}{n - p_m} + p_m\, c_0\, (\log n)^{2.1}, \qquad c_0 = 0.299, \label{eq:appC-lwz} \end{align} and the selected number of breaks is $\hat m = \arg\min_m$ of each. The BIC form \eqref{eq:appC-bic} is the Gaussian log-likelihood, maximised over the error variance, in which $-2\log\hat L = n\log(\mathrm{SSR}/n) + \text{const}$, plus the Schwarz penalty $p \log n$ \citep{schwarz1978bic}; the two differences from a textbook BIC are that the break positions are counted among the parameters and that the constant and the segment variances are treated as common, both as in \citet{bai2003computation}. The LWZ form \eqref{eq:appC-lwz} is the modified Schwarz criterion of \citet{liu1997segmented}, whose penalty grows as $(\log n)^{2+\delta_0}$ with $\delta_0 = 0.1$ and whose variance estimate divides by $n - p_m$; the constant $c_0 = 0.299$ is the value they recommend and the one used in the simulations of \citet{bai2003computation}, which find that LWZ selects fewer spurious breaks than BIC under serial correlation at the cost of some power. The comparison across $m$ is legitimate because every $\mathrm{SSR}_m$ is a global minimum over the same observations and the same admissible region; a sequential procedure that fixed earlier breaks before adding the next would not have this property and would need the sup-$F$ machinery that is not implemented. Neither criterion yields a confidence set for the break dates; the text reports the agreement of the two selections and the sensitivity to the truncation month instead. \subsection{PELT: cost, penalty and pruning} \label{sec:appC-pelt} \paragraph{Objective.} With the $\ell_2$ cost $\mathcal{C}(y_{i:j}) = \sum_{t=i}^{j-1} (y_t - \bar y_{i:j})^2$ for a segment $[i,j)$ and a penalty $\lambda > 0$ per changepoint, the problem of equation~\eqref{eq:pelt} of Part~IV is \begin{equation} F(n) \;=\; \min_{m,\ \tau_1 < \dots < \tau_m}\ \Bigl\{ \sum_{k=1}^{m+1} \mathcal{C}(y_{\tau_{k-1}:\tau_k}) + \lambda m \Bigr\}, \label{eq:appC-peltobj} \end{equation} and, by the same additivity argument as in Section~\ref{sec:appC-bp}, it satisfies the optimal-partitioning recursion of \citet{jackson2005optimal}, \begin{equation} F(0) = -\lambda, \qquad F(j) \;=\; \min_{0 \le i < j}\ \bigl\{ F(i) + \mathcal{C}(y_{i:j}) + \lambda \bigr\}, \label{eq:appC-op} \end{equation} where the number of breaks is not fixed in advance but chosen by the penalty; the convention $F(0) = -\lambda$ cancels the penalty charged to the first segment. Solving \eqref{eq:appC-op} for all $j$ costs $O(n^2)$ cost evaluations. \paragraph{The pruning condition.} \citet{killick2012pelt} observe that if there exists a constant $K$ such that for all $i < j < l$ \begin{equation} \mathcal{C}(y_{i:j}) + \mathcal{C}(y_{j:l}) + K \;\le\; \mathcal{C}(y_{i:l}), \label{eq:appC-Kcond} \end{equation} then any candidate $i$ for which \begin{equation} F(i) + \mathcal{C}(y_{i:j}) + K \;\ge\; F(j) \label{eq:appC-prune} \end{equation} can never be the last changepoint before any later $l > j$ and may be discarded from the candidate set. The proof is two lines. For $l > j$, by \eqref{eq:appC-Kcond} and \eqref{eq:appC-prune}, $F(i) + \mathcal{C}(y_{i:l}) + \lambda \ge F(i) + \mathcal{C}(y_{i:j}) + \mathcal{C}(y_{j:l}) + K + \lambda \ge F(j) + \mathcal{C}(y_{j:l}) + \lambda$, so the partition that places a changepoint at $j$ after the optimal prefix of $[0,j)$ is at least as good as any that ends its last segment at $i$; hence $i$ never needs to be examined again. For the $\ell_2$ cost, \eqref{eq:appC-Kcond} holds with $K = 0$, because adding a split point to a segment can only reduce its residual sum of squares (the split model nests the unsplit one). The recursion with pruning examines, at each $j$, only the candidates not yet discarded; under the regularity conditions of \citeauthor{killick2012pelt} (changepoints whose number grows linearly with $n$) the expected number of surviving candidates is bounded and the total cost is linear in $n$, whence the name. For a short series with few changes, as here, the pruning saves little and the method is simply an exact solution of \eqref{eq:appC-peltobj}; the point of using it is exactness at a given penalty, not speed. The implementation (\texttt{ruptures.Pelt}, \citealp{truong2020ruptures}) is called with \texttt{model="l2"}, \texttt{min\_size=6} and \texttt{jump=1}, the last two restricting segments to at least six months and allowing a changepoint at every index; the library returns the segment end points including $n$, which the wrapper drops. \paragraph{The penalty $2\sigma^2 \log n$.} Suppose the observations are independent Gaussian with piecewise-constant mean and a common variance $\sigma^2$. Twice the negative log-likelihood of a partition, up to a constant, is $\sigma^{-2}\sum_k \mathcal{C}(y_{\tau_{k-1}:\tau_k})$. Each additional changepoint adds two parameters, a segment mean and a position, so the Schwarz criterion in this scale adds $2\log n$ per changepoint. Multiplying through by $\sigma^2$ to express the criterion in the units of the cost gives \begin{equation} \sum_k \mathcal{C}(y_{\tau_{k-1}:\tau_k}) + 2\sigma^2 \log n \cdot m, \end{equation} which is \eqref{eq:appC-peltobj} with $\lambda = 2\sigma^2\log n$. The implementation replaces $\sigma^2$ by the sample variance of the whole series, $\widehat{\mathrm{Var}}(y) = n^{-1}\sum_t (y_t - \bar y)^2$ (\texttt{numpy.var}, population form). This is the conservative choice discussed in Part~IV: in a series with a trend or with genuine level shifts, the overall variance exceeds the within-segment variance, so the penalty is larger than the within-segment Schwarz penalty and fewer changepoints are declared. \citet{yao1988schwarz} proves that the Schwarz criterion, with a known or consistently estimated $\sigma^2$, selects the true number of changes with probability tending to one in the piecewise-constant Gaussian model; the result does not extend to a series whose mean is a trend, for which a piecewise-constant fit must spend changepoints to track the slope, and the PELT dates of this study are read with that in mind. \subsection{Bayesian online changepoint detection} \label{sec:appC-bocpd} \paragraph{Conjugate updates.} Within a run the observations are modelled as $y \mid \mu, \sigma^2 \sim \mathcal{N}(\mu, \sigma^2)$ with the Normal--Inverse-Gamma prior $\mu \mid \sigma^2 \sim \mathcal{N}(\mu_0, \sigma^2/\kappa_0)$, $\sigma^2 \sim \mathrm{IG}(\alpha_0, \beta_0)$, whose joint density is proportional to \begin{equation} (\sigma^2)^{-\alpha_0 - 3/2} \exp\Bigl\{ -\frac{\beta_0}{\sigma^2} - \frac{\kappa_0 (\mu - \mu_0)^2}{2\sigma^2} \Bigr\}. \end{equation} Multiplying by the likelihood of one observation $y$, proportional to $(\sigma^2)^{-1/2}\exp\{-(y-\mu)^2/(2\sigma^2)\}$, and completing the square in $\mu$, \begin{equation} \kappa_0 (\mu - \mu_0)^2 + (y - \mu)^2 \;=\; (\kappa_0 + 1)\Bigl(\mu - \frac{\kappa_0\mu_0 + y}{\kappa_0 + 1}\Bigr)^2 + \frac{\kappa_0 (y - \mu_0)^2}{\kappa_0 + 1}, \end{equation} shows that the posterior is again Normal--Inverse-Gamma with \begin{equation} \mu_1 = \frac{\kappa_0 \mu_0 + y}{\kappa_0 + 1}, \quad \kappa_1 = \kappa_0 + 1, \quad \alpha_1 = \alpha_0 + \tfrac12, \quad \beta_1 = \beta_0 + \frac{\kappa_0 (y - \mu_0)^2}{2(\kappa_0 + 1)}, \label{eq:appC-nigupdate} \end{equation} which are the four one-step updates of the implementation (\texttt{mu\_new}, \texttt{kappa\_new}, \texttt{alpha\_new}, \texttt{beta\_new}). Applying \eqref{eq:appC-nigupdate} $r$ times and collecting terms gives the batch form quoted in Part~IV, with $\kappa_r = \kappa_0 + r$, $\mu_r = (\kappa_0\mu_0 + r\bar y)/\kappa_r$, $\alpha_r = \alpha_0 + r/2$ and $\beta_r = \beta_0 + \tfrac12\sum_{i \le r}(y_i - \bar y)^2 + \kappa_0 r (\bar y - \mu_0)^2 / (2\kappa_r)$; the equality of the two forms is a matter of algebra (induction on $r$) and is the reason the online recursion can be trusted to reproduce the batch posterior. \paragraph{Student-$t$ predictive.} The predictive density of the next observation integrates the Gaussian likelihood against the current Normal--Inverse-Gamma posterior. Integrating $\mu$ first gives $y \mid \sigma^2 \sim \mathcal{N}(\mu_r, \sigma^2 (1 + 1/\kappa_r))$; integrating $\sigma^2 \sim \mathrm{IG}(\alpha_r, \beta_r)$ against this scale mixture of normals gives \begin{equation} p(y \mid r) \;=\; \int \mathcal{N}\Bigl(y;\ \mu_r,\ \sigma^2\frac{\kappa_r + 1}{\kappa_r}\Bigr)\,\mathrm{IG}(\sigma^2; \alpha_r, \beta_r)\, d\sigma^2 \;=\; t_{2\alpha_r}\Bigl( y;\ \mu_r,\ \frac{\beta_r(\kappa_r + 1)}{\alpha_r \kappa_r} \Bigr), \label{eq:appC-student} \end{equation} a Student-$t$ density with $2\alpha_r$ degrees of freedom, location $\mu_r$ and squared scale $\beta_r(\kappa_r+1)/(\alpha_r\kappa_r)$: the standard result that a normal with inverse-gamma mixing on the variance is a $t$ with degrees of freedom twice the shape and scale equal to the rate over the shape times the normal's variance factor. The code evaluates \eqref{eq:appC-student} through \texttt{scipy.stats.t.pdf} with \texttt{df = 2*alpha} and \texttt{scale = sqrt(beta*(kappa+1)/(alpha*kappa))}, vectorised over the run lengths. \paragraph{Run-length recursion and the mass on $r = 0$.} Let $R_t(r) = P(r_t = r \mid y_{1:t})$ be the filtered run-length posterior after $t$ observations, with $R_0(0) = 1$, and let $\pi_t(r) = p(y_{t+1} \mid r_t = r, y_{1:t})$ be the predictive \eqref{eq:appC-student} evaluated with the hyperparameters of the run of length $r$ ending at $t$. With a constant hazard $H$ (a geometric prior on run lengths), the joint recursion of \citet{adams2007bocpd} is, for the growth and the change moves, \begin{equation} \tilde R_{t+1}(r+1) = R_t(r)\,\pi_t(r)\,(1 - H), \qquad \tilde R_{t+1}(0) = \sum_{r=0}^{t} R_t(r)\,\pi_t(r)\, H, \label{eq:appC-rl} \end{equation} followed by normalisation, $R_{t+1}(r) = \tilde R_{t+1}(r) / \sum_{r'} \tilde R_{t+1}(r')$. Write $Z_t = \sum_{r} R_t(r)\pi_t(r)$ for the marginal predictive likelihood of $y_{t+1}$. Then $\sum_{r \ge 1}\tilde R_{t+1}(r) = (1-H) Z_t$ and $\tilde R_{t+1}(0) = H Z_t$, so the normaliser is $Z_t$ and \begin{equation} R_{t+1}(0) \;=\; \frac{H Z_t}{H Z_t + (1-H) Z_t} \;=\; H \qquad \text{for every } t. \label{eq:appC-r0} \end{equation} The filtered probability that a changepoint occurs \emph{at} the current step therefore equals the prior hazard identically, whatever the data: the run-length posterior carries information about where the last change was only through the relative masses at $r \ge 1$, which are reweighted by the predictive likelihoods, and not through the mass at $r = 0$, which the constant hazard fixes. This is why the detection statistics of Part~IV are not $R_t(0)$. The first, $P(r_t \le 3 \mid y_{1:t}) = \sum_{r=0}^{3} R_t(r)$, is $H$ plus the mass on runs of length one to three, that is, on changes that occurred one to three months earlier and have since accumulated evidence; its value exceeds $H$ only when the recent observations are better explained by a fresh run than by the continuation of the old one. The second is the maximum-a-posteriori run length $\hat r_t = \arg\max_r R_t(r)$, whose resets from a value above twelve to a value at most two are the online detector's changepoints. The implementation keeps the full $(n+1)\times(n+1)$ matrix $R$, adds $10^{-300}$ to the normaliser against underflow, and initialises $\mu_0$ and $\beta_0$ from the first six observations with $\kappa_0 = \alpha_0 = 1$; the prior mean run length $1/H = 60$ months is the only tuning constant. The recursion is the filtered one; the smoothed posterior of \citet{fearnhead2006exact} would require a backward pass and answers the retrospective question that the offline methods of Sections~\ref{sec:appC-bp} and~\ref{sec:appC-pelt} already address. \subsection{The Gini coefficient: rank form and Lorenz form} \label{sec:appC-gini} Let $c_{(1)} \le c_{(2)} \le \dots \le c_{(n)}$ be the citation counts of the $n$ works of a publication year sorted in ascending order, $S = \sum_i c_{(i)} > 0$ their total, and $L_i = \sum_{j \le i} c_{(j)} / S$ the cumulative share held by the $i$ least-cited works, with $L_0 = 0$ and $L_n = 1$. The Lorenz curve \citep{lorenz1905concentration} is the polygon through the points $(i/n, L_i)$, and the Gini coefficient is defined as one minus twice the area $A$ under it \citep{ceriani2012gini}. By the trapezoidal rule, which is exact for a polygon, \begin{equation} A \;=\; \sum_{i=1}^{n} \frac{1}{n}\cdot\frac{L_{i-1} + L_i}{2} \;=\; \frac{1}{2n}\Bigl( 2\sum_{i=1}^{n} L_i - L_n \Bigr) \;=\; \frac{1}{n}\sum_{i=1}^{n} L_i - \frac{1}{2n}. \end{equation} Exchanging the order of summation in $\sum_i L_i$, \begin{equation} \sum_{i=1}^{n} L_i \;=\; \frac{1}{S}\sum_{i=1}^{n}\sum_{j=1}^{i} c_{(j)} \;=\; \frac{1}{S}\sum_{j=1}^{n} (n - j + 1)\, c_{(j)} \;=\; (n+1) - \frac{1}{S}\sum_{j=1}^{n} j\, c_{(j)}, \end{equation} so that \begin{equation} G \;=\; 1 - 2A \;=\; 1 - \frac{2(n+1)}{n} + \frac{2}{nS}\sum_{j=1}^{n} j\, c_{(j)} + \frac{1}{n} \;=\; \frac{2\sum_{j=1}^{n} j\, c_{(j)}}{n \sum_{j} c_{(j)}} - \frac{n+1}{n}, \label{eq:appC-gini} \end{equation} which is equation~\eqref{eq:gini} of Part~IV and the expression that \texttt{bibliometrics/03\_citation\_impact.py} evaluates in SQL, the rank $j$ being the window function \texttt{row\_number()} partitioned by year and ordered by the citation count and then by the work identifier. The secondary ordering by work identifier is needed only to make the rank a permutation when counts tie; since tied values receive consecutive ranks and contribute $c \cdot (j + j')$ to the numerator whichever of the two tied works gets the smaller rank, the value of $G$ does not depend on how ties are broken. The bounds follow from \eqref{eq:appC-gini}: $G = 0$ when all $c_{(j)}$ are equal (then $\sum_j j c_{(j)} = c\,n(n+1)/2$ and the two terms cancel), and $G = 1 - 1/n$ when a single work holds all citations (then $\sum_j j c_{(j)} = nS$), so the maximum attainable value is $1 - 1/n$ rather than one and the coefficient is not normalised by that factor. Uncited works enter with $c_{(j)} = 0$ at the lowest ranks; adding $u$ uncited works to a year leaves $\sum_j j c_{(j)}$ shifted by $uS$ and $n$ increased by $u$, and one checks from \eqref{eq:appC-gini} that $G$ increases, which is the direction stated in Part~IV and the reason the uncited share accompanies the coefficient in the tables. \subsection{Rao--Stirling and Leinster--Cobbold at order two} \label{sec:appC-diversity} Let $p \in \R^K$ be a probability vector over categories, $\delta_{ij} \in [0,1]$ a dissimilarity with $\delta_{ii} = 0$, and $Z = (z_{ij})$ the similarity matrix $z_{ij} = 1 - \delta_{ij}$, so that $z_{ii} = 1$. The Rao--Stirling index \citep{rao1982diversity, stirling2007diversity} is $\Delta_{\mathrm{RS}}(p) = \sum_{i \ne j} p_i p_j \delta_{ij} = p^{\top}\Delta p$ with $\Delta = (\delta_{ij})$, the diagonal contributing nothing. The Leinster--Cobbold diversity of order $q$ \citep{leinster2012diversity} is ${}^{q}D^{Z}(p) = \bigl(\sum_{i : p_i > 0} p_i (Zp)_i^{q-1}\bigr)^{1/(1-q)}$; at $q = 2$ the exponent $1/(1-q) = -1$ and the inner power is one, so \begin{equation} {}^{2}D^{Z}(p) \;=\; \Bigl(\sum_i p_i (Zp)_i\Bigr)^{-1} \;=\; \frac{1}{p^{\top} Z p}. \end{equation} Since $Z = \mathbf{1}\mathbf{1}^{\top} - \Delta$ entrywise (using $z_{ii} = 1 = 1 - \delta_{ii}$ on the diagonal as well), and $p^{\top}\mathbf{1}\mathbf{1}^{\top}p = (\sum_i p_i)^2 = 1$, \begin{equation} p^{\top} Z p \;=\; 1 - p^{\top}\Delta p \;=\; 1 - \Delta_{\mathrm{RS}}(p), \qquad\text{hence}\qquad {}^{2}D^{Z}(p) \;=\; \frac{1}{1 - \Delta_{\mathrm{RS}}(p)}, \label{eq:appC-lc2} \end{equation} the identity quoted in Part~IV\@. It shows that at order two the two families carry the same information: ${}^{2}D^{Z}$ is a strictly increasing function of $\Delta_{\mathrm{RS}}$ on $[0, 1)$, and the ordering of years or categories by either index is the same. They differ in scale and in behaviour near saturation. $\Delta_{\mathrm{RS}}$ is bounded by the mean dissimilarity and compresses differences among very even distributions; ${}^{2}D^{Z}$ is an effective number of categories, equal to $K$ for the uniform distribution over $K$ mutually dissimilar categories ($\Delta_{\mathrm{RS}} = 1 - 1/K$) and to one for a distribution concentrated on a single category ($\Delta_{\mathrm{RS}} = 0$), and it expands the compressed end. The identity requires only $z_{ii} = 1$ and $z_{ij} = 1 - \delta_{ij}$; it does not require $\delta$ to be a metric, and the dissimilarity used, one minus a cosine similarity of category centroids, is not one. The script \texttt{bibliometrics/04\_diversity\_cagr.py} computes both quantities from the yearly category mix exactly as \eqref{eq:appC-lc2} prescribes, $\Delta_{\mathrm{RS}} = p^{\top}(1 - Z)p$ with the diagonal of $Z$ set to one and ${}^{2}D^{Z} = 1/(p^{\top}Zp)$, and attaches a percentile bootstrap interval to $\Delta_{\mathrm{RS}}$ by multinomial resampling of the works over categories ($B = 500$, seed 44), which is the sampling model under which the category counts of a year are a multinomial draw of fixed size; the interval of ${}^{2}D^{Z}$ follows by the monotone transformation. \subsection{Modularity of a directed weighted graph at a fixed partition} \label{sec:appC-modularity} Let $W \in \R_{\ge 0}^{K \times K}$ be the flow matrix of a citing year, $W_{ij}$ the number of citations from category $i$ to category $j$, with $m = \sum_{ij} W_{ij}$, out-strength $k^{\mathrm{out}}_i = \sum_j W_{ij}$ and in-strength $k^{\mathrm{in}}_j = \sum_i W_{ij}$, and let $g : \{1, \dots, K\} \to \mathcal{G}$ be a given assignment of categories to communities. The statistic implemented by \texttt{modularity()} in \texttt{knowledge\_graph/02\_category\_flows.py} is \begin{equation} Q(W, g) \;=\; \frac{1}{m}\sum_{i,j}\Bigl( W_{ij} - \frac{k^{\mathrm{out}}_i k^{\mathrm{in}}_j}{m} \Bigr)\mathbf{1}[g_i = g_j], \label{eq:appC-Q} \end{equation} the directed form of \citet{leicht2008directed}, which reduces to the Newman--Girvan modularity \citep{newman2004community} when $W$ is symmetric (then $k^{\mathrm{out}} = k^{\mathrm{in}} = k$ and $m = 2|E|$ for an unweighted graph). Three facts are used in Part~IV\@. First, the null term is the expected weight of the edge $i \to j$ under random rewiring that preserves every node's out- and in-strength in expectation: a configuration model in which each of the $m$ units of weight leaves node $i$ with probability $k^{\mathrm{out}}_i/m$ and enters node $j$ with probability $k^{\mathrm{in}}_j/m$ independently gives expected weight $m \cdot (k^{\mathrm{out}}_i/m)(k^{\mathrm{in}}_j/m) = k^{\mathrm{out}}_i k^{\mathrm{in}}_j/m$, and summing over $j$ recovers $k^{\mathrm{out}}_i$, so the null model has the observed strengths. Second, $Q$ vanishes when all nodes are in one community: then the indicator is identically one and $\sum_{ij} W_{ij} = m = \sum_{ij} k^{\mathrm{out}}_i k^{\mathrm{in}}_j/m$. Third, writing $e_{gg} = \sum_{i,j : g_i = g_j = g} W_{ij}/m$ for the fraction of weight inside community $g$, $a^{\mathrm{out}}_g = \sum_{i : g_i = g} k^{\mathrm{out}}_i/m$ and $a^{\mathrm{in}}_g$ likewise, \begin{equation} Q \;=\; \sum_{g \in \mathcal{G}} \bigl( e_{gg} - a^{\mathrm{out}}_g\, a^{\mathrm{in}}_g \bigr), \label{eq:appC-Qcomm} \end{equation} so that $Q \le \sum_g e_{gg} \le 1$ and $Q \ge -\sum_g a^{\mathrm{out}}_g a^{\mathrm{in}}_g \ge -1$; the value is positive when more weight stays inside communities than the strength-preserving null predicts. The self-share reported alongside, $\operatorname{tr}(W)/m = \sum_i e_{ii}$ at the category partition, is the first term of \eqref{eq:appC-Qcomm} alone and differs from $Q_{\mathrm{cat}}$ by the correction $\sum_i a^{\mathrm{out}}_i a^{\mathrm{in}}_i$, which grows with the concentration of flows on a few large categories. For the area partition, \eqref{eq:appC-Qcomm} is summed over the eight areas with $e_{\alpha\alpha}$ the within-area share, which is one minus the cross-area share $X_{\alpha,t}$ of Part~IV weighted by the area's out-strength; $Q_{\mathrm{area}}$ is therefore a strength-weighted, null-corrected average of the within-area shares, and a fall in $Q_{\mathrm{area}}$ can arise from a rise in boundary crossing or from a shift of out-strength toward areas whose $a^{\mathrm{out}}_\alpha a^{\mathrm{in}}_\alpha$ is large. Because the partition is fixed rather than optimised, none of the resolution-limit results for maximised modularity \citep{fortunato2007resolution} applies; $Q$ is here a descriptive index and its comparison across years is meaningful only because the partition and the category definitions are the same in every year. \subsection{Krippendorff's \texorpdfstring{$\alpha$}{alpha} with the MASI distance} \label{sec:appC-alpha} \paragraph{General form.} Krippendorff's $\alpha$ \citep{hayes2007krippendorff, artstein2008agreement} is defined for any difference function $d(v, v') \ge 0$ on the values that coders may assign, with $d(v, v) = 0$, as \begin{equation} \alpha \;=\; 1 - \frac{D_o}{D_e}, \label{eq:appC-alpha} \end{equation} where $D_o$ is the mean difference between the values assigned to the same unit by different coders and $D_e$ the mean difference between all pairs of values in the pooled data, irrespective of unit. With two coders $A$ and $B$ rating each of $n$ units, the pooled set contains $N = 2n$ values and \begin{equation} D_o \;=\; \frac{1}{n}\sum_{u=1}^{n} d\bigl(a_u, b_u\bigr), \qquad D_e \;=\; \frac{1}{N(N-1)}\sum_{c \ne c'} d\bigl(v_c, v_{c'}\bigr) \;=\; \frac{1}{\binom{N}{2}}\sum_{c < c'} d\bigl(v_c, v_{c'}\bigr), \label{eq:appC-DoDe} \end{equation} the second equality using the symmetry of $d$. The coefficient is one when the coders agree on every unit ($D_o = 0$), zero when the within-unit differences are what chance pairing of the pooled values would produce ($D_o = D_e$), and negative when disagreement is systematic. Unlike Cohen's $\kappa$, which compares observed agreement with the product of the two coders' marginals, $\alpha$ pools the two coders' values into one distribution for its chance term, so it does not reward coders for having different marginal distributions; this and its accommodation of arbitrary difference functions are the reasons it is the recommended coefficient for set-valued annotation \citep{artstein2008agreement}. \paragraph{The MASI distance.} For set-valued labels $x, y \subseteq \mathcal{K}$, \citet{passonneau2006masi} defines the Measuring Agreement on Set-valued Items distance as \begin{gather} d_{\mathrm{MASI}}(x, y) \;=\; 1 - J(x, y)\, M(x, y), \qquad J(x, y) = \frac{|x \cap y|}{|x \cup y|}, \nonumber\\ M(x, y) = \begin{cases} 1 & x = y,\\ 2/3 & x \subsetneq y \text{ or } y \subsetneq x,\\ 1/3 & x \cap y \ne \emptyset \text{ and neither contains the other},\\ 0 & x \cap y = \emptyset , \end{cases} \label{eq:appC-masi} \end{gather} the Jaccard similarity attenuated by a monotonicity factor that distinguishes nesting from mere overlap. The distance is zero only for identical non-empty sets, equals one for disjoint sets, and treats the pair (empty, empty) as identical ($d = 0$) by the convention of the implementation, which returns zero before computing $J$ for two empty sets; the pair (empty, non-empty) has $J = 0$ and $d = 1$. \paragraph{What the code computes.} \texttt{taxonomy/validate\_sample.py} forms, for the two raters, the observed term as the mean of $d_{\mathrm{MASI}}^2$ over the $n$ rated works and the expected term as the mean of $d_{\mathrm{MASI}}^2$ over all unordered pairs of the $2n$ pooled label sets (exhaustively when $2n \le 1200$, otherwise over 200{,}000 random ordered pairs with $i \ne j$, seed 44), and reports $1 - D_o/D_e$. Two remarks make this precise. The code uses the constants $0.67$ and $0.33$ for the monotonicity factor rather than $2/3$ and $1/3$, a rounding of the published definition that changes distances by at most $0.0034$. More consequentially, it \emph{squares} the MASI distance before averaging, that is, it applies \eqref{eq:appC-alpha}--\eqref{eq:appC-DoDe} with $d = d_{\mathrm{MASI}}^2$. Krippendorff's interval metric is the squared difference, and the code's comment describes the computation as the ``interval form on the MASI distance''; \citeauthor{passonneau2006masi}, in contrast, plugs $d_{\mathrm{MASI}}$ itself into the $\alpha$ formula, and the agreement packages that implement MASI follow her. The two conventions yield different numbers from the same ratings---squaring compresses small disagreements and so, as a rule, raises $\alpha$ when most disagreements are partial---and the value reported in Part~IX is the squared-distance version, labelled as such. Both are legitimate instances of \eqref{eq:appC-alpha}; what is not legitimate is to compare the reported value with published MASI-$\alpha$ figures without this caveat. The mean Jaccard index reported next to it is $n^{-1}\sum_u J(a_u, b_u)$ with $0/0 = 0$ and is a raw agreement rate with no chance correction. Both statistics are computed on the full rated sample and not on the 200-work subsample reserved for the principal investigator, whose verdicts will add a third coder to \eqref{eq:appC-DoDe} once checkpoint H-2 is signed. \subsection{The multi-label score rule and the tie-break as a total order} \label{sec:appC-score} \paragraph{Score.} For a work $w$ and a category $k$ the implementation (\texttt{taxonomy/classify.py}, \texttt{score\_row}) computes five components, one per signal type $\sigma \in \{\mathrm{T}, \mathrm{F}, \mathrm{X}, \mathrm{D}, \mathrm{kw}\}$, \begin{align} s^{\sigma}_k(w) &\;=\; \min\Bigl\{ 1,\ \sum_{x \in \sigma(w)} \omega^{\sigma}_k(x) \Bigr\} \qquad (\sigma \ne \mathrm{kw}), \\ s^{\mathrm{kw}}_k(w) &\;=\; \min\Bigl\{ 1,\ \sum_{(r, \omega, \phi) \in R_k} \omega\, \mathbf{1}[r \text{ matches } \phi(w)] \Bigr\}, \end{align} where $\sigma(w)$ is the \emph{set} of the work's topic, subfield, arXiv category or DBLP stream identifiers (Python \texttt{set()}, so a repeated identifier contributes once), and the keyword loop stops at the first rule that brings the running sum to one, which is equivalent to the capped sum. The score is $s_k(w) = \sum_\sigma s^{\sigma}_k(w) \in [0, 5]$; a category with $s_k(w) \ge \theta = 1$ is then vetoed if any exclusion pattern of $Z_k$ matches the concatenation of title and abstract, in which case its score is set to zero and it is not assigned. The set of assigned categories is $C(w) = \{k : s_k(w) \ge \theta,\ \text{not vetoed}\}$, and the stored score of an assigned category is $s_k(w)$ rounded to three decimals. Two elementary properties justify the reading given in Part~IV\@. The cap makes each component a bounded, monotone, subadditive function of the matched weights: adding a signal never lowers a component, and no number of signals of one type can contribute more than one. And because the threshold equals the cap, a single weight-one signal of any type suffices for assignment while signals of weight below one require corroboration from a different type; formally, $s_k(w) \ge 1$ holds if and only if either some component reaches one or the sum of the (uncapped) components across at least two types reaches one. \paragraph{Primary category as the minimum of a total order.} Let $\mathcal{P}(w) = \bigcup_{k \in C(w)} \mathrm{parents}(k)$ be the set of categories declared parents of at least one assigned category (the \texttt{child\_of} relation of the ontology). The implementation sorts the assigned categories by the key \begin{equation} \phi(k) \;=\; \bigl( -s_k(w),\ \mathbf{1}[k \in \mathcal{P}(w)],\ \mathrm{number}(k) \bigr) \in \R \times \{0,1\} \times \mathbb{N} \label{eq:appC-key} \end{equation} in lexicographic order and takes the first element; this is $\kappa^{\ast}(w) = \arg\min_{k \in C(w)} \phi(k)$ and coincides with the lexicographic arg-max of Part~IV (the sign of the first component reversed). The lexicographic order on $\R \times \{0,1\} \times \mathbb{N}$ is a total order, and $\phi$ is injective on $\mathcal{K}$ because the ontology numbers are distinct, so the restriction of $\phi$ to $C(w)$ has a unique minimum whenever $C(w) \ne \emptyset$: the primary category is well defined and does not depend on the order in which categories are scanned. The second component implements ``child before parent'': if $k$ and $k'$ are both assigned with equal scores and $k'$ is a declared parent of $k$, then $k' \in \mathcal{P}(w)$ while $k$ may not be, and $k$ precedes $k'$. The rule is not transitive in the sense of a hierarchy, however. Membership in $\mathcal{P}(w)$ depends only on whether $k$ is the parent of \emph{some} assigned category, not of the specific competitor; a category that is the parent of a low-scoring assigned child is demoted in the tie against an unrelated category of equal score. This is a property of the key as implemented, stated here so that the primary counts of Part~IX are read with it; it affects only exact ties in a score rounded to three decimals, which are frequent precisely among the categories whose signals are weight-one keywords. The third component, the ontology number, is arbitrary and makes the order total; no claim is attached to it. \subsection{The emerging-topic label and the absence of look-ahead} \label{sec:appC-lookahead} \paragraph{Filtrations.} Index months by integers $t = 0, 1, \dots, M$ (January 2018 to the last complete month) and let the panel of \texttt{experiments/emerging\_detection.py} be the pair of arrays $n_{k,t}$ (eligible month-precision works of topic $k$ with first month $t$) and $c_{k,t}$ (internal citations received by works of topic $k$ from works with first month $t$). Define the filtration \begin{equation} \mathcal{F}_T \;=\; \sigma\bigl( n_{k,t},\ c_{k,t} :\ k \in \mathcal{K}_{\mathrm{top}},\ t \le T \bigr), \label{eq:appC-filtration} \end{equation} the information contained in the panel columns up to and including month $T$. A statistic is \emph{available at} $T$ if it is $\mathcal{F}_T$-measurable. Each of the six features of Part~IV is a function of sums of panel entries over windows $(a, b]$ with $b \le T$: $g^{12}_{k,T}$ uses $(T-24, T]$, $\mathrm{acc}_{k,T}$ uses $(T-36, T]$, $z_{k,T}$ uses $[T-27, T]$, $\mathrm{cit}_{k,T}$ uses $(T-24, T]$ of $c$, $\mathrm{share}_{k,T}$ uses $(T-12, T]$ of every topic, and $\mathrm{age}_{k,T}$ uses the cumulative sum up to $T$. All are $\mathcal{F}_T$-measurable by construction. The implementation enforces this by index arithmetic (\texttt{win(a, lo, hi)} slices columns \texttt{lo+1} to \texttt{hi} inclusive with \texttt{hi = T\_idx}), not by convention. \paragraph{Label.} The label $\ell_{k,T,h}$ of equation~\eqref{eq:label} is a function of $V_k(T-h, T]$, $V_k(T, T+h]$, $V_k(T-12, T]$ and of the within-cutoff decile of $g^{\mathrm{fut}}$ over eligible topics; it is therefore $\mathcal{F}_{T+h}$-measurable and, because it depends on columns strictly after $T$, not $\mathcal{F}_T$-measurable. The feature--label pair at cutoff $T$ thus has the structure of a prediction problem: predict an $\mathcal{F}_{T+h}$-measurable outcome from an $\mathcal{F}_T$-measurable input. The eligibility condition $V_k(T-12, T] \ge 20$ is $\mathcal{F}_T$-measurable, so conditioning on it does not leak the outcome. \paragraph{Separation of training and test.} Let $\mathcal{T}_{\mathrm{tr}}$ and $\mathcal{T}_{\mathrm{te}}$ be the training and test cutoffs. Every quantity used to fit a model---features, labels and the standardisation constants of the scaler, which is fitted on training rows only---is $\mathcal{F}_{T^{\mathrm{tr}}_{\max} + h}$-measurable with $T^{\mathrm{tr}}_{\max} = \max \mathcal{T}_{\mathrm{tr}}$. The implementation takes as candidate cutoffs every third month of the panel, which begins in January 2018 (January, April, July and October of each year), and admits as training cutoffs those from December 2019 up to December 2021 for $h = 12$ and up to December 2020 for $h = 24$; the realised training cutoffs therefore run from January 2020 to October 2021 ($h = 12$) or to October 2020 ($h = 24$), so that $T^{\mathrm{tr}}_{\max} + h$ is October 2022 in both cases, and the first test cutoff is January 2023 (the last is October 2024 at most, subject to the censoring condition below). The realised lists are written to \texttt{results/emerging/metrics\_h12.json} and \texttt{metrics\_h24.json} under \texttt{train\_cutoffs} and \texttt{test\_cutoffs}. Hence \begin{equation} T^{\mathrm{tr}}_{\max} + h \;<\; \min \mathcal{T}_{\mathrm{te}}, \label{eq:appC-gap} \end{equation} and the fitted predictor is measurable with respect to a $\sigma$-field that precedes every test feature, let alone every test label, which closes at $\max \mathcal{T}_{\mathrm{te}} + h \le M$. Condition \eqref{eq:appC-gap} is the formal content of ``out of time'' in the sense of \citet{bergmeir2012crossval}; it is stricter than the plan's wording, which allowed training cutoffs through 2022; the code's rule is the one that guarantees \eqref{eq:appC-gap}, and Part~IV describes the same rule. The test cutoffs are further restricted to those with $T + h \le M$, so that no test label is right-censored. \paragraph{What measurability does not cover.} The filtration \eqref{eq:appC-filtration} is generated by the panel, and the panel is built once, in 2026, from a corpus whose topic assignments, eligibility flags, linkage and month-precision filter were all fixed with knowledge of the whole period. Formally, the random objects $n_{k,t}$ themselves are not $\mathcal{F}_t$-measurable functionals of the literature as it stood at $t$: they are functionals of the literature as OpenAlex indexed and classified it by October 2026. The statement proved above is therefore conditional: \emph{given} the 2026 panel, no feature at $T$ uses a column after $T$ and no training quantity uses a column at or after the first test cutoff. It is not the statement that an observer in 2021 could have computed the training set, which would require a topic vocabulary and a corpus frozen in 2021. Part~IV draws the distinction and names the cluster-based extension that would narrow it; the derivation here makes precise which half of the claim is proved and which is assumed.