% ============================================================================ % Part IV — Computational Methodology % Written by Agent L (Part IV instance), 2026-11-03. Documents what the code in % ingestion/, systematic_review/, taxonomy/, bibliometrics/, knowledge_graph/, % econometrics/, embeddings/ and experiments/ actually does. Where the code and % RESEARCH_PLAN.md differ, the code is described and the difference is stated. % Corpus numbers only through macros of tables/numbers.tex. % ============================================================================ \section{Notation and the corpus as a measurable object} \label{sec:m-notation} Every quantity reported in Parts VIII and IX is a function of a finite set of bibliographic records and of a small number of deterministic transformations applied to them. This part states those transformations with enough precision that an independent analyst could recompute the results from the raw snapshots listed in Part III. The exposition follows the order of the pipeline (\texttt{reproducibility/RUNBOOK.md}): record linkage, deduplication and eligibility (Section~\ref{sec:m-linkage}), multi-label classification (Section~\ref{sec:m-classification}), bibliometric indicators (Section~\ref{sec:m-bibliometrics}), network measures (Section~\ref{sec:m-networks}), semantic mapping (Section~\ref{sec:m-semantic}), structural change (Section~\ref{sec:m-structural}), emerging-topic detection (Section~\ref{sec:m-emerging}), knowledge-graph extraction (Section~\ref{sec:m-kg}) and the treatment of uncertainty and reproducibility (Section~\ref{sec:m-uncertainty}). Throughout, a design choice that departs from the preregistered plan (\texttt{RESEARCH\_PLAN.md}, \texttt{protocol/PROTOCOL.md}) is stated as such, because the code, not the plan, is what produced the numbers. \subsection{Works, dates and periods} Let $\mathcal{W}_0$ denote the set of OpenAlex work records loaded from the snapshot of 14~October 2026 (the records carrying at least one topic of the Computer Science field, plus the second-pass records recovered through DBLP and arXiv identifiers, Section~\ref{sec:m-linkage}). Each record $w \in \mathcal{W}_0$ carries an OpenAlex identifier, a type $\tau(w)$ drawn from the OpenAlex controlled vocabulary, a publication date $d_{\mathrm{pub}}(w)$, a creation date $d_{\mathrm{cr}}(w)$ (the date at which the record entered OpenAlex), a title, an optional abstract, authorships, a primary source (venue), OpenAlex topics with their subfield and field, a list of referenced works, and yearly citation counts. Linked records from DBLP, arXiv and the ACL Anthology attach to $w$ a DBLP key, an arXiv identifier with its arXiv creation date $d_{\mathrm{arx}}(w)$ and primary category, and an ACL identifier. The temporal position of a work is its \emph{first date}, \begin{equation} d(w) \;=\; \min\bigl\{\, d_{\mathrm{pub}}(w),\; d_{\mathrm{pub}}(\pi(w)),\; d_{\mathrm{arx}}(w) \,\bigr\}, \label{eq:first-date} \end{equation} where $\pi(w)$ is the preprint record merged into $w$ by the deduplication rule of Section~\ref{sec:m-dedup} when one exists, and each missing term is replaced by $d_{\mathrm{pub}}(w)$. The first date, not the date of the version of record, is the quantity that places a work on the time axis, because the research question concerns when ideas entered the literature rather than when a publisher released them. The publication year $y(w)$ used for citation normalisation is, in contrast, the OpenAlex \texttt{publication\_year} of the surviving record, because citation windows are defined in calendar years of the OpenAlex \texttt{counts\_by\_year} table (Section~\ref{sec:m-citations}). The two conventions are deliberately distinct and both are stored on every record. The observation window is $[t_0, t_1] = [\text{2018-01-01}, \text{2026-11-02}]$, split at the reference date $t^{\ast} = \text{2022-11-30}$ into a baseline period $B = [t_0, t^{\ast})$ and a post period $P = [t^{\ast}, t_1]$: \begin{equation} \mathrm{period}(w) \;=\; \begin{cases} B & \text{if } t_0 \le d(w) < t^{\ast},\\ P & \text{if } t^{\ast} \le d(w) \le t_1 . \end{cases} \end{equation} Monthly series use the month $m(w)$ of the first date. Two facts about dates constrain everything that follows. First, a substantial share of OpenAlex records carry a publication date equal to the first of January of their year, which is the database's convention for year-only precision rather than a real date. The pipeline therefore attaches to every record a flag \begin{equation} \mathrm{prec}(w) \;=\; \begin{cases} \text{year} & \text{if } d_{\mathrm{pub}}(w) \text{ falls on 1 January},\\ \text{month} & \text{otherwise}, \end{cases} \end{equation} and every monthly series in this paper is computed on the month-precision subset $\mathcal{W}^{\mathrm{m}} = \{w : \mathrm{prec}(w) = \text{month}\}$ only (amendment A-002). A genuine 1~January publication is thereby misclassified as year precision and dropped from monthly series; the loss is small and, more importantly, it does not depend on the period, so it cannot manufacture a break. Annual series use all eligible records. Second, the right end of the window is censored: records published in the last months before the snapshot are under-represented because OpenAlex indexes them with a lag. The treatment of this right-truncation is specified in Section~\ref{sec:m-truncation}. \subsection{Categories, areas and the measurable structure} Let $\mathcal{K}$ be the set of the forty leaf categories of the ontology (\texttt{taxonomy/ontology.yaml}, Part III and Appendix~A) and $\mathcal{A}$ the set of its eight areas, with the surjection $a : \mathcal{K} \to \mathcal{A}$ assigning each leaf to its area. Seven leaves are additionally declared children of another leaf (for instance \textit{llm} $\prec$ \textit{foundation\_models}, \textit{compilers} $\prec$ \textit{programming\_languages}); this partial order $\prec$ is used only to break ties when a primary category is chosen. The classifier of Section~\ref{sec:m-classification} assigns to each work a label set $C(w) \subseteq \mathcal{K}$, possibly empty, and, when $C(w) \neq \emptyset$, a primary category $\kappa^{\ast}(w) \in C(w)$. Multi-label counting and primary counting give different answers to ``how many works are in category $k$'', and both are reported: for a set of works $S$, \begin{equation} N_k^{\mathrm{ml}}(S) = \bigl|\{ w \in S : k \in C(w) \}\bigr|, \qquad N_k^{\mathrm{pr}}(S) = \bigl|\{ w \in S : \kappa^{\ast}(w) = k \}\bigr| , \end{equation} so that $\sum_k N_k^{\mathrm{pr}}(S) \le |S|$ with equality when every work is classified, whereas $\sum_k N_k^{\mathrm{ml}}(S)$ exceeds $|S|$ by the number of secondary labels. Flows between categories (Section~\ref{sec:m-networks}) and the emerging-topic panel (Section~\ref{sec:m-emerging}) use the primary label; co-classification statistics use the full label set. The eligible corpus $\mathcal{W} \subseteq \mathcal{W}_0$ is the set of records passing the predicate $E(w)$ of Section~\ref{sec:m-eligibility}. For a month $t$ and a category $k$, the elementary counts are \begin{equation} N_t = \bigl|\{ w \in \mathcal{W}^{\mathrm{m}} : m(w) = t \}\bigr|, \qquad N_{k,t} = \bigl|\{ w \in \mathcal{W}^{\mathrm{m}} : m(w) = t,\; \kappa^{\ast}(w) = k \}\bigr|, \qquad s_{k,t} = N_{k,t}/N_t . \label{eq:counts} \end{equation} Every estimand of Parts VIII and IX is a functional of these counts, of the citation matrix of Section~\ref{sec:m-citations}, of the authorship lists, or of the embedding vectors of Section~\ref{sec:m-semantic}. The corpus is finite and fully enumerated, so the descriptive quantities are population quantities rather than sample estimates; the inferential devices of Sections~\ref{sec:m-structural} and~\ref{sec:m-emerging} address a different kind of uncertainty, namely whether an observed temporal pattern is distinguishable from the ordinary fluctuations of the series, and whether a predictor would have worked out of time. \subsection{Storage and computation} The pipeline keeps the raw snapshots immutable (per-file SHA-256 ledgers, Section~\ref{sec:m-uncertainty}) and materialises all derived tables as Parquet files queried through DuckDB \citep{raasveldt2019duckdb}; the linkage, deduplication, eligibility, counting and citation-window steps are SQL statements executed inside one database file, which makes every table in this part a deterministic function of the raw inputs and of the script that produced it. Python is used where SQL is inconvenient: the regular-expression classifier, the structural-change toolkit, the embedding and clustering steps, and the detector. The slim table of all OpenAlex works (\LinkSlimTotal{} rows: identifier, DOI, year, type, primary topic hierarchy, citation count) is kept so that the field of a cited work outside computer science can be resolved (Section~\ref{sec:m-citgraph}); this is decision D2 of the plan. \section{Record linkage, deduplication and eligibility} \label{sec:m-linkage} The four sources describe overlapping but differently delimited populations: OpenAlex is the backbone, DBLP defines what counts as a computer-science venue, arXiv contributes preprints and their categories, and the ACL Anthology serves as a coverage check for natural-language processing. Combining them is a record linkage problem in the classical sense of \citet{fellegi1969linkage}: two records from different files must be declared the same work or not, on the basis of comparison vectors computed from their fields. The pipeline uses a deterministic cascade rather than a probabilistic model, because the dominant comparison fields (DOI and arXiv identifier) are persistent identifiers whose agreement is near-conclusive, and because a probabilistic model would require labelled training pairs that the project does not possess before the human checkpoint H-1. The cost of this choice is that the precision of the residual title-based step must be estimated from a reviewed sample rather than derived from the model; the design of that estimate is given in Section~\ref{sec:m-linkprecision}. \subsection{Normalised keys and the linkage cascade} \label{sec:m-cascade} For each source the script \texttt{ingestion/link\_sources.py} builds a key table. A DOI is lower-cased. An arXiv identifier is lower-cased and stripped of its version suffix (\texttt{v[0-9]+\$}); for DBLP records, which do not carry an arXiv field, the identifier is extracted from the electronic-edition URLs by the pattern \texttt{arxiv.org/abs/([\^{} ]+)}. A title is normalised by the map \begin{equation} \eta(\text{title}) \;=\; \mathrm{delete}_{\,\neg[a\text{--}z\,0\text{--}9]}\bigl(\mathrm{lower}(\text{title})\bigr), \label{eq:ntitle} \end{equation} which lower-cases and deletes every character outside $[a$--$z0$--$9]$, so that punctuation, whitespace, case and diacritics (which do not survive the ASCII filter) no longer separate otherwise identical titles. The normalised title is used only for records whose original title has at least 25 characters, a threshold that removes the many short generic titles (``Introduction'', ``Editorial'', ``Preface'') for which equality of $\eta$ carries no evidence. DBLP records are restricted to the years 2018--2026 and to the record types \textit{article}, \textit{inproceedings}, \textit{incollection}, \textit{book}, \textit{phdthesis} and \textit{data}. The DBLP--OpenAlex cascade is then \begin{enumerate} \item \textbf{DOI}: join on equal lower-cased DOI; every matching pair is kept (a DBLP key may match several OpenAlex records sharing a DOI, and conversely; the many-to-many structure is resolved at the deduplication stage, not here); \item \textbf{arXiv}: among records unmatched on both sides, join on equal normalised arXiv identifier; \item \textbf{title--year}: among records still unmatched on both sides, restrict each side to normalised titles that are \emph{unique} within that side, join on equal $\eta$, and keep the pair if the years differ by at most one. \end{enumerate} The uniqueness restriction in step 3 is the blocking device: it turns the join into a one-to-one map and prevents a frequent title from generating a clique of spurious pairs. The price is recall, since a genuine pair whose title appears twice on either side (a journal version and a workshop version with the same title, for instance) cannot be linked at this step; such pairs are usually caught by the DOI step or by the preprint merge of Section~\ref{sec:m-dedup}. The arXiv--OpenAlex cascade is analogous (arXiv identifier, then DOI, then unique normalised title with a year tolerance of two, because the arXiv creation year and the OpenAlex publication year of the version of record can legitimately differ by more than one). The ACL--OpenAlex cascade uses DOI, then the ACL identifier parsed from OpenAlex landing-page URLs of the form \texttt{aclanthology.org/}, then unique normalised title with a year tolerance of one. Each link carries its method label, which is the stratification variable of the precision sample. The counts of the first run are stored in \texttt{data/metadata/linkage\_report.json} and reproduced in Part III; here it suffices to note the shape of the result. Of the \LinkDblpTwoZeroOneEightTwoZeroTwoSix{} DBLP records in window, \LinkDblpWithDoi{} carry a DOI, \LinkLinkDblpOaDoi{} are linked by DOI and \LinkLinkDblpOaTitleYear{} by title and year, for \LinkDblpLinkedDistinct{} distinct DBLP keys linked and \LinkDblpUnlinked{} unlinked. No DBLP record was linked through the arXiv step (\LinkDblpWithArxiv{} DBLP keys with a parsable arXiv identifier), which reflects the fact that the DBLP dump used here places arXiv links in a field the parser did not read rather than a property of the literature; the arXiv--OpenAlex cascade links \LinkArxivLinkedDistinct{} of the \LinkArxivCreatedTwoZeroOneEightTwoZeroTwoSix{} arXiv \texttt{cs} records created in window, almost all of them (\LinkLinkArxivOaArxivId{}) by identifier. The \LinkDblpUnlinkedWithDoiInSlim{} unlinked DBLP records whose DOI does exist in the slim table of all OpenAlex works are precisely the records that OpenAlex does not label with any Computer Science topic; they motivate the second snapshot pass, in which these identifiers (\LinkNeededOaIdsSecondPassDblpDoi{} from DBLP and \LinkNeededOaIdsSecondPassArxivDoi{} from arXiv) are fetched in full and the linkage is rerun with the union of both passes. The corpus is therefore not the set of works that OpenAlex calls computer science; it is the union of that set with what DBLP and arXiv call computer science, which is the sense in which the mandate's requirement to ``cover the complete breadth of computer science'' rather than only the OpenAlex topic model is operationalised. \subsection{Preprint--publication deduplication} \label{sec:m-dedup} A work that exists as an arXiv preprint and as a published version is two OpenAlex records whenever OpenAlex has not merged them. Counting both would double-count exactly the kind of work (AI preprints) whose growth is at issue (CLAUDE.md §6.2). The script \texttt{systematic\_review/define\_corpus.py} identifies such pairs within $\mathcal{W}_0$ by a title rule: \begin{equation} (p, b) \text{ is a candidate pair} \iff \eta(p) = \eta(b),\;\; |y(p) - y(b)| \le 2,\;\; p \in \mathcal{P},\;\; b \notin \mathcal{P},\;\; |\text{title}| \ge 25, \label{eq:duppair} \end{equation} where $\mathcal{P} = \{ w : \tau(w) = \text{preprint} \text{ or } \text{DOI}(w) \text{ starts with } \text{10.48550/arxiv} \}$ is the preprint-like set. A preprint may match several published records and conversely; the rule keeps, for each published record, the earliest-dated preprint and, for each preprint, the earliest-dated published record, and discards any pair that is not the first in both orderings. The surviving pairs define the map $\pi$ of equation~\eqref{eq:first-date}: the published record $b$ receives $\pi(b) = p$, $\text{preprint\_date}(b) = d_{\mathrm{pub}}(p)$ and the earlier of the two dates as its first date; the preprint $p$ receives the flag \textit{e5\_duplicate} and leaves the eligible corpus. The version relationship is therefore kept on the surviving node, as the plan requires, but the match is by exact normalised title only. Two limitations follow. A preprint whose title changed between versions is not merged, and the pair survives as two works; a preprint and an unrelated published paper with an identical normalised title within two years are wrongly merged. The second error is rare for titles of at least 25 characters; the first is the more consequential one and biases the preprint share upward, which is the conservative direction for hypothesis H7. Deduplication across the OpenAlex--DBLP boundary is not needed because DBLP records are never counted as works: a DBLP record either links to an OpenAlex record, in which case the OpenAlex record carries the flag \textit{in\_dblp}, or it does not, in which case it is counted in the separate DBLP-only table used for coverage assessment. \subsection{Eligibility predicate} \label{sec:m-eligibility} Each record receives seven exclusion flags and two membership flags, computed once and stored, so that every PRISMA count is a filter on the same table. With $T_{\mathrm{keep}}$ = \{article, conference-paper, preprint, book-chapter, book, dissertation, report, review, software-paper\}, $T_{\mathrm{hard}}$ = \{editorial, erratum, retraction, peer-review, paratext, conference-abstract, reference-entry, dataset, software, supplementary-materials, libguides, letter, grant, standard\}, and $\mathcal{G}$ the list of generic deposit platforms (Zenodo, Figshare, IRDB, LA Referencia, Dialnet, DOAJ-as-source, OSTI), the flags are \begin{align} e_1(w) &: d_{\mathrm{pub}}(w) \text{ missing or outside } [t_0, t_1];\\ e_2(w) &: \tau(w) \notin T_{\mathrm{keep}} \;\wedge\; \neg\bigl(\text{in\_dblp}(w) \wedge \tau(w) \notin T_{\mathrm{hard}}\bigr);\\ e_3(w) &: \text{is\_xpac}(w) \wedge \neg \text{in\_dblp}(w);\\ e_4(w) &: \text{title empty};\\ e_5(w) &: w \text{ is the preprint member of a pair of \eqref{eq:duppair}};\\ e_6(w) &: \text{is\_retracted}(w);\\ e_7(w) &: \text{source}(w) \in \mathcal{G} \wedge \neg\text{in\_dblp}(w) \wedge \text{no linked arXiv record}. \end{align} The membership flags encode the computer-science rule of the protocol: \begin{align} \text{core}(w) &= \text{in\_dblp}(w) \;\vee\; \text{cs\_primary}(w) \;\vee\; \bigl(\text{cs\_any}(w) \wedge \text{arxiv\_cs\_primary}(w)\bigr),\\ \text{penumbra}(w) &= \text{cs\_any}(w) \wedge \neg\,\text{core}(w), \end{align} where \text{cs\_primary} means that the primary OpenAlex topic belongs to field 17, \text{cs\_any} that some topic does, and \text{arxiv\_cs\_primary} that the linked arXiv record's primary category starts with \texttt{cs.}. The eligibility predicate is \begin{equation} E(w) \;=\; \neg e_1 \wedge \neg e_2 \wedge \neg e_3 \wedge \neg e_4 \wedge \neg e_5 \wedge \neg e_7 \wedge \text{core}(w). \label{eq:eligible} \end{equation} Three features of this predicate deserve comment. Retraction ($e_6$) is \emph{not} part of $E$: retracted works stay in the mapping corpus with their flag and are excluded only from impact-based selections (Section~\ref{sec:m-kg}), as the protocol specifies (E6). The type rule $e_2$ is asymmetric by amendment A-001: a DBLP-indexed record is kept whatever its OpenAlex type unless that type is in the hard-exclusion list, because the first run showed that OpenAlex typed more than a million DBLP conference papers in ways the original list rejected; XPAC records (OpenAlex's expansion of coverage from secondary sources) are likewise kept when DBLP-indexed and flagged \textit{xpac\_kept\_dblp}. The deposit-platform rule $e_7$ was added by amendment A-002 after Zenodo alone was found to contribute a six-figure number of 2026 records typed as articles with almost no references; the protocol's original E7 (penumbra) is now the membership flag rather than an exclusion, so the reason code E7 in the protocol and the flag $e_7$ in the code denote different things. This is a documentation discrepancy, not an analytical one, but readers comparing the protocol and the PRISMA table should be aware of it. The penumbra set---works with a secondary computer-science topic but neither DBLP nor arXiv support---is counted separately and enters only sensitivity analyses; the strict core used for the sensitivity analyses in the other direction is $\{w : E(w) \wedge \text{in\_dblp}(w) \wedge \text{cs\_primary}(w)\}$. The PRISMA counts are computed both marginally (how many records carry each flag) and sequentially (how many are removed by each flag after the previous ones have been applied, in the order $e_1, e_2, e_3, e_4, e_5, e_7$), because the flags overlap heavily and only the sequential version sums to the final count. The order is a reporting convention; the final eligible set does not depend on it. \subsection{Design of the linkage-precision estimate} \label{sec:m-linkprecision} Precision of the deterministic cascade is estimated on a stratified sample of 500 DBLP--OpenAlex pairs drawn by \texttt{systematic\_review/linkage\_sample.py}: 250 pairs linked by DOI, 200 by title--year and 50 by arXiv identifier (the last stratum is empty in the current run, for the reason given in Section~\ref{sec:m-cascade}), selected by ordering each stratum on a hash of the DBLP key salted with the seed 44 and taking the first records, which is a reproducible simple random sample within stratum. For each pair the script computes an automatic agreement vector: a string similarity between the two raw titles (Python's \texttt{difflib} ratio, twice the number of matched characters in the longest-matching-block alignment divided by the total length), the absolute year difference, and whether the last tokens of the two first-author names coincide; a pair is \textit{auto\_ok} if the similarity is at least 0.9, the years differ by at most one and the surnames agree whenever both are present. Two of every five pairs are reserved for the principal investigator (\textit{pi\_review}), whose verdicts constitute the human checkpoint H-1. Let $n_s$ be the stratum sizes and $\hat p_s$ the share of pairs judged correct in stratum $s$; the overall precision of the link table is the weighted estimate \begin{equation} \hat p \;=\; \sum_s \frac{L_s}{L}\,\hat p_s, \qquad \widehat{\mathrm{Var}}(\hat p) = \sum_s \Bigl(\frac{L_s}{L}\Bigr)^2 \frac{\hat p_s(1-\hat p_s)}{n_s}, \label{eq:linkprec} \end{equation} where $L_s$ is the number of links of method $s$ in the full table and $L$ their sum, so that the title--year stratum, which is the only one where errors are plausible, is weighted by its small share of the links. The estimate \pending{linkage precision from the H-1 sample, data/metadata/linkage\_sample\_summary.json} is reported in Part III once the checkpoint is signed; until then the automatic agreement rate is the only available figure and is labelled as such. Recall is not estimated by this design: a DBLP record without an OpenAlex counterpart may be a true absence from OpenAlex or a missed link, and distinguishing the two would require searching OpenAlex by title for a sample of unlinked DBLP records, which is left to the robustness appendix. \section{Multi-label classification into the ontology} \label{sec:m-classification} The ontology assigns works to forty categories by rules over four kinds of metadata signals and one textual signal. A rule-based classifier was preferred to a trained one for three reasons that are worth stating because they are also its limitations. The rules are inspectable: every assignment can be traced to the signals that produced it, and the mapping from OpenAlex topics, arXiv categories and DBLP venues to categories is a document (\texttt{taxonomy/ontology.yaml}, with provenance notes per category) that a reader can contest line by line. The rules need no labelled training set, which the project did not have before checkpoint H-2, and so cannot inherit the biases of one. And the rules are cheap enough to run on every eligible work, whereas an LLM rater at the quality used for validation would cost orders of magnitude more. The corresponding limitations are that rules do not generalise beyond the vocabulary they encode, that the weights are expert judgements rather than estimates, and that validation against independent raters is therefore the only evidence of their accuracy. \subsection{Signals and the score} \label{sec:m-score} For a work $w$, let $T(w)$ be its set of OpenAlex topic identifiers (up to three per work), $F(w)$ its set of subfield identifiers, $X(w)$ the set of arXiv categories of its linked arXiv record (primary and cross-lists), $D(w)$ the set of DBLP venue streams of its linked DBLP records, and $\text{title}(w)$, $\text{abs}(w)$ its title and abstract. Each category $k$ specifies weight maps $\omega^{\mathrm{T}}_k : T \to [0,1]$, $\omega^{\mathrm{F}}_k$, $\omega^{\mathrm{X}}_k$, $\omega^{\mathrm{D}}_k$ over the respective vocabularies (zero outside the listed entries), a list of keyword rules $(r, \omega, \phi)$ consisting of a regular expression $r$, a weight $\omega$ and a field $\phi \in \{\text{title}, \text{abstract}, \text{both}\}$, and a list of exclusion regular expressions $Z_k$. The score of $w$ for $k$ is \begin{equation} s_k(w) \;=\; \sum_{\sigma \in \{\mathrm{T},\mathrm{F},\mathrm{X},\mathrm{D}\}} \min\Bigl\{1,\; \sum_{x \in \sigma(w)} \omega^{\sigma}_k(x)\Bigr\} \;+\; \min\Bigl\{1,\; \sum_{(r,\omega,\phi) \in R_k} \omega \cdot \mathbf{1}\bigl[r \text{ matches } \phi(w)\bigr]\Bigr\}, \label{eq:score} \end{equation} where $\phi(w)$ is the title, the abstract, or their concatenation according to the field of the rule. Each of the five signal types is thus capped at one before the types are summed, so $s_k(w) \in [0, 5]$, and the assignment rule is \begin{equation} k \in C(w) \iff s_k(w) \ge \theta \;\wedge\; \neg\, \exists\, z \in Z_k :\ z \text{ matches } \text{title}(w) \| \text{abs}(w), \qquad \theta = 1 . \label{eq:assign} \end{equation} The cap is what gives the weights their meaning. A single signal with weight one (a topic that \emph{is} the category, a venue that publishes nothing else, a keyword that names the object of study) suffices on its own; a signal with weight below one is a partial indication that must be corroborated by a signal of another type, because repetitions of the same type cannot push the capped sum above one. The ontology uses this device deliberately: the six AI categories that the OpenAlex topic model does not separate (large language models, foundation models, multimodal AI, generative AI, agents, AI safety) rely on keyword rules of weight one that fire on the name of the object, while their topic and venue signals are fractional. The exclusion list is a veto applied after the threshold: a category that would otherwise be assigned is removed if any exclusion pattern matches the title or abstract (for instance a cryptocurrency pattern vetoing applied cryptography). The veto is not a negative weight; it cannot be outvoted. One discrepancy between the ontology document and the implementation must be recorded. The notes of the \texttt{assignment\_rule} block state that the classifier takes the \emph{maximum} over matched topics before capping, whereas \texttt{taxonomy/classify.py} takes the \emph{sum} and then caps, as equation~\eqref{eq:score} states. The two agree whenever at most one listed topic matches or the matched weights already sum to at least one; they differ when two fractional topics of the same category co-occur, in which case the implemented rule is the more permissive. The unit tests in \texttt{tests/test\_classify\_rules.py} fix the implemented behaviour (a topic listed three times contributes its weight once, because the topic set is deduplicated, and a 0.6 topic plus a 0.4 arXiv category reach exactly 1.0). The manuscript describes the implemented rule. \subsection{Primary category} When $C(w) \neq \emptyset$ the primary category is \begin{equation} \kappa^{\ast}(w) \;=\; \operatorname*{arg\,max}_{k \in C(w)} \bigl( s_k(w),\; -\mathbf{1}[k \text{ is a parent of some } k' \in C(w)],\; -\mathrm{number}(k) \bigr) \end{equation} in lexicographic order: the highest score wins; among equal scores a category that is the declared parent of another assigned category loses to its child (so that a work scoring equally on \textit{llm} and \textit{foundation\_models} is primarily an LLM paper); among remaining ties the lower ontology number wins. The last rule is arbitrary and is stated so that the reader can see that it is. The number of assigned categories $|C(w)|$ and the primary score are stored with every work; works with $C(w) = \emptyset$ (eligible works none of whose signals reach the threshold) are counted and characterised in Part IX, and their share is one of the quality indicators of the classification. The classifier is run on the eligible corpus and on the penumbra, so that sensitivity analyses on the wider set do not require a second run. \subsection{Validation design and metrics} \label{sec:m-validation} The rules are validated against two independent LLM raters on a stratified sample (\texttt{taxonomy/VALIDATION.md}, \texttt{taxonomy/validate\_sample.py}): fifty eligible works with an abstract per rule-assigned primary category (forty strata) plus two hundred works with no category, drawn by ordering each stratum on a salted hash with seed 44; two hundred of the resulting works are reserved for the principal investigator (checkpoint H-2). Each rater receives the forty category definitions, and for each work the title, abstract, venue and year, and returns under a JSON schema a label set of at most five categories, a primary category or null, a confidence and a short rationale. The raters never see the rule-based assignment, so there is no leakage from the rules to the reference labels, and the rule revision policy (a category with consensus $F_1 < 0.60$ triggers a mapping revision, logged as an amendment, and a re-run) can be applied without re-rating. The two raters are different models of the same family (\texttt{claude-haiku-5-5}, \texttt{claude-sonnet-5-5}); their agreement therefore does not measure the agreement that two human experts would reach, and the 200-work human subsample is the only anchor for that. With $\hat C(w)$ the rule label set, $C^{r}(w)$ the label set of rater $r$ and $C^{\cap}(w) = C^{A}(w) \cap C^{B}(w)$ the consensus set, the per-category confusion counts against a reference $C^{\mathrm{ref}}$ are $\mathrm{TP}_k = |\{w : k \in \hat C(w) \wedge k \in C^{\mathrm{ref}}(w)\}|$, $\mathrm{FP}_k = |\{w : k \in \hat C(w) \wedge k \notin C^{\mathrm{ref}}(w)\}|$, $\mathrm{FN}_k = |\{w : k \notin \hat C(w) \wedge k \in C^{\mathrm{ref}}(w)\}|$, with precision $P_k = \mathrm{TP}_k/(\mathrm{TP}_k+\mathrm{FP}_k)$, recall $R_k = \mathrm{TP}_k/(\mathrm{TP}_k+\mathrm{FN}_k)$ and $F_{1,k} = 2P_kR_k/(P_k+R_k)$, the standard label-wise decomposition of multi-label evaluation \citep{zhang2014multilabel}. Micro-averages pool the counts over categories before forming the ratios; the macro-$F_1$ is the unweighted mean of $F_{1,k}$ over categories with at least one positive or predicted label. Because the sample is stratified by rule-assigned primary category, the per-category precision is estimated on roughly equal support for every category, whereas recall is estimated only among works that the rules placed somewhere; a category that the rules systematically miss (true members scattered among other strata or among the unassigned) will show inflated recall in this design. The 200 unassigned works partly address this, but a proper recall estimate would require sampling from the whole corpus with weights, and the per-category recall figures should be read with that caveat. Agreement on the primary category is measured by Cohen's $\kappa$ \citep{cohen1960kappa}, \begin{equation} \kappa \;=\; \frac{p_o - p_e}{1 - p_e}, \qquad p_o = \frac{1}{n}\sum_w \mathbf{1}[\kappa^{A}(w) = \kappa^{B}(w)], \qquad p_e = \sum_{k \in \mathcal{K} \cup \{\varnothing\}} \frac{n^{A}_k}{n}\,\frac{n^{B}_k}{n}, \end{equation} where ``no category'' is treated as a forty-first label and $n^{r}_k$ counts the works to which rater $r$ assigned primary $k$; $\kappa$ is computed between the two raters and between the rules and each rater. Agreement on the label sets is measured by the mean Jaccard index $\bar J = n^{-1}\sum_w |C^{A}(w) \cap C^{B}(w)| / |C^{A}(w) \cup C^{B}(w)|$ (with the convention $0/0 = 0$). The validation note announces Krippendorff's $\alpha$ with the MASI distance for the multi-label agreement; the metrics script computes the mean Jaccard index instead, and the manuscript reports what is computed. A work is exported as a disagreement for human review when the rules, rater~A and rater~B have no category in common although at least one of them assigned one. \subsection{Known failure modes} The design makes some errors predictable, and they are listed here so that the results of the validation can be read against expectations rather than as surprises. Keyword rules on abstracts fire on mentions as well as on contributions: a systems paper that evaluates its scheduler on a large language model workload matches the LLM keyword and, since that keyword alone reaches the threshold, acquires the \textit{llm} label; the exclusion lists remove the most frequent such cases but cannot enumerate them. Venue signals are coarse: general machine-learning venues carry fractional weights for several AI categories at once, so a work with no abstract and a generic title can be assigned to a parent-level category on venue evidence alone, or to none. OpenAlex topics are themselves the output of a classifier with documented error, and a work whose topics are wrong inherits that error with weight; the protocol lists this among the limitations declared before analysis. Multi-label assignment with a cap of one per type and a threshold of one tends to over-assign categories to long abstracts that mention many objects, which inflates $|C(w)|$ in the post period, when abstracts increasingly cite models and benchmarks by name; the co-classification statistics of Section~\ref{sec:m-networks} are affected by this in a direction that would mimic convergence (hypothesis H4) and must be read together with the primary-label flow statistics, which are not. Finally, works without an abstract (a known share of the corpus) are classified from the title and the metadata only and have lower recall for the keyword-dependent categories; the share of such works is reported by year because it is not constant. \section{Bibliometric indicators} \label{sec:m-bibliometrics} The indicators of this section are the estimands of research questions RQ1, RQ3 and RQ6. They are standard in the scientometric literature, and the definitions follow the review of \citet{waltman2016review} where a choice had to be made; what is specific to this study is the citation-window discipline imposed by the eight-year span of the corpus and the explicit treatment of the two counting conventions. The scripts are \texttt{bibliometrics/01\_volume\_series.py}, \texttt{02\_collaboration.py} and \texttt{03\_citation\_impact.py}. \subsection{Volume, composition and growth} The monthly count $N_t$ and the category counts $N_{k,t}$ of equation~\eqref{eq:counts} are tabulated by first month, period, date precision, type and source membership (DBLP-indexed, OpenAlex-primary, arXiv-linked), with the numbers of works having an abstract, having at least one resolvable reference, and being open access; the annual table adds the mean number of authors, references and countries per work. Composition is the share $s_{k,t}$; its annual counterpart uses the primary label on all eligible works. Growth between two dates separated by $\Delta$ years is summarised by the compound annual growth rate \begin{equation} \mathrm{CAGR}(t_a, t_b) \;=\; \Bigl( \frac{N_{t_b}}{N_{t_a}} \Bigr)^{1/\Delta} - 1, \qquad \Delta = (t_b - t_a)\ \text{in years}, \label{eq:cagr} \end{equation} applied to annual totals and to annual category totals; it is a descriptive summary of two end points and says nothing about the path between them, which is why the structural-change analysis of Section~\ref{sec:m-structural} works on the full monthly series instead. The CAGR is computed at table-making time from the annual counts rather than by a dedicated script; the plan lists it among the Phase-4 indicators and it is reported for complete years only, since 2026 is right-censored (Section~\ref{sec:m-truncation}). \subsection{Fixed citation windows} \label{sec:m-citations} OpenAlex provides, for each work, the number of citations received in each calendar year (\texttt{counts\_by\_year}). Let $c_{w}(u)$ be the citations received by $w$ in calendar year $u$ and $y(w)$ its publication year. The fixed-window counts are \begin{equation} c^{(12)}_w = \sum_{u \le y(w)+1} c_w(u), \qquad c^{(36)}_w = \sum_{u \le y(w)+2} c_w(u), \qquad c^{(48)}_w = \sum_{u \le y(w)+3} c_w(u), \label{eq:windows} \end{equation} so that $c^{(12)}$ counts citations in the publication year and the following calendar year, $c^{(36)}$ in the publication year and the two following years, and so on. The superscripts are the names used in the code and in the tables and must be read as calendar-year windows rather than as exact month counts: a work published in January and one published in December of the same year receive windows that differ by eleven months in effective length. This granularity is imposed by the data (OpenAlex does not provide citation dates below the year) and is the same for the baseline and the post period, so it blurs comparisons within a year but does not bias comparisons between years. The window is the device that neutralises citation-age bias: comparing the total citation count of a 2019 work with that of a 2025 work compares seven years of exposure with one, whereas comparing $c^{(36)}$ compares equal exposures. The cost is that the last window-length of the corpus cannot be evaluated; $c^{(36)}$ is complete for publication years up to 2023 given a snapshot taken late in 2026, and $c^{(12)}$ up to 2024. Tables flag the years for which a window is incomplete, and the choice of window length follows the evidence in \citet{wang2013window} that short windows rank works materially differently from long ones in slow-moving fields, which is why two lengths are reported rather than one. \subsection{Field normalisation} Raw citation counts differ across subfields and document types by factors that have nothing to do with influence. The normalised citation score of a work is its window count divided by the mean window count of its reference class \citep{waltman2016review, waltman2019fieldnorm}: \begin{equation} \mathrm{NCS}^{(h)}_w \;=\; \frac{c^{(h)}_w}{\bar c^{(h)}\bigl(y(w), \tau(w), f(w)\bigr)}, \qquad \bar c^{(h)}(y, \tau, f) = \frac{1}{|\mathcal{W}_{y,\tau,f}|}\sum_{v \in \mathcal{W}_{y,\tau,f}} c^{(h)}_v , \label{eq:ncs} \end{equation} where $f(w)$ is the primary OpenAlex subfield of $w$ and $\mathcal{W}_{y,\tau,f}$ the set of eligible works sharing year, type and subfield. The reference class is computed on the eligible corpus, not on all of OpenAlex, so the normalisation is relative to computer science as delimited here: an NCS of 2 means twice the mean of comparable computer-science works, not twice the world mean. The score is undefined when the class mean is zero (very small classes in the most recent years) and is then left missing rather than set to zero. Normalisation by the mean of a heavy-tailed distribution is sensitive to a few very highly cited works in the class; the median-based alternatives discussed by \citet{waltman2016review} are not used because the median of $c^{(36)}$ is zero in many classes of this corpus, which would make them uninformative. OpenAlex's own field-weighted citation impact (FWCI) is kept as a secondary indicator. Its documentation defines it as ``citations received divided by citations expected for works of the same type, year, and subfield'', with a world average of one \citep{openalex2026fwci}. It differs from equation~\eqref{eq:ncs} in three respects: the expected count is computed over all of OpenAlex rather than over this corpus; the citation count is the total to date rather than a fixed window, so that FWCI values of recent works are based on a short and unequal exposure; and the computation is OpenAlex's, recomputed nightly, so that the value depends on the snapshot date. For these reasons FWCI is reported for comparison and never used to select works. \subsection{Inequality and concentration} Citation inequality within a publication year is measured by the Gini coefficient of $c^{(36)}$ among the $n$ eligible works of that year. With the works sorted so that $c_{(1)} \le c_{(2)} \le \dots \le c_{(n)}$, the estimator implemented in SQL is the rank form \begin{equation} G \;=\; \frac{2\sum_{i=1}^{n} i\, c_{(i)}}{n \sum_{i=1}^{n} c_{(i)}} - \frac{n+1}{n}, \label{eq:gini} \end{equation} which equals one minus twice the area under the Lorenz curve and lies in $[0, 1 - 1/n]$; the coefficient is named after \citet{ceriani2012gini}'s account of its origin. Uncited works (a large share within a three-year window) contribute zero to the numerator and pull $G$ upward, so the share of uncited works is reported next to it. The protocol (H5) refers to the Gini of 24-month citations; the implemented statistic uses the three-calendar-year window $c^{(36)}$, which is complete for one more publication year than the longer alternatives and less dominated by zeros than $c^{(12)}$. This is a deviation from the protocol wording and is recorded as such. Venue concentration within a year is the Herfindahl--Hirschman index of the distribution of works over sources, \begin{equation} \mathrm{HHI}_y \;=\; \sum_{v} \sigma_{v,y}^2, \qquad \sigma_{v,y} = \frac{N_{v,y}}{\sum_{v'} N_{v',y}}, \label{eq:hhi} \end{equation} where $N_{v,y}$ is the number of eligible works of year $y$ whose primary source is $v$ \citep{hirschman1964paternity}; works without a source are excluded from the denominator, and the number of distinct sources and the largest single share are reported with the index. Because arXiv is a single OpenAlex source, growth in preprints mechanically raises $\mathrm{HHI}_y$ even when the journal and conference landscape becomes more dispersed; this is the reason the protocol's H5 predicts a stable or falling HHI only ``because of preprint growth'' with the preprint source treated separately, and the tables report the index with and without the preprint type. \subsection{Collaboration, countries and institutions} Team size is summarised by the mean and median number of authors per work and by the shares of single-author works and of works with at least five or ten authors. Two counting conventions are used for countries and institutions, because they answer different questions \citep{waltman2016review}. Under full counting a work contributes one unit to every country among its authors' affiliations; under fractional counting it contributes $1/|K(w)|$ to each of its $|K(w)|$ distinct countries, so that the fractional totals sum to the number of works with at least one country. The same pair of conventions is applied to institutions, with the fraction taken over the distinct institutions of the work. The international collaboration share of year $y$ is \begin{equation} \mathrm{ICS}_y \;=\; \frac{|\{w : y(w)=y,\ |K(w)| \ge 2\}|}{|\{w : y(w)=y,\ |K(w)| \ge 1\}|}, \end{equation} that is, among works with at least one resolved country, the share with authors from two or more countries; works without affiliation data are excluded from the denominator and their share is reported, because affiliation completeness in OpenAlex varies by source and year and a change in completeness would otherwise masquerade as a change in collaboration. The industry share is the share of works with at least one affiliation of OpenAlex institution type \textit{company} among works with at least one typed affiliation. Country-pair and institution-level tables apply minimum-support thresholds (fifty joint works for a country pair, two hundred works for an institution within a period) that keep the released tables to the robustly estimated part of the distribution; these thresholds are reporting choices and are stated in the table notes. \subsection{Diversity indices} \label{sec:m-diversity} Interdisciplinarity is measured on the distribution of a work's references, or of a category's citations, over the categories of the ontology. Let $p = (p_1, \dots, p_K)$ be such a distribution and $\delta_{ij} \in [0,1]$ a dissimilarity between categories $i$ and $j$. The Rao--Stirling index \citep{rao1982diversity, stirling2007diversity} \begin{equation} \Delta_{\mathrm{RS}}(p) \;=\; \sum_{i \ne j} p_i\, p_j\, \delta_{ij} \label{eq:rao-stirling} \end{equation} is the expected dissimilarity between two categories drawn at random from $p$; it is zero when all mass sits on one category and increases with variety (the number of categories present), balance (the evenness of $p$) and disparity (the dissimilarity of the categories involved), the three components that \citeauthor{stirling2007diversity} argues any diversity measure should respond to. Its use in scientometrics follows \citet{rafols2010diversity}. Its known weakness is that it saturates: for very even distributions over many categories it approaches the mean dissimilarity and no longer discriminates \citep{zhang2016diversity}. The Leinster--Cobbold family \citep{leinster2012diversity} repairs this by defining, for a similarity matrix $Z = (z_{ij})$ with $z_{ij} = 1 - \delta_{ij}$ and an order $q \ge 0$, \begin{equation} {}^{q}D^{Z}(p) \;=\; \Bigl( \sum_{i : p_i > 0} p_i\, (Zp)_i^{\,q-1} \Bigr)^{1/(1-q)}, \qquad (Zp)_i = \sum_j z_{ij}\, p_j , \label{eq:leinster-cobbold} \end{equation} with the limit ${}^{1}D^{Z}(p) = \prod_i (Zp)_i^{-p_i}$ at $q = 1$. The quantity $(Zp)_i$ is the ``ordinariness'' of category $i$ under $p$: how much of the distribution is similar to $i$. The index is an effective number of categories---it equals $K$ for the uniform distribution over $K$ mutually dissimilar categories---and the order $q$ sets the weight given to rare categories (large $q$ counts only the dominant ones). Following \citet{zhang2016diversity} the manuscript reports $q = 2$, which has the closed form ${}^{2}D^{Z}(p) = 1 / \sum_{i,j} p_i z_{ij} p_j = 1/(1 - \Delta_{\mathrm{RS}}(p))$ when $z_{ii} = 1$, so that the two families are monotone transforms of each other at this order and differ only in scale and in their behaviour at the saturation end. The dissimilarity $\delta_{ij}$ between categories is one minus the cosine similarity of the category centroids of Section~\ref{sec:m-semantic} in the baseline period, so that the disparity component is estimated from the corpus rather than imposed. The current pipeline computes the category flow matrices from which $p$ is formed (Section~\ref{sec:m-networks}) and the centroid similarities, but the two diversity indices are not yet produced by a script; they are defined here because the protocol commits to them, and their values in Part IX are \pending{Rao--Stirling and Leinster--Cobbold indices per category and period, not yet computed} until the computation is added and audited.