SPB Git

spb/firc0001_uqo

Public

E (exhibits): make_tables.py rewritten — every table a self-contained float (caption, label, threeparttable notes, generated-by comment), 13 new Stage D exhibits (ledger calls, outage, grounding, spec curve, focus, cohort OLS, financing class, 8-K proxy, universe artefacts, time-series cohort, rules baseline, tokens, over-merge), Tables 1-9/12 rebuilt (ledger vs stored, CI column, 100.1 share, longtable), 8 figures to one design system (Okabe-Ito, markers, zero-based axes, integer ticks, cohort series, CIs); 830 \SPID macros incl. the 365 requested by the writing stage, computed from results/ (numbers_pending.tex retired); half-up rounding; render-and-inspect audit (quality_control/_FIRC-0001_*_audit.csv); README exhibit map (EDIT-21..23, ADVE-16, AI_C-16, AI_C-17, LITE-10, LITE-12, ECON-18, THEO-18, EDIT-05, ADVE-06, DATA-04, ECON-13, EDIT-14, ADVE-13, ECON-14, THEO-15, DATA-15, engine audit)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Nov 5, 2026) parent f80b0e6 Browse files

60 changed files +6,212 −1,177

60 changed files
Unified Split
modified README.md +30 −24
@@ -31,28 +31,34 @@ python3 -I -m pytest -q tests # checks only
31 31
32 32 ## Program-to-exhibit map
33 33
34 −| exhibit | generated file | script | inputs |
34 +Every table is a self-contained float written by `make_tables.py` to `paper/tables/<name>.tex` (caption, label, `threeparttable` notes, generated-by comment); every figure is a vector PDF plus a float wrapper `paper/figures/<name>.tex`. The prose files only `\input` them. Labels are `tab:<name without tab_>` and `fig:<name without fig_>`.
35 +
36 +| exhibit (label) | generated file | script | inputs |
35 37 |---|---|---|---|
36 −| Table 1 universe reconciliation | `paper/tables/tab_reconciliation.tex` | `make_tables.py` | `stats.json:universe`, `documented_inputs.json:iwv_equity_lines_reported` |
37 −| Table 2 filings by form | `tab_filings.tex` | `make_tables.py` | `filings_by_form.csv`, `parse_status.csv`, `stats.json` |
38 −| Table 3 sections and ledger (+ note) | `tab_sections.tex`, `tab_sections_note.tex` | `make_tables.py` | `sections_by_form.csv`, `ledger_by_form.csv`, `mentions_by_form.csv`, `results/ledger/table3_ledger_vs_stored.csv`, `results/ledger/ledger_collisions.csv` |
39 −| Table 4 items in scope | `tab_items.tex` | `make_tables.py` | `ledger_10k_items.csv`, `ledger_10q_items.csv`, `results/ledger/gate_pass_by_form_item.csv` |
40 −| Table 5 projects by type (+ note) | `tab_types.tex`, `tab_types_note.tex` | `make_tables.py` | `projects_by_type.csv`, `projects_by_type_ci.csv` (N13), `results/resolver/overmerge_by_type.csv`, `amount_dist.csv` |
41 −| Table 6 by sector | `tab_sectors.tex` | `make_tables.py` | `projects_by_sector.csv`, `companies_by_sector.csv` |
42 −| Table 7 status / mentions / span | `tab_status.tex` | `make_tables.py` | `projects_by_status.csv`, `mentions_per_project.csv`, `duration.csv` |
43 −| Table 8 amounts and projects per issuer (+ note) | `tab_amounts.tex`, `tab_amounts_note.tex` | `make_tables.py` | `amount_dist.csv`, `projects_per_issuer.csv`, `stats.json:amount_*` |
44 −| Table 9 provenance example | `tab_provenance.tex` | `make_tables.py` | `example_provenance.csv`, `documented_inputs.json:snippet_chars` |
45 −| Table 12 data-model audit (longtable) | `tab_datamodel.tex` | `make_tables.py` | `data/datamodel_audit.csv` |
46 −| Tables 14–17 (appendix) | `tab_coverage_year.tex`, `tab_top_issuers.tex`, `tab_confidence.tex`, `tab_graph.tex` | `make_tables.py` | `issuers_by_year.csv`, `filings_by_year_form.csv`, `mentions_by_year.csv`, `projects_by_first_seen_year.csv`, `top_issuers.csv`, `confidence_dist.csv`, `kg.csv` |
47 −| Appendix A taxonomy | `tab_taxonomy.tex` | `make_tables.py` | `code/audit/spid_snapshot/taxonomy.py` |
48 −| Appendix B prompt and gate regex | `prompt_verbatim.tex`, `gate_regex.tex` | `make_tables.py` | `code/audit/spid_snapshot/llm.py`, `rules.py` (read with `ast`, never retyped) |
49 −| Stage D tables (when `results/` is present) | `tab_spec_curve.tex`, `tab_top_name_tokens.tex`, `tab_overmerge.tex`, `tab_june_october.tex`, `tab_table3_calls.tex`, `tab_grounding.tex`, `tab_focus.tex`, `tab_cohort.tex`, `tab_fp_classes.tex`, `tab_timeseries_cohort.tex`, `tab_benchmark_8k.tex`, `tab_rules_agreement.tex` | `make_tables.py` (generic CSV → tabular) | `results/<package>/*.csv` from `code/audit/a*.py` |
50 −| Figure 1 coverage (integer year ticks) | `paper/figures/fig_coverage.pdf` | `make_tables.py` | `issuers_by_year.csv` |
51 −| Figure 3 projects by type | `fig_types.pdf` | `make_tables.py` | `projects_by_type.csv` |
52 −| Figure 4 confidence | `fig_confidence.pdf` | `make_tables.py` | `confidence_dist.csv` |
53 −| Figure 5 mentions and new projects by year (y from 0; second panel per issuer; 2010 / 2026 shaded) | `fig_mentions_year.pdf` | `make_tables.py` | `mentions_by_year.csv`, `projects_by_first_seen_year.csv` |
54 −| Figure 2 pipeline diagram | `fig_pipeline.pdf` | hand-drawn (TikZ/PDF, not generated) | — |
55 −| inline numbers (`\SPID…`) | `paper/tables/numbers.tex`, `results/inline_numbers.json` | `make_tables.py` | all of the above; `results/**.json` (N1, N3, L5) |
56 −| `data/*.csv`, `data/stats.json` | 29 CSV + 3 new (`ledger_collisions`, `cohort_by_run`, `calls_by_form`) + `projects_by_type_ci.csv` | `export_stats.py` (node, read-only) | `edgar_research.duckdb`, `spid.duckdb`, `data/metadata/*.json`, run logs |
57 −
58 −Figure numbers follow the order of `main.tex`; the `.png` copies under `paper/figures/` are not produced by any script and are kept only for the Word export (`code/tex2docx`).
38 +| tab:reconciliation universe reconciliation + Russell coverage | `tab_reconciliation.tex` | `make_tables.py` | `stats.json:universe`, `documented_inputs.json`, `results/russell_coverage.json`, `results/universe/universe_artefacts.json` |
39 +| tab:filings filings by form | `tab_filings.tex` | `make_tables.py` | `filings_by_form.csv`, `parse_status.csv`, `results/universe/filings_status_missing.csv` |
40 +| tab:sections ledger vs stored, calls | `tab_sections.tex` | `make_tables.py` | `sections_by_form.csv`, `ledger_by_form.csv`, `mentions_by_form.csv`, `results/ledger/table3_ledger_vs_stored.csv`, `ledger_collisions.csv` |
41 +| tab:ledger_calls rows / calls / productive by form x run | `tab_ledger_calls.tex` | `make_tables.py` | `results/ledger/gate_pass_by_form_run.csv`, `gate_pass_by_run.csv`, `gate_pass_totals.json` |
42 +| tab:outage outage reconciliation | `tab_outage.tex` | `make_tables.py` | `results/ledger/log_summary.json`, `throughput.json`, `backfill_block.json`, `resume_batch1_vs_expected.csv` |
43 +| tab:items items in scope (+ calls, shown share, financing share) | `tab_items.tex` | `make_tables.py` | `ledger_10k_items.csv`, `ledger_10q_items.csv`, `results/ledger/gate_pass_by_form_item.csv`, `results/focus/`, `results/fp_classes/` |
44 +| tab:fp_classes financing-class mentions | `tab_fp_classes.tex` | `make_tables.py` | `results/fp_classes/*.csv`, `summary.json` |
45 +| tab:focus focus-window coverage | `tab_focus.tex` | `make_tables.py` | `results/focus/focus_coverage_by_form_item.csv`, `_by_form.csv`, `stats_keys.json` |
46 +| tab:types projects by category (+ CI, excl. financing, over-merge) | `tab_types.tex` | `make_tables.py` | `projects_by_type.csv`, `projects_by_type_ci.csv`, `results/fp_classes/table5_restated_excl_financing.csv`, `results/resolver/overmerge_by_type.csv` |
47 +| tab:sectors by sector | `tab_sectors.tex` | `make_tables.py` | `projects_by_sector.csv`, `companies_by_sector.csv` |
48 +| tab:cohort cohort x run, issuer-level OLS | `tab_cohort.tex` | `make_tables.py` | `results/runs/table6_cohort.csv`, `table6_cohort_regression.json` |
49 +| tab:status status / mentions / span | `tab_status.tex` | `make_tables.py` | `projects_by_status.csv`, `mentions_per_project.csv`, `duration.csv`, `results/resolver/ties_idempotence.json` |
50 +| tab:amounts amounts and projects per issuer | `tab_amounts.tex` | `make_tables.py` | `amount_dist.csv`, `projects_per_issuer.csv`, `stats.json:amount_*`, `results/grounding/amount_tail.json` |
51 +| tab:provenance provenance example | `tab_provenance.tex` | `make_tables.py` | `example_provenance.csv`, `documented_inputs.json:snippet_chars`, `results/resolver/composition.json` |
52 +| tab:spec_curve specification curve of the project count | `tab_spec_curve.tex` | `make_tables.py` | `results/resolver/spec_curve.csv`, `composition.json`, `ties_idempotence.json` |
53 +| tab:grounding mechanical grounding | `tab_grounding.tex` | `make_tables.py` | `results/grounding/grounding_by_group.csv`, `grounding_element_level.csv`, `grounding_all_structured.csv`, `fallback_bounds.json` |
54 +| tab:benchmark_8k 8-K item-code consistency | `tab_benchmark_8k.tex` | `make_tables.py` | `results/benchmark_8k/item_vs_type.csv`, `summary.json` |
55 +| tab:rules_agreement rules vs LLM, focus recall bound | `tab_rules_agreement.tex` | `make_tables.py` | `results/rules/agreement_by_form.csv`, `agreement_overall.csv`, `focus_recall_loss.csv` |
56 +| tab:datamodel data-model audit (longtable, no float) | `tab_datamodel.tex` | `make_tables.py` | `data/datamodel_audit.csv` |
57 +| tab:taxonomy, Appendix B prompt and gate regex | `tab_taxonomy.tex`, `prompt_verbatim.tex`, `gate_regex.tex` | `make_tables.py` | `code/audit/spid_snapshot/{taxonomy,llm,rules}.py` (read with `ast`, never retyped) |
58 +| tab:june_october, tab:universe_artefacts, tab:coverage_year, tab:timeseries_cohort, tab:top_issuers, tab:confidence, tab:graph, tab:top_name_tokens, tab:overmerge (appendix) | `tab_<name>.tex` | `make_tables.py` | `results/resolver/`, `results/universe/`, `results/timeseries/`, `data/*.csv` |
59 +| fig:coverage, fig:types, fig:confidence, fig:mentions_year, fig:grounding, fig:spec_curve, fig:focus | `fig_<name>.pdf` + `.png` + `.tex` float | `make_tables.py` (Okabe-Ito palette, markers + line styles, 9 pt serif, width = textwidth) | `data/*.csv`, `results/timeseries/`, `results/grounding/`, `results/resolver/`, `results/focus/` |
60 +| fig:pipeline pipeline diagram | TikZ in `paper/sections/methodology.tex` | hand-drawn (not generated) | counts via `\SPID` macros |
61 +| inline numbers (`\SPID…`) | `paper/tables/numbers.tex`, `results/inline_numbers.json` | `make_tables.py` | all of the above; `results/**.json` |
62 +| `data/*.csv`, `data/stats.json` | 29 CSV + `ledger_collisions`, `cohort_by_run`, `calls_by_form`, `projects_by_type_ci` | `export_stats.py` (node, read-only; `IS DISTINCT FROM` amount_raw check, October wall-clock from the first October flush, deterministic ORDER BY, spill directory outside the repo) | `edgar_research.duckdb`, `spid.duckdb`, `data/metadata/*.json`, run logs |
63 +
64 +Exhibit numbers follow the order of `main.tex`. The `.png` copies under `paper/figures/` are written by `make_tables.py` at `documented_inputs.json:png_dpi` for the Word export (`code/tex2docx`). The render-and-inspect audit of every exhibit is recorded in `UQO-WP-REVIEW/quality_control/_FIRC-0001_{table,figure}_audit.csv`.
modified code/make_tables.py +1541 −273
@@ -1,14 +1,17 @@
1 −"""Build every LaTeX table, figure and inline-number macro of the paper from the exported data.
1 +"""Build every LaTeX exhibit (self-contained table floats, figure floats, PDF figures) and inline-number macro of the paper.
2 2
3 3 Inputs (read-only):
4 4 data/*.csv, data/stats.json exports of code/export_stats.py (node, DuckDB read-only)
5 5 data/documented_inputs.json the few values that no query can reproduce (each with its source)
6 6 data/datamodel_audit.csv rows of the data-model audit table (Appendix C)
7 7 code/audit/spid_snapshot/{llm,rules,taxonomy}.py frozen pipeline snapshot (prompt, gate regex, taxonomy)
8 − results/**/*.csv Stage D audit outputs (optional; tables are skipped when absent)
8 + results/** Stage D audit outputs (optional; the corresponding exhibits are skipped when absent)
9 9 Outputs:
10 − paper/tables/*.tex, paper/figures/*.pdf, paper/tables/numbers.tex (SPID... macros for inline numbers),
11 − results/inline_numbers.json (macro -> value, source, formula), data/example_project.json.
10 + paper/tables/tab_*.tex complete floats (\\begin{table} ... caption, label, threeparttable notes ... \\end{table}); the prose
11 + files only \\input them. tab_datamodel.tex is a longtable (no float).
12 + paper/figures/fig_*.pdf vector figures (Okabe-Ito palette, markers + line styles), fig_*.png copies (Word export),
13 + paper/figures/fig_*.tex figure floats (includegraphics + caption + label),
14 + paper/tables/numbers.tex (\\SPID... macros), results/inline_numbers.json (macro -> value, source, formula), data/example_project.json.
12 15 No numeric literal is typed in this file; stats.json is never rewritten.
13 16 Usage: python3 -I code/make_tables.py [--out SCRATCH_DIR] (--out is used by tests/)
14 17 """
@@ -17,7 +20,7 @@ from pathlib import Path
17 20 import matplotlib
18 21 matplotlib.use("Agg")
19 22 import matplotlib.pyplot as plt
20 −from matplotlib.ticker import MaxNLocator
23 +from matplotlib.ticker import MaxNLocator, FuncFormatter
21 24
22 25 ROOT = Path(__file__).resolve().parent.parent
23 26 ap = argparse.ArgumentParser()
@@ -36,6 +39,7 @@ for p in (T, F, RES_OUT, DATA_OUT):
36 39 S = json.load(open(D / "stats.json")) # read-only
37 40 DI = json.load(open(D / "documented_inputs.json")) if (D / "documented_inputs.json").exists() else {}
38 41 INLINE = {} # macro -> {value, source, formula}
42 +GEN = "code/make\\_tables.py"
39 43
40 44
41 45 def rows(name, base=D):
@@ -43,9 +47,27 @@ def rows(name, base=D):
43 47 return list(csv.DictReader(f))
44 48
45 49
50 +def rel(p):
51 + try:
52 + return str(p.relative_to(ROOT))
53 + except ValueError:
54 + return str(p)
55 +
56 +
57 +from decimal import Decimal, ROUND_HALF_UP
58 +
59 +
60 +def hr(x, d=0):
61 + """Half-up rounding on the decimal representation (what a reader does by hand); avoids 5.35 -> 5.3 float artefacts."""
62 + return Decimal(str(x)).quantize(Decimal(1).scaleb(-d), rounding=ROUND_HALF_UP)
63 +
64 +
46 65 def n(x, d=0):
47 − x = float(x)
48 − return f"{x:,.{d}f}".replace(",", "{,}")
66 + return f"{hr(float(x), d):,.{d}f}".replace(",", "{,}")
67 +
68 +
69 +def pct(x, d=1):
70 + return f"{hr(float(x), d):.{d}f}"
49 71
50 72
51 73 def w(name, body):
@@ -58,6 +80,40 @@ def esc(s):
58 80 .replace("$", "\\$").replace("_", "\\_").replace("#", "\\#"))
59 81
60 82
83 +def tt(s):
84 + return "\\texttt{" + str(s).replace("_", "\\_") + "}"
85 +
86 +
87 +def ttb(s):
88 + """Monospace name that may break after underscores or dots (for narrow p-columns)."""
89 + return "\\texttt{" + str(s).replace("_", "\\_\\allowbreak{}").replace(".", ".\\allowbreak{}") + "}"
90 +
91 +
92 +def H(text):
93 + """Multi-line, centred column header (makecell); lines separated by '\\\\'."""
94 + return "\\multicolumn{1}{c}{\\makecell{" + text + "}}"
95 +
96 +
97 +def float_table(fname, label, caption, tabular, notes, inputs, size="\\small", colsep=None, placement="H", fit=False):
98 + """Write a self-contained float: generated-by comment, caption, label, threeparttable with notes.
99 + fit=True wraps the tabular (never the notes) in an adjustbox that scales it down only if it exceeds \\textwidth."""
100 + pre = f"\\setlength{{\\tabcolsep}}{{{colsep}}}\n" if colsep else ""
101 + if fit: tabular = "\\begin{adjustbox}{max width=\\textwidth}\n" + tabular + "\n\\end{adjustbox}"
102 + body = (f"% Generated by code/make_tables.py from {inputs}. Do not edit by hand.\n"
103 + f"\\begin{{table}}[{placement}]\n\\centering{size}\n{pre}\\caption{{{caption}}}\\label{{{label}}}\n"
104 + f"\\begin{{threeparttable}}\n{tabular}\n"
105 + f"\\begin{{tablenotes}}\\footnotesize\n\\item {notes}\n\\end{{tablenotes}}\n\\end{{threeparttable}}\n\\end{{table}}\n")
106 + w(fname, body)
107 +
108 +
109 +def float_figure(fname, label, caption, pdf, inputs, width="\\textwidth"):
110 + body = (f"% Generated by code/make_tables.py from {inputs}. Do not edit by hand.\n"
111 + f"\\begin{{figure}}[H]\n\\centering\n\\includegraphics[width={width}]{{figures/{pdf}}}\n"
112 + f"\\caption{{{caption}}}\\label{{{label}}}\n\\end{{figure}}\n")
113 + (F / fname).write_text(body)
114 + print("figure float", fname)
115 +
116 +
61 117 _DIGITS = {"0": "Zero", "1": "One", "2": "Two", "3": "Three", "4": "Four", "5": "Five", "6": "Six", "7": "Seven", "8": "Eight", "9": "Nine"}
62 118
63 119
@@ -68,7 +124,6 @@ def macro(name, value, source, formula):
68 124
69 125
70 126 def di(key):
71 − """Documented input (value + source) or None."""
72 127 e = DI.get(key)
73 128 return None if e is None else e.get("value")
74 129
@@ -78,6 +133,11 @@ def di_source(key):
78 133 return "" if e is None else e.get("source", "")
79 134
80 135
136 +def jload(rel_path):
137 + p = R / rel_path
138 + return json.load(open(p)) if p.exists() else {}
139 +
140 +
81 141 LAB = {"ma_integration": "M\\&A / integration", "capex_program": "Capital expenditure program", "partnership": "Strategic partnership",
82 142 "geographic_expansion": "Geographic expansion", "plant_construction": "Plant / site construction", "cost_reduction": "Cost reduction / restructuring",
83 143 "drug_pipeline": "Drug / clinical pipeline", "product_launch": "New product / launch", "rd_program": "R\\&D program",
@@ -85,11 +145,12 @@ LAB = {"ma_integration": "M\\&A / integration", "capex_program": "Capital expend
85 145 "technology_deployment": "Technology deployment", "digital_transformation": "Digital transformation", "erp_implementation": "ERP / systems implementation",
86 146 "sustainability": "Sustainability / ESG", "supply_chain": "Supply-chain initiative", "data_center": "Data center", "energy_transition": "Energy transition / renewables",
87 147 "ai_initiative": "AI / ML initiative", "automation": "Automation / robotics", "cloud_migration": "Cloud migration"}
148 +RUNLAB = {"backfilled_june": "June run (backfilled)", "october": "October run"}
149 +P = S["projects"]; M = S["mentions"]
88 150
89 −# ---- Table 1: universe reconciliation ----------------------------------------
151 +# ---- Table 1: universe reconciliation (+ Russell coverage and artefact hashes) ---------------------------------
90 152 U = S["universe"]
91 −iwv_lines = S.get("iwv_equity_lines") # exported by export_stats.py when the holdings file is archived
92 −iwv_src = "stats.json:iwv_equity_lines (export_stats.py)"
153 +iwv_lines = S.get("iwv_equity_lines"); iwv_src = "stats.json:iwv_equity_lines (export_stats.py)"
93 154 if iwv_lines is None:
94 155 iwv_lines = di("iwv_equity_lines_reported"); iwv_src = di_source("iwv_equity_lines_reported")
95 156 if iwv_lines is not None:
@@ -102,7 +163,20 @@ else:
102 163 row1_val = "--"
103 164 macro("iwvEquityLines", row1_val, iwv_src, "documented input or stats.json")
104 165 sp500_ciks = S.get("sp500_ciks", U.get("n_sp500"))
105 −w("tab_reconciliation.tex", f"""\\begin{{tabular}}{{lr}}
166 +rc = json.load(open(R / "russell_coverage.json")) if (R / "russell_coverage.json").exists() else {}
167 +ua = jload("universe/universe_artefacts.json")
168 +cov_rows = ""
169 +if rc.get("index_constituents") is not None:
170 + cov = 100.0 * U["russell_distinct_ciks"] / rc["index_constituents"]
171 + macro("russellIndexConstituents", n(rc["index_constituents"]), "results/russell_coverage.json:index_constituents", rc.get("source_url", ""))
172 + macro("russellProxyCoveragePct", f"{cov:.1f}", "results/russell_coverage.json", "100 * russell_distinct_ciks / index_constituents")
173 + cov_rows = (f"\\midrule\nRussell~3000 index constituents, FTSE Russell factsheet as of {rc.get('index_as_of', '')} & {n(rc['index_constituents'])} \\\\\n"
174 + f"\\quad coverage of the index by the proxy (distinct CIKs / constituents, \\%) & {cov:.1f} \\\\\n")
175 +if rc.get("fund_holdings_count") is not None:
176 + macro("iwvHoldingsCount", n(rc["fund_holdings_count"]), "results/russell_coverage.json:fund_holdings_count", rc.get("fund_source_url", ""))
177 +if rc.get("replication_method"):
178 + macro("iwvReplicationMethod", esc(rc["replication_method"]), "results/russell_coverage.json:replication_method", rc.get("fund_source_url", ""))
179 +tab = f"""\\begin{{tabular}}{{p{{11.6cm}}r}}
106 180 \\toprule
107 181 Step & Count \\\\
108 182 \\midrule
@@ -115,30 +189,55 @@ Merged issuer universe (distinct CIKs) & {n(U['n'])} \\\\
115 189 \\quad in both lists & {n(U['both'])} \\\\
116 190 \\quad S\\&P~500 only & {n(U['sp_only'])} \\\\
117 191 \\quad Russell proxy only & {n(U['ru_only'])} \\\\
118 −\\midrule
192 +{cov_rows}\\midrule
119 193 Issuers with at least one 10-K, 10-Q or 8-K since 2010 & {n(S['issuers_with_filings'])} \\\\
120 194 Issuers without any such filing (foreign private issuers filing 20-F/40-F, FDIC-only banks) & {n(S['issuers_without_filings'])} \\\\
121 195 Issuers with at least one resolved project & {n(S['issuers_with_projects'])} \\\\
122 196 \\bottomrule
123 −\\end{{tabular}}""")
197 +\\end{{tabular}}"""
198 +hashes = ua.get("sha256", {})
199 +hash_txt = "; ".join(f"\\texttt{{{esc(k)}}} {v['sha256'][:12]}\\ldots" for k, v in hashes.items() if k in ("universe.json", "russell3000_constituents.json", "sp500_constituents.json"))
200 +unm = U.get("russell_unmatched_list", [])
201 +note1 = (f"Sources: \\texttt{{data/metadata/universe.json}}, \\texttt{{russell3000\\_constituents.json}}, \\texttt{{sp500\\_constituents.json}} "
202 + f"(SHA-256 prefixes: {hash_txt}; full digests in Table~\\ref{{tab:universe_artefacts}}) and the merged DuckDB database. "
203 + f"The first row is the count reported by the build log of \\texttt{{scripts/build\\_universe.py}}; the iShares holdings file and the SEC "
204 + f"\\texttt{{company\\_tickers.json}} used by the build were not archived, so this count and the dropped non-company lines are not reconstructible "
205 + f"(Section~\\ref{{sec:sample}}). The mapped lines collapse to fewer CIKs because {n(U['russell_equity_lines_mapped'] - U['russell_distinct_ciks'])} dual-class "
206 + f"registrants appear twice; {n(U['russell_unmatched'])} tickers have no CIK in the SEC map ({esc(', '.join(x.split(' ')[0] for x in unm))}). "
207 + + (f"The index count is the ``Number of Holdings'' of the FTSE Russell factsheet (SHA-256 {rc.get('source_sha256', '')[:12]}\\ldots); the fund tracks the index by "
208 + f"{esc(rc.get('replication_method', ''))}, so the omitted constituents cannot be identified without the licensed constituent list. " if rc.get("index_constituents") else "")
209 + + f"The {n(S['issuers_without_filings'])} issuers without filings are listed in \\texttt{{data/issuers\\_without\\_filings.csv}} (foreign private issuers filing "
210 + f"Forms 20-F/40-F and banks filing with the FDIC); {n(S['issuers_with_filings'] - S['issuers_with_projects'])} issuers have filings but no resolved project.")
211 +float_table("tab_reconciliation.tex", "tab:reconciliation", "Universe-to-dataset reconciliation: from the two constituent lists to issuers with resolved projects",
212 + tab, note1, "data/stats.json (universe), data/documented\\_inputs.json, results/russell\\_coverage.json, results/universe/universe\\_artefacts.json")
124 213 macro("universeN", n(U["n"]), "stats.json:universe.n", "count")
125 214 macro("russellDistinctCiks", n(U["russell_distinct_ciks"]), "stats.json:universe.russell_distinct_ciks", "count")
126 215 macro("russellMappedLines", n(U["russell_equity_lines_mapped"]), "stats.json:universe.russell_equity_lines_mapped", "count")
127 216 macro("russellUnmatched", n(U["russell_unmatched"]), "stats.json:universe.russell_unmatched", "len(unmatched)")
128 −# Russell 3000 coverage of the proxy (L5): only if results/russell_coverage.json holds a retrieved constituent count
129 −rc_path = R / "russell_coverage.json"
130 −if rc_path.exists():
131 − rc = json.load(open(rc_path))
132 − if rc.get("index_constituents") is not None:
133 − cov = 100.0 * U["russell_distinct_ciks"] / rc["index_constituents"]
134 − macro("russellIndexConstituents", n(rc["index_constituents"]), "results/russell_coverage.json:index_constituents", rc.get("source_url", ""))
135 − macro("russellProxyCoveragePct", f"{cov:.1f}", "results/russell_coverage.json", "100 * russell_distinct_ciks / index_constituents")
136 − if rc.get("fund_holdings_count") is not None:
137 − macro("iwvHoldingsCount", n(rc["fund_holdings_count"]), "results/russell_coverage.json:fund_holdings_count", rc.get("fund_source_url", ""))
138 − if rc.get("replication_method"):
139 − macro("iwvReplicationMethod", esc(rc["replication_method"]), "results/russell_coverage.json:replication_method", rc.get("fund_source_url", ""))
140 −
141 −# ---- Table 2: filings by form --------------------------------------------------
217 +macro("russellDualClassCiks", n(U["russell_equity_lines_mapped"] - U["russell_distinct_ciks"]), "stats.json:universe", "mapped lines - distinct CIKs")
218 +
219 +# ---- universe artefacts with hashes (appendix) -------------------------------------------------------------------
220 +if hashes:
221 + shipped = {"universe.json", "russell3000_constituents.json", "sp500_constituents.json"}
222 + tab = "\\begin{tabular}{p{3.4cm}p{5.5cm}rp{2.9cm}}\n\\toprule\nArtefact & SHA-256 & Bytes & Shipped with the paper \\\\\n\\midrule\n"
223 + for k, v in hashes.items():
224 + tab += f"{ttb(k)} & \\texttt{{\\scriptsize {v['sha256'][:32]}}} \\texttt{{\\scriptsize {v['sha256'][32:]}}} & {n(v['bytes'])} & {'yes (data/metadata/)' if k in shipped else 'no (hash only)'} \\\\\n"
225 + if rc.get("source_sha256"):
226 + tab += f"FTSE Russell factsheet ({rc.get('index_as_of', '')}) & \\texttt{{\\scriptsize {rc['source_sha256'][:32]}}} \\texttt{{\\scriptsize {rc['source_sha256'][32:]}}} & -- & no (public URL) \\\\\n"
227 + md = rc.get("methodology_document", {})
228 + if md.get("sha256"):
229 + tab += f"Russell US indexes methodology (v7.2) & \\texttt{{\\scriptsize {md['sha256'][:32]}}} \\texttt{{\\scriptsize {md['sha256'][32:]}}} & -- & no (public URL) \\\\\n"
230 + nf = ", ".join(ua.get("holdings_or_company_tickers_files_found", [])) or "none"
231 + tab += "\\bottomrule\n\\end{tabular}"
232 + float_table("tab_universe_artefacts.tex", "tab:universe_artefacts", "Universe artefacts: file digests computed on the master node and release status",
233 + tab, f"Digests computed read-only on the master node (\\texttt{{results/universe/SHA256SUMS}}); the three constituent files are shipped under "
234 + f"\\texttt{{data/metadata/}}. The iShares holdings CSV and the SEC \\texttt{{company\\_tickers.json}} consumed by the build were searched for on the node and not "
235 + f"found ({esc(nf)}): gate (a) of Table~\\ref{{tab:gates}} is met for the frozen JSON artefacts only, not for their upstream sources. "
236 + "\\texttt{cik\\_mapping.json} and \\texttt{shards.json} are hashed but not released (the latter names private cluster nodes); the URLs of the two public "
237 + "FTSE Russell documents are recorded in \\texttt{results/russell\\_coverage.json}.",
238 + "results/universe/universe\\_artefacts.json, results/russell\\_coverage.json", size="\\footnotesize", colsep="3pt", fit=True)
239 +
240 +# ---- Table 2: filings by form --------------------------------------------------------------------------------
142 241 fb = rows("filings_by_form"); ps = rows("parse_status")
143 242 err = {}
144 243 for r in ps:
@@ -146,34 +245,55 @@ for r in ps:
146 245 fdr = S.get("filing_date_range") or [min(r["first"] for r in fb), max(r["last"] for r in fb)]
147 246 macro("filingDateFirst", fdr[0], "stats.json:filing_date_range or min(filings_by_form.first)", "min")
148 247 macro("filingDateLast", fdr[1], "stats.json:filing_date_range or max(filings_by_form.last)", "max")
149 −body = "\\begin{tabular}{lrrrrr}\n\\toprule\nForm & Filings & First filing & Last filing & Raw HTML (GB) & Not parsed \\\\\n\\midrule\n"
248 +tab = "\\begin{tabular}{lrrrrrr}\n\\toprule\nForm & Filings & First filing & Last filing & Raw HTML (GB) & Parser error & Missing on disk \\\\\n\\midrule\n"
150 249 for r in fb:
151 − e = err.get(r["form_type"], {}); notp = e.get("error", 0) + e.get("missing", 0)
152 − body += f"{r['form_type']} & {n(r['n'])} & {r['first']} & {r['last']} & {float(r['gb']):.1f} & {notp} \\\\\n"
250 + e = err.get(r["form_type"], {})
251 + tab += f"{r['form_type']} & {n(r['n'])} & {r['first']} & {r['last']} & {float(r['gb']):.1f} & {e.get('error', 0)} & {e.get('missing', 0)} \\\\\n"
153 252 not_parsed = sum(e.get("error", 0) + e.get("missing", 0) for e in err.values())
154 −missing = sum(e.get("missing", 0) for e in err.values())
155 −body += f"\\midrule\nTotal & {n(S['filings_total'])} & {fdr[0]} & {fdr[1]} & {S['raw_gb']:.1f} & {not_parsed} \\\\\n\\bottomrule\n\\end{{tabular}}"
156 −w("tab_filings.tex", body)
253 +missing = sum(e.get("missing", 0) for e in err.values()); perr = sum(e.get("error", 0) for e in err.values())
254 +tab += f"\\midrule\nTotal & {n(S['filings_total'])} & {fdr[0]} & {fdr[1]} & {S['raw_gb']:.1f} & {perr} & {missing} \\\\\n\\bottomrule\n\\end{{tabular}}"
255 +fsm = R / "universe" / "filings_status_missing.csv"
256 +miss_note = ""
257 +if fsm.exists():
258 + fm = rows(fsm.stem, fsm.parent)
259 + mrows = [r for r in fm if r.get("parse_status") == "missing" or r.get("download_status") == "missing"]
260 + erows = [r for r in fm if r.get("parse_status") == "error"]
261 + miss_note = (f" The {len(erows)} parser errors and {len(mrows)} documents logged as downloaded but absent on disk are listed by accession number in "
262 + f"\\texttt{{results/universe/filings\\_status\\_missing.csv}} (parser errors: {esc(', '.join(sorted({r['ticker'] for r in erows})))}; "
263 + f"missing: {esc(', '.join(r['ticker'] + ' ' + r['form_type'] + ' ' + r['filing_date'][:4] for r in mrows))}).")
264 +float_table("tab_filings.tex", "tab:filings", f"Filings in the corpus by form, {fdr[0]} to {fdr[1]}", tab,
265 + "Primary documents of Forms 10-K, 10-Q and 8-K retained from the SEC submissions index of every issuer of Table~\\ref{tab:reconciliation}. "
266 + "``Parser error'' counts documents whose primary document could not be cleaned; ``missing on disk'' counts documents logged as downloaded "
267 + "but not found at parse time. Raw HTML size is the sum of primary-document sizes recorded at download time." + miss_note,
268 + "data/filings\\_by\\_form.csv, data/parse\\_status.csv, data/stats.json, results/universe/filings\\_status\\_missing.csv")
157 269 macro("filingsTotal", n(S["filings_total"]), "stats.json:filings_total", "count")
158 270 macro("filingsNotParsed", str(not_parsed), "data/parse_status.csv", "sum(error)+sum(missing)")
159 271 macro("filingsMissingOnDisk", str(missing), "data/parse_status.csv", "sum(missing)")
272 +macro("filingsParserError", str(perr), "data/parse_status.csv", "sum(error)")
160 273 macro("rawGb", f"{S['raw_gb']:.1f}", "stats.json:raw_gb", "sum(file_size_bytes)/1e9")
161 274
162 −# ---- Table: coverage by year ----------------------------------------------------
275 +# ---- Table: coverage by year (appendix) ------------------------------------------------------------------------
163 276 iy = rows("issuers_by_year"); fy = rows("filings_by_year_form")
164 277 py = {r["yr"]: r for r in rows("projects_by_first_seen_year")}; my = {r["yr"]: r for r in rows("mentions_by_year")}
165 278 byf = {}
166 279 for r in fy: byf.setdefault(r["yr"], {})[r["form_type"]] = r["n"]
167 −body = "\\begin{tabular}{lrrrrrrrr}\n\\toprule\nYear & Issuers & 10-K & 10-Q & 8-K & Mentions & Issuers w/ mentions & Mentions per issuer & Projects first seen \\\\\n\\midrule\n"
280 +tab = ("\\begin{tabular}{lrrrrrrrr}\n\\toprule\nYear & Issuers filing & 10-K & 10-Q & 8-K & Mentions stored & " + H("Issuers with\\\\$\\geq 1$ mention") +
281 + " & " + H("Mentions per\\\\issuer with mention") + " & " + H("Projects\\\\first seen") + " \\\\\n\\midrule\n")
168 282 for r in iy:
169 283 y = r["yr"]; b = byf[y]; mpi = int(my[y]["mentions"]) / int(my[y]["issuers"])
170 − body += f"{y} & {n(r['issuers'])} & {n(b['10-K'])} & {n(b['10-Q'])} & {n(b['8-K'])} & {n(my[y]['mentions'])} & {n(my[y]['issuers'])} & {mpi:.1f} & {n(py[y]['n'])} \\\\\n"
171 −body += "\\bottomrule\n\\end{tabular}"
172 −w("tab_coverage_year.tex", body)
284 + tab += f"{y} & {n(r['issuers'])} & {n(b['10-K'])} & {n(b['10-Q'])} & {n(b['8-K'])} & {n(my[y]['mentions'])} & {n(my[y]['issuers'])} & {mpi:.1f} & {n(py[y]['n'])} \\\\\n"
285 +tab += "\\bottomrule\n\\end{tabular}"
173 286 yrs_all = sorted(int(r["yr"]) for r in iy)
174 287 y_first, y_last = yrs_all[0], yrs_all[-1]
175 −inner = [y for y in yrs_all if y_first < y < y_last] # exclude the left-censored first year and the partial last year
288 +inner = [y for y in yrs_all if y_first < y < y_last]
176 289 fs_inner = [int(py[str(y)]["n"]) for y in inner]
290 +float_table("tab_coverage_year.tex", "tab:coverage_year", "Issuers, filings, stored mentions and projects first seen, by filing year", tab,
291 + f"Filing year of the document. {y_first} is left-censored (a project already under way before the corpus start is ``first seen'' at its first in-window "
292 + f"filing) and {y_last} is partial (filings to {fdr[1]}); the range quoted in the text, {n(min(fs_inner))}--{n(max(fs_inner))} projects first seen per year, "
293 + f"covers {inner[0]}--{inner[-1]} only. ``Projects first seen'' counts projects under the current resolution key whose earliest mention falls in the year "
294 + f"(Table~\\ref{{tab:timeseries_cohort}} holds the issuer-cohort and windowed-key series). Issuers filing rise mechanically under the snapshot design "
295 + "(Section~\\ref{sec:sample}).", "data/issuers\\_by\\_year.csv, filings\\_by\\_year\\_form.csv, mentions\\_by\\_year.csv, projects\\_by\\_first\\_seen\\_year.csv",
296 + size="\\footnotesize", colsep="3pt", fit=True)
177 297 macro("firstSeenYearMin", str(inner[0]), "data/projects_by_first_seen_year.csv", "first full year after the left-censored start")
178 298 macro("firstSeenYearMax", str(inner[-1]), "data/projects_by_first_seen_year.csv", "last full year before the partial final year")
179 299 macro("firstSeenRangeInner", f"{n(min(fs_inner))}--{n(max(fs_inner))}", "data/projects_by_first_seen_year.csv", f"min/max of projects first seen, {inner[0]}--{inner[-1]}")
@@ -186,32 +306,36 @@ macro("issuersWithMentionsLastFullYear", n(my[str(inner[-1])]["issuers"]), "data
186 306 macro("mentionsPerIssuerFirstYear", f"{int(my[str(y_first)]['mentions'])/int(my[str(y_first)]['issuers']):.1f}", "data/mentions_by_year.csv", "mentions/issuers")
187 307 macro("mentionsPerIssuerLastFullYear", f"{int(my[str(inner[-1])]['mentions'])/int(my[str(inner[-1])]['issuers']):.1f}", "data/mentions_by_year.csv", "mentions/issuers")
188 308 macro("lastYear", str(y_last), "data/issuers_by_year.csv", "max year (partial)")
309 +macro("issuersFilingFirstYear", n(iy[0]["issuers"]), "data/issuers_by_year.csv", f"issuers in {y_first}")
310 +macro("issuersFilingLastYear", n(iy[-1]["issuers"]), "data/issuers_by_year.csv", f"issuers in {y_last}")
189 311
190 −# ---- Table 3: sections and extraction ledger -----------------------------------
312 +# ---- Table 3: sections and extraction ledger (ledger vs stored, calls) ------------------------------------------
191 313 sb = {r["form_type"]: r for r in rows("sections_by_form")}; lb = rows("ledger_by_form")
192 314 mf = {r["form_type"]: int(r["n"]) for r in rows("mentions_by_form")}
193 315 calls = {}
194 316 t3 = R / "ledger" / "table3_ledger_vs_stored.csv"
195 317 if t3.exists():
196 318 calls = {r["form_type"]: int(float(r["calls"])) for r in rows(t3.stem, t3.parent) if r.get("calls")}
197 −cc = " & Gate-passing calls" if calls else ""
198 −body = ("\\begin{tabular}{lrrrr" + ("r" if calls else "") + "rrr}\n\\toprule\nForm & Parsed sections & Median words & Ledgered sections ($\\geq$ 30 words)" + cc + " & "
199 − "Sections with $\\geq 1$ mention & Mentions returned by the model (ledger) & Mentions stored & Issuers \\\\\n\\midrule\n")
319 +elif S.get("calls_by_form"):
320 + calls = dict(S["calls_by_form"])
321 +cc = (" & " + H("Gate-passing\\\\calls")) if calls else ""
322 +tab = ("\\begin{tabular}{l" + "r" * (8 if calls else 7) + "}\n\\toprule\nForm & " + H("Parsed\\\\sections") + " & " + H("Median\\\\words") + " & " +
323 + H("Ledgered rows\\\\($\\geq 30$ words)") + cc + " & " + H("Sections with\\\\$\\geq 1$ mention") + " & " + H("Mentions returned\\\\(ledger, before de-dup.)") +
324 + " & " + H("Mentions\\\\stored") + " & " + H("Issuers\\\\ledgered") + " \\\\\n\\midrule\n")
200 325 tot = [0, 0, 0, 0, 0]; gap_by_form = {}
201 326 for r in lb:
202 327 s = sb[r["form_type"]]; stored = mf[r["form_type"]]
203 328 gap_by_form[r["form_type"]] = int(r["mentions"]) - stored
204 329 cv = f" & {n(calls[r['form_type']])}" if calls else ""
205 − body += (f"{r['form_type']} & {n(s['sections'])} & {n(s['median_words'])} & {n(r['sections'])}{cv} & {n(r['with_mentions'])} & "
206 − f"{n(r['mentions'])} & {n(stored)} & {n(r['issuers'])} \\\\\n")
330 + tab += (f"{r['form_type']} & {n(s['sections'])} & {n(s['median_words'])} & {n(r['sections'])}{cv} & {n(r['with_mentions'])} & "
331 + f"{n(r['mentions'])} & {n(stored)} & {n(r['issuers'])} \\\\\n")
207 332 tot[0] += int(s["sections"]); tot[1] += int(r["sections"]); tot[2] += int(r["with_mentions"]); tot[3] += int(r["mentions"]); tot[4] += stored
208 333 ctot = f" & {n(sum(calls.values()))}" if calls else ""
209 −body += (f"\\midrule\nTotal & {n(tot[0])} & & {n(tot[1])}{ctot} & {n(tot[2])} & {n(tot[3])} & {n(tot[4])} & {n(S['issuers_with_filings'])}$^{{\\dagger}}$ \\\\\n"
210 − "\\bottomrule\n\\end{tabular}")
334 +tab += (f"\\midrule\nTotal & {n(tot[0])} & & {n(tot[1])}{ctot} & {n(tot[2])} & {n(tot[3])} & {n(tot[4])} & {n(S['issuers_with_filings'])}$^{{\\dagger}}$ \\\\\n"
335 + "\\bottomrule\n\\end{tabular}")
211 336 if calls:
212 337 for ft, v in calls.items():
213 338 macro(f"calls{ft}", n(v), "results/ledger/table3_ledger_vs_stored.csv", f"calls where form_type={ft}")
214 −w("tab_sections.tex", body)
215 339 ledger_gap = tot[3] - tot[4]
216 340 gap_txt = ", ".join(f"{k} {v}" for k, v in gap_by_form.items())
217 341 coll_sections = None
@@ -220,17 +344,19 @@ for cand in (R / "ledger" / "ledger_collisions.csv", D / "ledger_collisions.csv"
220 344 with open(cand, newline="") as f:
221 345 coll_sections = sum(1 for _ in csv.DictReader(f))
222 346 break
223 −note = (f"\\item ``Ledgered sections'' counts rows of the \\texttt{{extracted\\_sections}} ledger (sections with at least 30 words; "
224 − f"for 10-Ks restricted to the items of Table~\\ref{{tab:items}}); the ledger does not record whether the candidate gate "
225 − f"passed or whether the API call succeeded, so this is not a count of calls"
226 − + (f"; ``Gate-passing calls'' recomputes the candidate gate of Appendix~\\ref{{app:prompt}} over the ledgered text ({n(sum(calls.values()))} sections reached the model)" if calls else "")
227 − + ". ``Mentions returned by the model'' is "
228 − f"$\\sum$\\texttt{{n\\_mentions}} over the ledger ({n(tot[3])}); ``Mentions stored'' is the row count of "
229 − f"\\texttt{{project\\_mentions}} ({n(tot[4])}). The difference of {n(ledger_gap)} ({gap_txt})"
230 − + (f", spread over {n(coll_sections)} sections," if coll_sections else "")
231 − + " is the number of mentions overwritten by mention-identifier collisions before storage (Section~\\ref{sec:construct}). "
232 − f"$^{{\\dagger}}$Issuers with at least one filing of any form, not a column sum.\n")
233 −w("tab_sections_note.tex", note)
347 +note3 = (f"``Ledgered rows'' counts rows of the \\texttt{{extracted\\_sections}} ledger (parsed sections with at least 30 words; for 10-Ks restricted to the items of "
348 + f"Table~\\ref{{tab:items}}); the ledger records neither whether the candidate gate passed nor whether the API call succeeded, so it is not a count of calls"
349 + + (f". ``Gate-passing calls'' recomputes the candidate gate of Appendix~\\ref{{app:prompt}} over the ledgered text: {n(sum(calls.values()))} sections reached the "
350 + f"model and {n(jload('ledger/gate_pass_totals.json').get('gate_rejected_zero', tot[1] - sum(calls.values())))} were ledgered with zero mentions without a call (Table~\\ref{{tab:ledger_calls}} splits them by run)" if calls else "")
351 + + f". ``Mentions returned'' is $\\sum$\\texttt{{n\\_mentions}} over the ledger ({n(tot[3])}); ``Mentions stored'' is the row count of "
352 + f"\\texttt{{project\\_mentions}} ({n(tot[4])}). The difference of {n(ledger_gap)} ({gap_txt})"
353 + + (f", spread over {n(coll_sections)} sections," if coll_sections else "")
354 + + " is the number of mentions overwritten before storage because the mention identifier hashes the type and the first 40 characters of the project name "
355 + "(Section~\\ref{sec:construct}); every count in the text uses the stored basis unless labelled ``ledger''. "
356 + f"$^{{\\dagger}}$Issuers with at least one filing of any form, not a column sum.")
357 +float_table("tab_sections.tex", "tab:sections", "Parsed sections, extraction ledger, gate-passing calls and mentions, by form", tab, note3,
358 + "data/sections\\_by\\_form.csv, ledger\\_by\\_form.csv, mentions\\_by\\_form.csv, results/ledger/table3\\_ledger\\_vs\\_stored.csv, ledger\\_collisions.csv",
359 + size="\\scriptsize", colsep="3pt", fit=True)
234 360 macro("ledgerTotal", n(S["ledger_total"]), "stats.json:ledger_total", "count(extracted_sections)")
235 361 macro("ledgerMentionsReturned", n(tot[3]), "data/ledger_by_form.csv", "sum(mentions)")
236 362 macro("ledgerGap", n(ledger_gap), "data/ledger_by_form.csv, data/mentions_by_form.csv", "sum(ledger mentions) - sum(stored mentions)")
@@ -246,91 +372,213 @@ macro("productiveSections", n(productive), "data/ledger_by_form.csv", "sum(with_
246 372 macro("productiveShareLedger", f"{100*productive/S['ledger_total']:.1f}", "data/ledger_by_form.csv, stats.json", "100*productive/ledger_total")
247 373 macro("mentionsPerLedgerSection", f"{S['mentions']/S['ledger_total']:.2f}", "stats.json", "mentions/ledger_total")
248 374 macro("mentionsPerProductiveSection", f"{S['mentions']/productive:.2f}", "stats.json, data/ledger_by_form.csv", "mentions/productive")
249 −gate_total = S.get("gate_pass_total")
250 −gt_path = R / "ledger" / "gate_pass_totals.json"
251 −if not gate_total and gt_path.exists():
252 − gt = json.load(open(gt_path))
253 − gate_total = next((gt[k] for k in ("calls", "gate_pass", "calls_total", "gate_pass_total") if isinstance(gt.get(k), (int, float))), None)
375 +gt = jload("ledger/gate_pass_totals.json")
376 +# true call denominator = gate pass AND >= 30 words (N1 'calls'); stats.json:gate_pass_total counts the gate alone (includes 12 backfilled rows under 30 words)
377 +gate_total = gt.get("calls") if isinstance(gt.get("calls"), (int, float)) else S.get("gate_pass_total")
254 378 if gate_total:
255 379 g = gate_total
256 − S = dict(S); S["gate_pass_total"] = g # local copy only; stats.json is never written
257 − macro("gatePassTotal", n(g), "stats.json:gate_pass_total", "regexp_matches(_PROJECT_GATE) over the ledger")
258 − macro("productiveShareCalls", f"{100*productive/g:.1f}", "stats.json:gate_pass_total", "100*productive/gate_pass_total")
259 − macro("mentionsPerCall", f"{S['mentions']/g:.2f}", "stats.json:gate_pass_total", "mentions/gate_pass_total")
380 + macro("gatePassTotal", n(g), "results/ledger/gate_pass_totals.json:calls or stats.json:gate_pass_total", "gate-passing rows with >= 30 words (true calls)")
381 + macro("productiveShareCalls", f"{100*productive/g:.1f}", "results/ledger/gate_pass_totals.json", "100*productive/calls")
382 + macro("mentionsPerCall", f"{S['mentions']/g:.2f}", "results/ledger/gate_pass_totals.json", "mentions/calls")
383 + if S.get("gate_pass_total"): macro("gatePassRowsAll", n(S["gate_pass_total"]), "stats.json:gate_pass_total", "regexp_matches(_PROJECT_GATE) over all ledger rows")
260 384
261 −# ---- Table 4: 10-K / 10-Q items in scope ----------------------------------------
385 +# ---- Table: ledger reconciliation by form and run (calls vs rows vs productive) ----------------------------------
386 +gfr = R / "ledger" / "gate_pass_by_form_run.csv"; gr = R / "ledger" / "gate_pass_by_run.csv"
387 +if gfr.exists() and gr.exists():
388 + fr = rows(gfr.stem, gfr.parent); rr = rows(gr.stem, gr.parent)
389 + tab = ("\\begin{tabular}{llrrrrrrrr}\n\\toprule\nForm & Run & " + H("Ledgered\\\\rows") + " & " + H("Rows\\\\$< 30$ words") + " & " + H("Gate-passing\\\\calls") +
390 + " & " + H("Productive\\\\sections") + " & " + H("Productive\\\\(\\% of calls)") + " & " + H("Mentions\\\\(ledger)") + " & " + H("Mentions\\\\stored") +
391 + " & " + H("Mentions\\\\per call") + " \\\\\n\\midrule\n")
392 + for r in fr:
393 + tab += (f"{r['form_type']} & {RUNLAB.get(r['run'], r['run'])} & {n(r['ledger_rows'])} & {n(r['lt30_words'])} & {n(r['calls'])} & {n(r['with_mentions'])} & "
394 + f"{pct(r['productive_pct_calls'])} & {n(r['ledger_mentions'])} & {n(r['stored_mentions'])} & {float(r['mentions_per_call']):.2f} \\\\\n")
395 + tab += "\\midrule\n"
396 + for r in rr:
397 + tab += (f"All forms & {RUNLAB.get(r['run'], r['run'])} & {n(r['ledger_rows'])} & {n(r['lt30_words'])} & {n(r['calls'])} & {n(r['with_mentions'])} & "
398 + f"{pct(r['productive_pct_calls'])} & {n(r['ledger_mentions'])} & {n(r['stored_mentions'])} & {float(r['mentions_per_call']):.2f} \\\\\n")
399 + if gt:
400 + tab += (f"All forms & Both runs & {n(gt['ledger_rows'])} & {n(gt['lt30_words'])} & {n(gt['calls'])} & {n(gt['with_mentions'])} & {pct(gt['productive_pct_calls'])} & "
401 + f"{n(gt['ledger_mentions'])} & {n(gt['stored_mentions'])} & {gt['mentions_per_call']:.2f} \\\\\n")
402 + tab += "\\bottomrule\n\\end{tabular}"
403 + float_table("tab_ledger_calls.tex", "tab:ledger_calls", "Extraction ledger reconciliation by form and run: ledgered rows, gate-passing calls, productive sections and mentions",
404 + tab, "The run is identified by the ledger timestamp: every row of the June (S\\&P~500) run was re-inserted at a single instant "
405 + f"(\\SPIDextractedAtFirst) and the October run occupies all later timestamps; the ledger itself stores no run, model or prompt identifier. "
406 + "``Gate-passing calls'' are rows whose stored text matches the candidate gate of Appendix~\\ref{app:prompt} (recomputed with DuckDB RE2 and with "
407 + "Python \\texttt{re}; the two agree on every row and no row with mentions fails the gate); the remaining rows were ledgered as ``no project'' "
408 + "without an API call. Rows under 30 words exist only in the backfilled block, which ignored the word filter. A productive section has at least one "
409 + "stored mention. The ledger cannot distinguish an empty answer from a failed call (Table~\\ref{tab:outage}), so productive shares are lower bounds "
410 + "on the share of calls that would return a project under a complete run.",
411 + "results/ledger/gate\\_pass\\_by\\_form\\_run.csv, gate\\_pass\\_by\\_run.csv, gate\\_pass\\_totals.json", size="\\scriptsize", colsep="3pt", fit=True)
412 +
413 +# ---- Table: outage reconciliation (appendix) --------------------------------------------------------------------
414 +ls_ = jload("ledger/log_summary.json"); tp = jload("ledger/throughput.json"); bb = jload("ledger/backfill_block.json")
415 +oc_ = ls_.get("october", {}) if isinstance(ls_.get("october"), dict) else {}
416 +rb1 = R / "ledger" / "resume_batch1_vs_expected.csv"
417 +if oc_ and tp and rb1.exists():
418 + rec = oc_.get("outage_rows_reconciliation", {}); rs = oc_.get("resume_batch1", {}); lw = oc_.get("outage_window_from_log", ["", "", 0])
419 + owr = oc_.get("outside_window_by_reason", {}); rsn = oc_.get("llm_call_failed_by_reason", {})
420 + rb = rows(rb1.stem, rb1.parent)
421 + rb_calls = sum(int(r["calls"]) for r in rb); rb_prod = sum(int(r["with_mentions"]) for r in rb); rb_exp = sum(float(r["expected_with_mentions"]) for r in rb)
422 + rb_rows = sum(int(r["rows"]) for r in rb)
423 + anomalous = [b for b in oc_.get("anomalous_batches", []) if isinstance(b, list) and str(lw[0]) <= str(b[3]) <= str(lw[1])]
424 + an_ids = sorted(int(b[1]) for b in anomalous)
425 + tab = "\\begin{tabular}{p{9.3cm}r}\n\\toprule\nQuantity & Value \\\\\n\\midrule\n"
426 + tab += "\\multicolumn{2}{l}{\\itshape Panel A: rows removed from the ledger after the credit-exhaustion outage (research log: " + n(rec.get('paper_research_log_149352', 0)) + ")} \\\\\n"
427 + tab += f"Sections reported complete by the October log, all batches ($\\sum$ ``Extraction complete'') & {n(rec.get('extraction_complete_sum_sections', 0))} \\\\\n"
428 + tab += f"Sections pending at the second start of the run & {n(rec.get('pending_at_second_start', 0))} \\\\\n"
429 + tab += f"Difference = sections ledgered during the outage and re-submitted & {n(rec.get('difference', 0))} \\\\\n"
430 + tab += f"Ledger rows with a timestamp inside the largest gap ({str(tp.get('october_first_flush',''))[:0]}{str(tp['largest_gaps_seconds'][-1][1])[11:16]}--{str(tp['largest_gaps_seconds'][-1][2])[11:16]}, {tp['largest_gap_hours']:.2f}~h) & {n(oc_.get('ledger_rows_in_largest_gap', 0))} \\\\\n"
431 + tab += f"Log batches returning zero mentions inside the outage window (batch ids {an_ids[0] if an_ids else ''}--{an_ids[-1] if an_ids else ''}) & {len(anomalous)} \\\\\n"
432 + tab += "\\midrule\n\\multicolumn{2}{l}{\\itshape Panel B: failed-call lines in the October log (" + n(oc_.get('llm_call_failed_total', 0)) + " lines; the ledger records none of them)} \\\\\n"
433 + tab += f"Retryable HTTP 429/5xx inside the outage window {str(lw[0])[11:16]}--{str(lw[1])[11:16]} & {n(lw[2])} \\\\\n"
434 + tab += f"Retryable HTTP 429/5xx in the outage tail (first ledger window definition, 20 s after the log window) & {n(owr.get('retryable_http_429_5xx', 0))} \\\\\n"
435 + tab += f"Connection resets & {n(rsn.get('connection_error', 0))} \\\\\n"
436 + tab += f"JSON-decode failures outside the outage (ledgered as ``no project'': silent empty results) & {n(oc_.get('silent_empty_results_outside_outage', 0))} \\\\\n"
437 + tab += f"``Section failed'' lines & {n(oc_.get('section_failed', 0))} \\\\\n"
438 + jn_ = ls_.get("june", {}) if isinstance(ls_.get("june"), dict) else {}
439 + tab += f"JSON-decode failures in the June log (of {n(bb.get('june_log_sections', 0))} sections) & {n(jn_.get('llm_call_failed_total', 0))} \\\\\n"
440 + tab += "\\midrule\n\\multicolumn{2}{l}{\\itshape Panel C: first batch after the resume (" + str(rs.get('window', ['', ''])[0])[11:16] + "--" + str(rs.get('window', ['', ''])[1])[11:16] + ", " + n(len(rs.get('ciks', []))) + " issuers)} \\\\\n"
441 + tab += f"Sections in the batch (log) / ledgered rows & {n(rs.get('log_sections', 0))} / {n(rb_rows)} \\\\\n"
442 + tab += f"Gate-passing calls & {n(rb_calls)} \\\\\n"
443 + tab += f"Productive sections observed & {n(rb_prod)} \\\\\n"
444 + tab += f"Productive sections expected at the form $\\times$ item rates of the rest of the run & {rb_exp:.1f} \\\\\n"
445 + tab += f"Failed-call lines logged inside the batch window & {n(rs.get('failed_call_lines_in_window', 0))} \\\\\n"
446 + tab += "\\bottomrule\n\\end{tabular}"
447 + float_table("tab_outage.tex", "tab:outage", "Reconciliation of the October 2026 extraction outage: log, ledger and the suspect post-resume batch", tab,
448 + "Panel A reconciles the research log's figure with the run log and the ledger timestamps; the ledger stamps every row individually "
449 + f"({n(tp.get('october_distinct_flush_timestamps', 0))} distinct timestamps), so the per-flush test proposed at review is replaced by per-minute and "
450 + "per-batch productivity tests (\\texttt{results/ledger/}). Panel B classifies the ``LLM call failed'' lines of the log by reason; a JSON-decode failure "
451 + "returns an empty list that the ledger records as zero mentions, indistinguishable from ``no project''. Panel C: the first batch after the resume returned "
452 + f"{n(rb_prod)} productive sections where {rb_exp:.0f} were expected, with no failure logged, which is consistent with HTTP-200 empty answers while the "
453 + "quota was being restored; only a re-submission of its gate-passing sections (authorisation request AR-LLM-4, not granted in this revision) can "
454 + "separate ``no project'' from ``empty answer''. Expected counts apply the productive share of each form $\\times$ item outside the batch to the batch's calls.",
455 + "results/ledger/log\\_summary.json, throughput.json, backfill\\_block.json, resume\\_batch1\\_vs\\_expected.csv", size="\\footnotesize")
456 + macro("resumeBatchCalls", n(rb_calls), "results/ledger/resume_batch1_vs_expected.csv", "sum(calls)")
457 + macro("resumeBatchProductive", n(rb_prod), "results/ledger/resume_batch1_vs_expected.csv", "sum(with_mentions)")
458 + macro("resumeBatchExpected", f"{rb_exp:.0f}", "results/ledger/resume_batch1_vs_expected.csv", "sum(expected_with_mentions)")
459 + macro("resumeBatchSections", n(rs.get("log_sections", 0)), "results/ledger/log_summary.json:october.resume_batch1.log_sections", "log")
460 + macro("resumeBatchCiks", n(len(rs.get("ciks", []))), "results/ledger/log_summary.json", "len(ciks)")
461 + macro("outageZeroBatches", str(len(anomalous)), "results/ledger/log_summary.json:october.anomalous_batches", "count")
462 +
463 +# ---- Table 4: 10-K / 10-Q items in scope ------------------------------------------------------------------------
262 464 gp = None
263 −for cand in (R / "ledger" / "gate_pass_by_form_item.csv",):
264 − if cand.exists():
265 − gp = {}
266 − for r in rows(cand.stem, cand.parent):
267 − fk = next((r[c] for c in r if c in ("form", "form_type")), None)
268 − ik = next((r[c] for c in r if c in ("item", "section_name")), None)
269 − gk = r.get("calls", next((r[c] for c in r if "gate_pass" in c.lower()), None))
270 − if fk and ik and gk not in (None, ""):
271 − gp[(fk, ik)] = gp.get((fk, ik), 0) + int(float(gk)) # summed over runs (backfilled + October)
272 −cols = "llrr" + ("r" if gp else "")
273 −body = f"\\begin{{tabular}}{{{cols}}}\n\\toprule\nForm & Section (item) & Ledgered sections & Mentions" + (" & Gate passed (calls)" if gp else "") + " \\\\\n\\midrule\n"
465 +cand = R / "ledger" / "gate_pass_by_form_item.csv"
466 +if cand.exists():
467 + gp = {}
468 + for r in rows(cand.stem, cand.parent):
469 + fk = next((r[c] for c in r if c in ("form", "form_type")), None)
470 + ik = next((r[c] for c in r if c in ("item", "section_name")), None)
471 + gk = r.get("calls", next((r[c] for c in r if "gate_pass" in c.lower()), None))
472 + if fk and ik and gk not in (None, ""):
473 + gp[(fk, ik)] = gp.get((fk, ik), 0) + int(float(gk))
474 +fpi = {}
475 +fpath = R / "fp_classes" / "financing_regex_by_item.csv"
476 +if fpath.exists():
477 + fpi = {(r["form_type"], r["item"]): r for r in rows(fpath.stem, fpath.parent)}
478 +foc = {}
479 +fcp = R / "focus" / "focus_coverage_by_form_item.csv"
480 +if fcp.exists():
481 + foc = {(r["form"], r["item"]): r for r in rows(fcp.stem, fcp.parent)}
482 +cols = "llrr" + ("r" if gp else "") + ("r" if foc else "") + ("r" if fpi else "")
483 +tab = (f"\\begin{{tabular}}{{{cols}}}\n\\toprule\nForm & Section (item) & " + H("Ledgered\\\\rows") + " & Mentions" + ((" & " + H("Gate-passing\\\\calls")) if gp else "")
484 + + ((" & " + H("Median share of\\\\text shown (\\%)")) if foc else "") + ((" & " + H("Financing-class\\\\mentions (\\%)")) if fpi else "") + " \\\\\n\\midrule\n")
274 485 for form, name in (("10-K", "ledger_10k_items"), ("10-Q", "ledger_10q_items")):
275 486 for r in rows(name):
276 − extra = f" & {n(gp[(form, r['section_name'])])}" if gp and (form, r["section_name"]) in gp else (" & --" if gp else "")
277 − body += f"{form} & \\texttt{{{r['section_name'].replace('_', '\\_')}}} & {n(r['n'])} & {n(r['mentions'])}{extra} \\\\\n"
278 − if form == "10-K": body += "\\midrule\n"
279 −body += "\\bottomrule\n\\end{tabular}"
280 −w("tab_items.tex", body)
487 + k = (form, r["section_name"])
488 + extra = (f" & {n(gp[k])}" if gp and k in gp else (" & --" if gp else ""))
489 + extra += (f" & {100*float(foc[k]['shown_p50']):.0f}" if foc and k in foc else (" & --" if foc else ""))
490 + extra += (f" & {pct(fpi[k]['pct'])}" if fpi and k in fpi else (" & --" if fpi else ""))
491 + tab += f"{form} & {tt(r['section_name'])} & {n(r['n'])} & {n(r['mentions'])}{extra} \\\\\n"
492 + if form == "10-K": tab += "\\midrule\n"
493 +k8 = ("8-K", "full_body"); lr8 = next(r for r in lb if r["form_type"] == "8-K")
494 +extra = (f" & {n(gp[k8])}" if gp and k8 in gp else (" & --" if gp else ""))
495 +extra += (f" & {100*float(foc[k8]['shown_p50']):.0f}" if foc and k8 in foc else (" & --" if foc else ""))
496 +extra += (f" & {pct(fpi[k8]['pct'])}" if fpi and k8 in fpi else (" & --" if fpi else ""))
497 +tab += f"\\midrule\n8-K & {tt('full_body')} & {n(lr8['sections'])} & {n(lr8['mentions'])}{extra} \\\\\n"
498 +tab += "\\bottomrule\n\\end{tabular}"
281 499 k10 = {r["section_name"]: r for r in rows("ledger_10k_items")}; q10 = {r["section_name"]: r for r in rows("ledger_10q_items")}
500 +float_table("tab_items.tex", "tab:items", "Ledgered rows, mentions, gate-passing calls, text shown to the model and financing-class share, by form and item", tab,
501 + "Mentions are ledger counts (before identifier de-duplication, Table~\\ref{tab:sections}). The 10-K \\texttt{full\\_body} rows are filings of the June "
502 + "(S\\&P~500) ingest in which its segmenter found no Item heading; the October parser's \\texttt{full\\_document} fallback produced 10-K rows that are "
503 + "excluded from extraction by scope (Section~\\ref{sec:architecture}), while its 10-Q \\texttt{full\\_document} rows are ledgered. "
504 + + ("``Median share of text shown'' is the median, over the item's ledgered rows, of the fraction of the section's characters contained in the focus windows "
505 + "actually sent to the model (Table~\\ref{tab:focus}). " if foc else "")
506 + + ("``Financing-class mentions'' is the share of the item's stored mentions whose name or description matches the repurchase / dividend / credit-facility / "
507 + "notes-offering pattern of Table~\\ref{tab:fp_classes}; rows above 10\\% are the 10-Q \\texttt{unregistered\\_sales} item (Part~II Item~2, where "
508 + "issuer repurchases are tabled) and the 8-K body." if fpi else ""),
509 + "data/ledger\\_10k\\_items.csv, ledger\\_10q\\_items.csv, results/ledger/gate\\_pass\\_by\\_form\\_item.csv, results/focus/, results/fp\\_classes/",
510 + size="\\footnotesize", colsep="3pt", fit=True)
282 511 for key, src in (("tenKmdnaMentions", k10.get("md_and_a")), ("tenQmdnaMentions", q10.get("md_and_a")), ("tenKbusinessMentions", k10.get("business")),
283 512 ("tenQfinancialStatementsMentions", q10.get("financial_statements"))):
284 513 if src: macro(key, n(src["mentions"]), "data/ledger_10k_items.csv / ledger_10q_items.csv", "mentions by item")
285 514 if k10.get("full_body"): macro("tenKfullBodyRows", n(k10["full_body"]["n"]), "data/ledger_10k_items.csv", "n where section_name=full_body")
286 515
287 −# ---- Table 5: projects by type ---------------------------------------------------
516 +# ---- Table 5: projects by type ----------------------------------------------------------------------------------
288 517 pt = rows("projects_by_type")
289 518 ci = {}
290 −ci_path = D / "projects_by_type_ci.csv"
291 −if ci_path.exists():
519 +if (D / "projects_by_type_ci.csv").exists():
292 520 for r in rows("projects_by_type_ci"):
293 521 lo = next((r[c] for c in r if c.lower() in ("ci_low", "lo", "ci_lo", "median_ci_low")), None)
294 522 hi = next((r[c] for c in r if c.lower() in ("ci_high", "hi", "ci_hi", "median_ci_high")), None)
295 523 if lo not in (None, "") and hi not in (None, ""):
296 − ci[r["project_type"]] = (float(lo), float(hi))
524 + ci[r["project_type"]] = (float(lo), float(hi), r.get("B", ""), r.get("seed", ""))
297 525 small_n = di("small_n_threshold") or 50
298 −# the threshold itself is a documented presentation rule (data/documented_inputs.json), not a measurement
299 526 ad = rows("amount_dist")[0]; q = json.loads(ad["q"])
300 527 total_median = S.get("amount_total_median_musd", q[2] / 1e6)
301 528 om = {}
302 529 om_path = R / "resolver" / "overmerge_by_type.csv"
303 530 if om_path.exists():
304 531 om = {r["project_type"]: r for r in rows(om_path.stem, om_path.parent)}
305 −oc = " & $\\geq 3$ distinct names (\\%)" if om else ""
306 −body = ("\\begin{tabular}{llrrrrrr" + ("r" if om else "") + "}\n\\toprule\nCode & Category & Projects & Share (\\%) & With amount ($N$) & Median amount (M USD) & "
307 − "95\\% CI of the median & Mentions / project" + oc + " \\\\\n\\midrule\n")
308 −pct_sum = 0.0; greyed = []
532 +rx = {}
533 +rx_path = R / "fp_classes" / "table5_restated_excl_financing.csv"
534 +if rx_path.exists():
535 + rx = {r["project_type"]: r for r in rows(rx_path.stem, rx_path.parent)}
536 +tab = ("\\begin{tabular}{lrr" + ("r" if rx else "") + "rrrr" + ("r" if om else "") + "}\n\\toprule\nCategory & Projects & " + H("Share\\\\(\\%)")
537 + + ((" & " + H("Excl. financing\\\\class ($N$)")) if rx else "") + " & " + H("With\\\\amount ($N$)") + " & " + H("Median amount\\\\(M USD)") + " & "
538 + + H("95\\% CI of\\\\the median") + " & " + H("Mentions\\\\per project") + ((" & " + H("$\\geq 3$ distinct\\\\names (\\%)")) if om else "") + " \\\\\n\\midrule\n")
539 +pct_sum = 0.0; greyed = []; excl_sum = 0
309 540 for r in pt:
310 541 pct_sum += float(r["pct"]); N = int(r["with_amount"])
311 542 med = n(r["median_amount_musd"], 1)
312 543 if N < small_n:
313 544 med = f"\\textcolor{{gray}}{{{med}}}"; greyed.append(r["project_type"])
314 − cic = f"{ci[r['project_type']][0]/1e6:,.1f}--{ci[r['project_type']][1]/1e6:,.1f}".replace(",", "{,}") if r["project_type"] in ci else "--"
545 + cic = (f"[{ci[r['project_type']][0]/1e6:,.1f}, {ci[r['project_type']][1]/1e6:,.1f}]".replace(",", "{,}") if r["project_type"] in ci else "--")
546 + if N < small_n and r["project_type"] in ci: cic = f"\\textcolor{{gray}}{{{cic}}}"
547 + rv = ""
548 + if rx:
549 + ex = int(rx[r["project_type"]]["n_excl_any"]) if r["project_type"] in rx else int(r["n"]); excl_sum += ex; rv = f" & {n(ex)}"
315 550 ov = f" & {float(om[r['project_type']]['pct_ge3_names']):.1f}" if om and r["project_type"] in om else (" & --" if om else "")
316 − body += (f"\\texttt{{{r['project_type'].replace('_', '\\_')}}} & {LAB[r['project_type']]} & {n(r['n'])} & {r['pct']} & {n(N)} & {med} & {cic} & "
317 − f"{float(r['mean_mentions']):.2f}{ov} \\\\\n")
318 −body += (f"\\midrule\n & Total & {n(S['projects'])} & {pct_sum:.1f} & {n(S['projects_fields'][0])} & {n(total_median, 1)} & -- & "
319 − f"{S['mentions']/S['projects']:.2f}" + (" & " if om else "") + f" \\\\\n\\bottomrule\n\\end{{tabular}}")
320 −w("tab_types.tex", body)
321 −note = (f"\\item Shares are rounded to one decimal and sum to {pct_sum:.1f}. ``With amount'' counts projects for which at least one mention carries a USD "
322 − f"figure; ``median amount'' is the median across those projects of the largest amount cited (Section~\\ref{{sec:amounts}} on why amounts are never summed). "
323 − f"Medians printed in grey rest on fewer than {small_n} projects with an amount ({', '.join('\\texttt{' + g.replace('_', '\\_') + '}' for g in greyed)}) "
324 − "and should not be quoted without their $N$. "
325 − + ("The 95\\% interval of the median is a percentile bootstrap (\\texttt{data/projects\\_by\\_type\\_ci.csv}). " if ci
326 − else "The 95\\% interval column is filled when \\texttt{data/projects\\_by\\_type\\_ci.csv} (bootstrap on the node) is present. ")
327 − + ("``$\\geq 3$ distinct names'' is the share of projects of the category whose mentions carry three or more distinct project names "
328 − "(over-merge indicator of the resolution key, \\texttt{results/resolver/overmerge\\_by\\_type.csv}).\n" if om else "\n"))
329 −w("tab_types_note.tex", note)
551 + tab += f"{LAB[r['project_type']]} & {n(r['n'])} & {r['pct']}{rv} & {n(N)} & {med} & {cic} & {float(r['mean_mentions']):.2f}{ov} \\\\\n"
552 +tab += (f"\\midrule\nTotal & {n(P)} & {pct_sum:.1f}" + (f" & {n(excl_sum)}" if rx else "") + f" & {n(S['projects_fields'][0])} & {n(total_median, 1)} & -- & "
553 + f"{M/P:.2f}" + (" & " if om else "") + " \\\\\n\\bottomrule\n\\end{tabular}")
554 +ci_meta = next(iter(ci.values()))[2:] if ci else ("", "")
555 +note5 = (f"Category codes are listed in Table~\\ref{{tab:taxonomy}}. Shares are rounded to one decimal and sum to {pct_sum:.1f}. "
556 + + (f"``Excl. financing class'' removes projects with at least one mention matching the repurchase / dividend / credit-facility / notes-offering pattern of "
557 + f"Table~\\ref{{tab:fp_classes}} ({n(P - excl_sum)} projects, {100*(P-excl_sum)/P:.1f}\\%); the two columns bracket the construct violation, they do not measure precision. " if rx else "")
558 + + f"``With amount'' counts projects for which at least one mention carries a USD figure; ``median amount'' is the median across those projects of the largest "
559 + f"amount cited (Section~\\ref{{sec:amounts}} on why amounts are never summed). Medians printed in grey rest on fewer than {small_n} projects with an amount "
560 + f"({', '.join(tt(g) for g in greyed)}) and should not be quoted without their $N$. "
561 + + (f"The 95\\% interval of the median is a percentile bootstrap over projects (B = {n(ci_meta[0])}, seed {ci_meta[1]}, \\texttt{{data/projects\\_by\\_type\\_ci.csv}}); "
562 + "an interval equal to the point estimate reflects the rounding of disclosed amounts to round numbers. " if ci else "The 95\\% interval column is filled when \\texttt{data/projects\\_by\\_type\\_ci.csv} is present. ")
563 + + ("``$\\geq 3$ distinct names'' is the share of the category's projects whose mentions carry three or more distinct project names, an over-merge indicator of the "
564 + "resolution key (Table~\\ref{tab:spec_curve}). " if om else "")
565 + + "All counts are under the current resolution key at the 0.45 confidence threshold.")
566 +float_table("tab_types.tex", "tab:types", "Resolved projects by taxonomy category: counts, financing-class restatement, disclosed amounts and over-merge indicator", tab, note5,
567 + "data/projects\\_by\\_type.csv, projects\\_by\\_type\\_ci.csv, results/fp\\_classes/table5\\_restated\\_excl\\_financing.csv, results/resolver/overmerge\\_by\\_type.csv",
568 + size="\\scriptsize", colsep="3pt", fit=True)
330 569 macro("typesPctSum", f"{pct_sum:.1f}", "data/projects_by_type.csv", "sum(pct)")
331 570 macro("amountMedianMusd", n(total_median, 1), "stats.json:amount_total_median_musd or data/amount_dist.csv", "median(total_amount_usd)/1e6")
332 571 macro("smallNThreshold", str(small_n), "data/documented_inputs.json:small_n_threshold", "presentation rule")
333 572 macro("smallNCategories", ", ".join(greyed), "data/projects_by_type.csv", f"with_amount < {small_n}")
573 +if rx:
574 + macro("projectsExclFinancing", n(excl_sum), "results/fp_classes/table5_restated_excl_financing.csv", "sum(n_excl_any)")
575 + macro("projectsWithFinancingMention", n(P - excl_sum), "results/fp_classes/table5_restated_excl_financing.csv", "projects - sum(n_excl_any)")
576 + macro("projectsWithFinancingMentionPct", f"{100*(P-excl_sum)/P:.1f}", "results/fp_classes/table5_restated_excl_financing.csv", "100*(projects - sum(n_excl_any))/projects")
577 + for code in ("capex_program", "cost_reduction", "ma_integration"):
578 + if code in rx:
579 + cam = "".join(p.capitalize() for p in code.split("_"))
580 + macro(f"nExclFinancing{cam}", n(rx[code]["n_excl_any"]), "results/fp_classes/table5_restated_excl_financing.csv", f"n_excl_any where project_type={code}")
581 + macro(f"shareExclFinancing{cam}", pct(rx[code]["pct_excl_any"]), "results/fp_classes/table5_restated_excl_financing.csv", f"pct_excl_any where project_type={code}")
334 582 ptd = {r["project_type"]: r for r in pt}
335 583 for code in ("data_center", "ai_initiative", "cloud_migration", "automation", "ma_integration", "capex_program", "partnership", "geographic_expansion", "plant_construction"):
336 584 if code in ptd:
@@ -339,18 +587,25 @@ for code in ("data_center", "ai_initiative", "cloud_migration", "automation", "m
339 587 macro(f"n{cam}", n(ptd[code]["n"]), "data/projects_by_type.csv", f"n where project_type={code}")
340 588 macro(f"withAmount{cam}", n(ptd[code]["with_amount"]), "data/projects_by_type.csv", f"with_amount where project_type={code}")
341 589 macro(f"medianAmount{cam}", n(ptd[code]["median_amount_musd"], 1), "data/projects_by_type.csv", f"median_amount_musd where project_type={code}")
590 + if code in ci:
591 + macro(f"medianAmountCI{cam}", f"{ci[code][0]/1e6:,.1f}--{ci[code][1]/1e6:,.1f}".replace(",", "{,}"), "data/projects_by_type_ci.csv", f"ci_low--ci_high where project_type={code}")
342 592 tech = [c for c in ("data_center", "ai_initiative", "cloud_migration", "automation") if c in ptd]
343 593 macro("techCategoriesCountRange", f"{n(min(int(ptd[c]['n']) for c in tech))}--{n(max(int(ptd[c]['n']) for c in tech))}", "data/projects_by_type.csv", "min/max n over " + ", ".join(tech))
344 594
345 −# ---- Table 6: by sector -------------------------------------------------------------
595 +# ---- Table 6: by sector -----------------------------------------------------------------------------------------
346 596 cs = {r["sector"]: r for r in rows("companies_by_sector")}
347 597 sec = rows("projects_by_sector")
348 −body = "\\begin{tabular}{lrrrrr}\n\\toprule\nGICS sector (iShares) & Issuers in universe & of which S\\&P~500 & Issuers with projects & Projects & Projects per issuer \\\\\n\\midrule\n"
598 +tab = ("\\begin{tabular}{lrrrrr}\n\\toprule\nGICS sector (iShares) & " + H("Issuers in\\\\universe") + " & " + H("of which\\\\S\\&P~500") + " & " +
599 + H("Issuers with\\\\projects") + " & Projects & " + H("Projects\\\\per issuer") + " \\\\\n\\midrule\n")
349 600 for r in sec:
350 601 c = cs.get(r["sector"], {"n": "", "sp500": ""})
351 − body += f"{r['sector']} & {n(c['n']) if c['n'] else ''} & {n(c['sp500']) if c['sp500'] else ''} & {n(r['issuers'])} & {n(r['n'])} & {float(r['per_issuer']):.1f} \\\\\n"
352 −body += "\\bottomrule\n\\end{tabular}"
353 −w("tab_sectors.tex", body)
602 + tab += f"{r['sector']} & {n(c['n']) if c['n'] else ''} & {n(c['sp500']) if c['sp500'] else ''} & {n(r['issuers'])} & {n(r['n'])} & {float(r['per_issuer']):.1f} \\\\\n"
603 +tab += (f"\\midrule\nTotal & {n(U['n'])} & {n(sp500_ciks)} & {n(S['issuers_with_projects'])} & {n(P)} & {P/S['issuers_with_projects']:.1f} \\\\\n\\bottomrule\n\\end{{tabular}}")
604 +float_table("tab_sectors.tex", "tab:sectors", "Issuers and resolved projects by sector", tab,
605 + "Sector labels come from the iShares holdings file (Russell proxy) or, for S\\&P~500-only issuers, from the Wikipedia GICS table; ``Issuers in universe'' "
606 + "includes issuers without filings. Projects per issuer is projects divided by issuers with at least one project. The S\\&P~500 issuers were extracted in two runs "
607 + "and with two 10-K segmenters (Table~\\ref{tab:cohort}), so cross-sector differences in projects per issuer mix disclosure behaviour with run and volume effects.",
608 + "data/projects\\_by\\_sector.csv, companies\\_by\\_sector.csv")
354 609 secd = {r["sector"]: r for r in sec}
355 610 top4 = sorted(sec, key=lambda r: -float(r["per_issuer"]))[:4]
356 611 vals = [float(r["per_issuer"]) for r in top4]
@@ -363,19 +618,73 @@ for name in ("Health Care", "Industrials"):
363 618 macro(f"sectorProjects{cam}", n(secd[name]["n"]), "data/projects_by_sector.csv", f"n for {name}")
364 619 macro(f"sectorIssuers{cam}", n(secd[name]["issuers"]), "data/projects_by_sector.csv", f"issuers for {name}")
365 620
366 −# ---- Table 7: status, mention buckets, duration ----------------------------------------
621 +# ---- Table: cohort (index membership x run) with issuer-level OLS ----------------------------------------------
622 +t6 = R / "runs" / "table6_cohort.csv"; t6r = jload("runs/table6_cohort_regression.json")
623 +if t6.exists() and t6r:
624 + cr = rows(t6.stem, t6.parent)
625 + CL = {"both": "S\\&P~500 $\\cap$ Russell proxy", "russell_only": "Russell proxy only", "sp500_only": "S\\&P~500 only"}
626 + tab = ("\\begin{tabular}{lrrrrrrr}\n\\toprule\n\\multicolumn{8}{l}{\\itshape Panel A: projects per issuer by cohort and by run of the mentions counted} \\\\\n"
627 + "Cohort & Issuers & " + H("Projects\\\\(all mentions)") + " & " + H("Per\\\\issuer") + " & " + H("Projects\\\\(October mentions)") + " & " + H("Per\\\\issuer") +
628 + " & " + H("Ledger rows\\\\per issuer") + " & " + H("October rows\\\\per issuer") + " \\\\\n\\midrule\n")
629 + for r in cr:
630 + tab += (f"{CL.get(r['cohort'], r['cohort'])} & {n(r['issuers'])} & {n(r['projects_all'])} & {pct(r['per_issuer_all'])} & {n(r['projects_october_only'])} & "
631 + f"{pct(r['per_issuer_october_only'])} & {pct(r['ledger_rows_per_issuer'])} & {pct(r['october_rows_per_issuer'])} \\\\\n")
632 + tab += "\\midrule\n\\multicolumn{8}{l}{\\itshape Panel B: issuer-level OLS of projects on the S\\&P~500 cohort dummy (HC1 standard errors in parentheses)} \\\\\n"
633 + tab += "Dependent variable & \\multicolumn{2}{c}{S\\&P~500 dummy} & \\multicolumn{2}{c}{log(1 + ledger rows)} & $N$ & $R^2$ & \\\\\n\\midrule\n"
634 + specs = (("projects_all_on_sp500", "Projects, all mentions", "log1p_ledger_rows"), ("projects_october_only_on_sp500", "Projects, October mentions only", "log1p_october_rows"),
635 + ("projects_all_on_sp500_log_rows", "Projects, all mentions, volume control", "log1p_ledger_rows"),
636 + ("projects_october_only_on_sp500_log_rows_oct", "Projects, October mentions, volume control", "log1p_october_rows"))
637 + for key, lab, vol in specs:
638 + m = t6r.get(key)
639 + if not m: continue
640 + b = m["in_sp500"]; v = m.get(vol)
641 + tab += (f"{lab} & {b['coef']:.2f} & ({b['hc1_se']:.2f}) & " + (f"{v['coef']:.2f} & ({v['hc1_se']:.2f})" if v else "-- & ") +
642 + f" & {n(m['n'])} & {m['r2']:.3f} & \\\\\n")
643 + tab += "\\bottomrule\n\\end{tabular}"
644 + sp = t6r.get("projects_all_on_sp500", {}).get("in_sp500", {}); so = t6r.get("projects_october_only_on_sp500", {}).get("in_sp500", {})
645 + float_table("tab_cohort.tex", "tab:cohort", "Projects per issuer by index-membership cohort: the apparent S\\&P~500 effect is a run and volume effect", tab,
646 + "Panel A counts projects per issuer with all mentions and with only the mentions produced by the October run (a project is ``October'' when at least one of its "
647 + "mentions carries an October timestamp); S\\&P~500 issuers were additionally extracted in the June run, whose 10-K items came from a different segmenter "
648 + "(Section~\\ref{sec:architecture}). Panel B reports the coefficient on the S\\&P~500 dummy from issuer-level OLS with heteroskedasticity-robust (HC1) standard "
649 + f"errors; the sign flips from $+{sp.get('coef', 0):.1f}$ to ${so.get('coef', 0):.1f}$ projects per issuer when the run is held fixed and vanishes once the "
650 + "number of ledgered rows is controlled for. Economic magnitude: one log point of ledgered rows is associated with "
651 + f"{t6r.get('projects_all_on_sp500_log_rows', {}).get('log1p_ledger_rows', {}).get('coef', 0):.1f} additional projects. No causal reading is intended: "
652 + "the regressions describe the composition of the database, not disclosure behaviour.",
653 + "results/runs/table6\\_cohort.csv, table6\\_cohort\\_regression.json", size="\\scriptsize", colsep="3pt", fit=True)
654 + macro("cohortEffectAll", f"{sp.get('coef', 0):.1f}", "results/runs/table6_cohort_regression.json", "projects_all_on_sp500.in_sp500.coef")
655 + macro("cohortEffectAllSE", f"{sp.get('hc1_se', 0):.2f}", "results/runs/table6_cohort_regression.json", "projects_all_on_sp500.in_sp500.hc1_se")
656 + macro("cohortEffectOctober", f"{so.get('coef', 0):.1f}", "results/runs/table6_cohort_regression.json", "projects_october_only_on_sp500.in_sp500.coef")
657 + macro("cohortEffectOctoberSE", f"{so.get('hc1_se', 0):.2f}", "results/runs/table6_cohort_regression.json", "projects_october_only_on_sp500.in_sp500.hc1_se")
658 + cv_ = t6r.get("projects_all_on_sp500_log_rows", {}).get("in_sp500", {})
659 + macro("cohortEffectVolumeControl", f"{cv_.get('coef', 0):.2f}", "results/runs/table6_cohort_regression.json", "projects_all_on_sp500_log_rows.in_sp500.coef")
660 + macro("cohortEffectVolumeControlSE", f"{cv_.get('hc1_se', 0):.2f}", "results/runs/table6_cohort_regression.json", "projects_all_on_sp500_log_rows.in_sp500.hc1_se")
661 + for r in cr:
662 + cam = "".join(p.capitalize() for p in r["cohort"].split("_"))
663 + macro(f"perIssuerAll{cam}", pct(r["per_issuer_all"]), "results/runs/table6_cohort.csv", f"per_issuer_all where cohort={r['cohort']}")
664 + macro(f"perIssuerOctober{cam}", pct(r["per_issuer_october_only"]), "results/runs/table6_cohort.csv", f"per_issuer_october_only where cohort={r['cohort']}")
665 +
666 +# ---- Table 7: status, mention buckets, duration -----------------------------------------------------------------
367 667 st = rows("projects_by_status"); mb = rows("mentions_per_project"); du = rows("duration"); cf = rows("confidence_dist")
368 −body = "\\begin{tabular}{lr@{\\hspace{2em}}lr@{\\hspace{2em}}lr}\n\\toprule\nLatest status & Projects & Mentions per project & Projects & Span of cited years & Projects \\\\\n\\midrule\n"
668 +tab = "\\begin{tabular}{lr@{\\hspace{1.6em}}lr@{\\hspace{1.6em}}lr}\n\\toprule\nLatest status & Projects & Mentions per project & Projects & Span of cited years & Projects \\\\\n\\midrule\n"
369 669 du_order = ["0", "1-2", "3-5", ">5", "unknown"]; dus = {r["span_years"]: int(r["n"]) for r in du}
370 670 rowsn = max(len(st), len(mb), len(du_order))
371 671 for i in range(rowsn):
372 − a = f"\\texttt{{{st[i]['status'].replace('_', '\\_')}}} & {n(st[i]['n'])}" if i < len(st) else "&"
672 + a = f"{tt(st[i]['status'])} & {n(st[i]['n'])}" if i < len(st) else "&"
373 673 b = f"{mb[i]['bucket']} & {n(mb[i]['n'])}" if i < len(mb) else "&"
374 674 c = f"{du_order[i].replace('>', '$>$')} years & {n(dus[du_order[i]])}" if i < len(du_order) else "&"
375 − body += f"{a} & {b} & {c} \\\\\n"
376 −body += "\\bottomrule\n\\end{tabular}"
377 −w("tab_status.tex", body)
378 −P = S["projects"]; known = P - dus["unknown"]
675 + tab += f"{a} & {b} & {c} \\\\\n"
676 +tab += f"\\midrule\nTotal & {n(P)} & & {n(P)} & & {n(P)} \\\\\n\\bottomrule\n\\end{{tabular}}"
677 +known = P - dus["unknown"]
678 +ti = jload("resolver/ties_idempotence.json")
679 +float_table("tab_status.tex", "tab:status", "Latest status, number of mentions and span of cited years of resolved projects", tab,
680 + "Status is that of the project's latest mention by filing date, a snapshot of the last statement rather than the terminal fate"
681 + + (f" (for {n(ti['projects_with_status_tie_on_last_seen'])} projects several mentions share the last filing date with different statuses, and the stored choice "
682 + "is one admissible value among ties)" if ti.get("projects_with_status_tie_on_last_seen") else "")
683 + + f". The span is the difference between the latest and earliest four-digit year cited in the mentions' text; it is unknown for {n(dus['unknown'])} projects "
684 + f"({100*dus['unknown']/P:.1f}\\%), so the shares quoted in the text, {100*dus['0']/known:.1f}\\% at zero span and {100*dus['>5']/known:.1f}\\% above five years, "
685 + f"are over the {n(known)} projects with known years. Single-mention projects ({100*int(next(r['n'] for r in mb if r['bucket']=='1'))/P:.1f}\\%) mix false splits, "
686 + "one-off disclosures and false positives; projects above ten mentions are where false merges concentrate (Table~\\ref{tab:spec_curve}).",
687 + "data/projects\\_by\\_status.csv, mentions\\_per\\_project.csv, duration.csv, results/resolver/ties\\_idempotence.json")
379 688 macro("spanKnownN", n(known), "data/duration.csv", "projects - unknown")
380 689 macro("spanUnknownN", n(dus["unknown"]), "data/duration.csv", "n where span_years=unknown")
381 690 macro("spanUnknownShareAll", f"{100*dus['unknown']/P:.1f}", "data/duration.csv", "100*unknown/projects")
@@ -387,23 +696,39 @@ for r in st:
387 696 macro("statusShare" + "".join(p.capitalize() for p in r["status"].split("_")), r["pct"], "data/projects_by_status.csv", f"pct where status={r['status']}")
388 697 mbd = {r["bucket"]: int(r["n"]) for r in mb}
389 698 macro("singleMentionShare", f"{100*mbd['1']/P:.1f}", "data/mentions_per_project.csv", "100*n(bucket=1)/projects")
699 +macro("twoMentionShare", f"{100*mbd['2']/P:.1f}", "data/mentions_per_project.csv", "100*n(bucket=2)/projects")
700 +macro("overFiveMentionShare", f"{100*(mbd['6-10']+mbd['>10'])/P:.1f}", "data/mentions_per_project.csv", "100*(n(6-10)+n(>10))/projects")
390 701 macro("overTenMentionShare", f"{100*mbd['>10']/P:.1f}", "data/mentions_per_project.csv", "100*n(bucket=>10)/projects")
391 702
392 −# ---- confidence ---------------------------------------------------------------------
393 −body = "\\begin{tabular}{lr}\n\\toprule\nSelf-reported confidence (rounded) & Mentions \\\\\n\\midrule\n"
394 −for r in cf: body += f"{r['conf']} & {n(r['n'])} \\\\\n"
395 −body += "\\bottomrule\n\\end{tabular}"
396 −w("tab_confidence.tex", body)
397 −M = S["mentions"]; cfd = {float(r["conf"]): int(r["n"]) for r in cf}
703 +# ---- confidence (appendix table) ---------------------------------------------------------------------------------
704 +cvd = jload("ledger/code_vs_data_checks.json")
705 +byrun = {}
706 +for run, conf, cnt in cvd.get("confidence_bins_by_run", []):
707 + byrun.setdefault(float(conf), {})[run] = int(cnt)
708 +cfd = {float(r["conf"]): int(r["n"]) for r in cf}
709 +tab = ("\\begin{tabular}{lrr" + ("rr" if byrun else "") + "}\n\\toprule\n" + H("Self-reported\\\\confidence (rounded)") + " & Mentions & " + H("Share\\\\(\\%)")
710 + + ((" & " + H("June run\\\\(backfilled)") + " & " + H("October\\\\run")) if byrun else "") + " \\\\\n\\midrule\n")
711 +for r in cf:
712 + c = float(r["conf"]); ex = (f" & {n(byrun.get(c, {}).get('backfilled_june', 0))} & {n(byrun.get(c, {}).get('october', 0))}" if byrun else "")
713 + tab += f"{r['conf']} & {n(r['n'])} & {100*int(r['n'])/M:.1f}{ex} \\\\\n"
714 +tab += f"\\midrule\nTotal & {n(M)} & {100.0:.1f}" + (f" & {n(sum(v.get('backfilled_june', 0) for v in byrun.values()))} & {n(sum(v.get('october', 0) for v in byrun.values()))}" if byrun else "") + " \\\\\n\\bottomrule\n\\end{tabular}"
715 +cdef = S.get("conf_exact_default_count")
716 +float_table("tab_confidence.tex", "tab:confidence", "Self-reported extraction confidence of stored mentions, by run", tab,
717 + "Confidence is the value returned by the model in its JSON answer, rounded to one decimal; mentions below 0.45 are discarded before storage. "
718 + + (f"A missing confidence is set to 0.6 by the post-processing code and passes the threshold: {n(cdef)} mentions carry exactly 0.600 and cannot be separated "
719 + "from genuine 0.6 answers because the raw response is not stored. " if cdef is not None else "")
720 + + "The distribution describes the model's reporting habit, not accuracy; calibration requires the human labels of gate (d) (Table~\\ref{tab:gates}).",
721 + "data/confidence\\_dist.csv, results/ledger/code\\_vs\\_data\\_checks.json")
398 722 macro("confShareOne", f"{100*cfd.get(1.0, 0)/M:.1f}", "data/confidence_dist.csv", "100*n(conf=1.0)/mentions")
399 723 macro("confShareNine", f"{100*cfd.get(0.9, 0)/M:.1f}", "data/confidence_dist.csv", "100*n(conf=0.9)/mentions")
400 724 macro("confShareLeSix", f"{100*sum(v for k, v in cfd.items() if k <= 0.6)/M:.1f}", "data/confidence_dist.csv", "100*n(conf<=0.6)/mentions")
401 −if S.get("conf_exact_default_count") is not None:
402 − macro("confExactDefaultCount", n(S["conf_exact_default_count"]), "stats.json:conf_exact_default_count", "count(round(confidence,3)=0.600)")
725 +if cdef is not None:
726 + macro("confExactDefaultCount", n(cdef), "stats.json:conf_exact_default_count", "count(round(confidence,3)=0.600)")
403 727
404 −# ---- Table 8: amounts ----------------------------------------------------------------
728 +# ---- Table 8: amounts and projects per issuer -------------------------------------------------------------------
405 729 ppi = json.loads(rows("projects_per_issuer")[0]["q"])
406 −body = f"""\\begin{{tabular}}{{lrrrrrr}}
730 +at = jload("grounding/amount_tail.json")
731 +tab = f"""\\begin{{tabular}}{{lrrrrrr}}
407 732 \\toprule
408 733 & P10 & P25 & Median & P75 & P90 & P99 \\\\
409 734 \\midrule
@@ -411,7 +736,33 @@ Largest amount cited per project, M USD ($N$ = {n(ad['n'])}) & {q[0]/1e6:,.1f} &
411 736 Projects per issuer ($N$ = {n(S['issuers_with_projects'])}) & {ppi[0]:.0f} & {ppi[1]:.0f} & {ppi[2]:.0f} & {ppi[3]:.0f} & {ppi[4]:.0f} & {ppi[5]:.0f} \\\\
412 737 \\bottomrule
413 738 \\end{{tabular}}""".replace(",", "{,}")
414 −w("tab_amounts.tex", body)
739 +amt_note = ("Amounts are the largest USD figure cited across the mentions of a project; they mix transaction values, budgets, contract values, financing facilities "
740 + "and estimates, and are never summed in the text. ")
741 +if S.get("amount_max") is not None:
742 + macro("amountMaxBusd", f"{S['amount_max']/1e9:,.1f}".replace(",", "{,}"), "stats.json:amount_max", "max(total_amount_usd)/1e9")
743 + amt_note += f"The maximum is {S['amount_max']/1e9:,.0f}~B USD".replace(",", "{,}")
744 + if at:
745 + amt_note += (f" (one mention, number found in the section text, no currency token nearby); {n(at['ge_50e9'])} mentions in {n(S.get('amount_ge_50b', at['projects_max_amount_ge_50e9']))} "
746 + f"projects cite 50~B USD or more, of which {n(at['ge_50e9_grounded_number'][0])} have the number in the text and {n(at['ge_50e9_grounded_number'][1])} a currency token "
747 + f"within 40 characters; {n(at['eq_0'])} mentions carry an amount of exactly zero (with \\texttt{{amount\\_raw}} NULL) and {n(at['lt_0'])} a negative amount")
748 + amt_note += ". "
749 +if S.get("amount_ge_50b") is not None:
750 + macro("amountGeFiftyB", n(S["amount_ge_50b"]), "stats.json:amount_ge_50b", "count(total_amount_usd >= 50e9)")
751 +if S.get("amount_le_zero") is not None:
752 + macro("amountLeZero", n(S["amount_le_zero"]), "stats.json:amount_le_zero", "count(total_amount_usd <= 0)")
753 + amt_note += f"{n(S['amount_le_zero'])} projects have a non-positive maximum amount; none of these values has been corrected (author decision pending). "
754 +if S.get("amount_raw_deviations") is not None:
755 + macro("amountRawDeviations", n(S["amount_raw_deviations"]), "stats.json:amount_raw_deviations", "count(amount_raw is distinct from format(amount_usd))")
756 +if at:
757 + for k, mname in (("ge_50e9", "amountMentionsGeFiftyB"), ("eq_0", "amountMentionsZero"), ("lt_0", "amountMentionsNegative"), ("projects_max_amount_ge_50e9", "amountProjectsGeFiftyB")):
758 + if at.get(k) is not None: macro(mname, n(at[k]), "results/grounding/amount_tail.json", k)
759 + macro("amountTopTwoHundredNumberFound", n(at["top200_grounded_number"][0]), "results/grounding/amount_tail.json", "top200_grounded_number[0]")
760 + macro("amountTopTwoHundredCurrency", n(at["top200_grounded_number"][1]), "results/grounding/amount_tail.json", "top200_grounded_number[1]")
761 + macro("amountNonUsdTokenShare", f"{100*at['nonusd_within_40_share'][0]/at['nonusd_within_40_share'][1]:.1f}", "results/grounding/amount_tail.json", "100*nonusd_within_40_share[0]/[1]")
762 +amt_note += ("Projects per issuer are counted under the current resolution key, whose choice moves the total by a factor of ten (Table~\\ref{tab:spec_curve}). "
763 + "Quantiles are exact order statistics of the stored tables; no sampling uncertainty applies.")
764 +float_table("tab_amounts.tex", "tab:amounts", "Distribution of the largest disclosed amount per project and of projects per issuer", tab, amt_note,
765 + "data/amount\\_dist.csv, projects\\_per\\_issuer.csv, data/stats.json, results/grounding/amount\\_tail.json")
415 766 macro("amountMentions", n(S["mentions_fields"][0]), "stats.json:mentions_fields[0]", "count(amount_usd is not null)")
416 767 macro("amountMentionsShare", f"{100*S['mentions_fields'][0]/M:.1f}", "stats.json", "100*mentions_fields[0]/mentions")
417 768 macro("amountProjects", n(S["projects_fields"][0]), "stats.json:projects_fields[0]", "count(total_amount_usd is not null)")
@@ -420,44 +771,38 @@ macro("amountP25Musd", f"{q[1]/1e6:,.0f}".replace(",", "{,}"), "data/amount_dist
420 771 macro("amountP75Musd", f"{q[3]/1e6:,.0f}".replace(",", "{,}"), "data/amount_dist.csv", "q[3]/1e6")
421 772 macro("amountP99Busd", f"{q[5]/1e9:,.1f}", "data/amount_dist.csv", "q[5]/1e9")
422 773 macro("amountSumTusd", f"{float(ad['sum_gusd'])/1e3:,.1f}", "data/amount_dist.csv", "sum_gusd/1e3")
423 −amt_note = ("\\item Amounts are the largest USD figure cited across the mentions of a project; they mix transaction values, budgets, contract values "
424 − "and estimates and are never summed in the text. ")
425 −if S.get("amount_max") is not None:
426 − macro("amountMaxBusd", f"{S['amount_max']/1e9:,.1f}".replace(",", "{,}"), "stats.json:amount_max", "max(total_amount_usd)/1e9")
427 − amt_note += f"The maximum is {S['amount_max']/1e9:,.1f}~B USD. ".replace(",", "{,}")
428 −if S.get("amount_ge_50b") is not None:
429 − macro("amountGeFiftyB", n(S["amount_ge_50b"]), "stats.json:amount_ge_50b", "count(total_amount_usd >= 50e9)")
430 − amt_note += f"{n(S['amount_ge_50b'])} projects carry an amount of 50~B USD or more. "
431 −if S.get("amount_le_zero") is not None:
432 − macro("amountLeZero", n(S["amount_le_zero"]), "stats.json:amount_le_zero", "count(total_amount_usd <= 0)")
433 −w("tab_amounts_note.tex", amt_note + "\n")
434 774
435 −# ---- knowledge graph --------------------------------------------------------------------
775 +# ---- knowledge graph (appendix) ----------------------------------------------------------------------------------
436 776 kg = rows("kg")
437 −body = "\\begin{tabular}{llr}\n\\toprule\n & Type & Count \\\\\n\\midrule\n"
438 −for r in kg: body += f"{r['k'].capitalize()} & \\texttt{{{r['node_type'].replace('_', '\\_')}}} & {n(r['n'])} \\\\\n"
439 −body += "\\bottomrule\n\\end{tabular}"
440 −w("tab_graph.tex", body)
777 +tab = "\\begin{tabular}{llr}\n\\toprule\n & Type & Count \\\\\n\\midrule\n"
778 +for r in kg: tab += f"{r['k'].capitalize()} & {tt(r['node_type'])} & {n(r['n'])} \\\\\n"
779 +tab += f"\\midrule\nNodes & total & {n(sum(int(r['n']) for r in kg if r['k']=='nodes'))} \\\\\nEdges & total & {n(sum(int(r['n']) for r in kg if r['k']=='edges'))} \\\\\n\\bottomrule\n\\end{{tabular}}"
780 +float_table("tab_graph.tex", "tab:graph", "Knowledge-graph composition: node and edge types", tab,
781 + "Nodes are projected from the resolved projects (one node per company, project, distinct location string, technology tag and partner string); "
782 + "edges are \\texttt{owns} (company--project), \\texttt{located\\_in} and \\texttt{uses}. Partner nodes are created without edges in the current build. "
783 + "Technology tags are free text and are grounded in the section text for only part of the mentions (Table~\\ref{tab:grounding}).", "data/kg.csv")
441 784 macro("kgNodes", n(sum(int(r["n"]) for r in kg if r["k"] == "nodes")), "data/kg.csv", "sum(n) where k=nodes")
442 785 macro("kgEdges", n(sum(int(r["n"]) for r in kg if r["k"] == "edges")), "data/kg.csv", "sum(n) where k=edges")
443 786 for r in kg:
444 787 if r["k"] == "nodes": macro("kgNodes" + r["node_type"].capitalize(), n(r["n"]), "data/kg.csv", f"n where node_type={r['node_type']}")
445 788
446 −# ---- top issuers ---------------------------------------------------------------------------
447 −body = "\\begin{tabular}{llr}\n\\toprule\nTicker & Issuer & Resolved projects \\\\\n\\midrule\n"
448 −for r in rows("top_issuers")[:12]: body += f"{r['ticker']} & {r['company_name'].title().replace('&', '\\&')} & {n(r['projects'])} \\\\\n"
449 −body += "\\bottomrule\n\\end{tabular}"
450 −w("tab_top_issuers.tex", body)
789 +# ---- top issuers (appendix) --------------------------------------------------------------------------------------
790 +tab = "\\begin{tabular}{llr}\n\\toprule\nTicker & Issuer & Resolved projects \\\\\n\\midrule\n"
791 +for r in rows("top_issuers")[:12]: tab += f"{r['ticker']} & {r['company_name'].title().replace('&', '\\&')} & {n(r['projects'])} \\\\\n"
792 +tab += "\\bottomrule\n\\end{tabular}"
793 +float_table("tab_top_issuers.tex", "tab:top_issuers", "Issuers with the most resolved projects", tab,
794 + "Projects under the current resolution key; ties are ordered by ticker. Issuers whose business consists of enumerable sites (mines, wells, routes, data-center "
795 + "sites) accumulate projects by construction of the key, which keys on the first location or name token of each mention (Section~\\ref{sec:resolution}).",
796 + "data/top\\_issuers.csv")
451 797
452 −# ---- Table 9: provenance example (Cheniere Corpus Christi) ------------------------------------
798 +# ---- Table 9: provenance example (Cheniere Corpus Christi) ------------------------------------------------------
453 799 ex = [r for r in rows("example_provenance") if r["ticker"] == "LNG"]
454 −body = "\\begin{tabular}{llllp{6.2cm}}\n\\toprule\nAccession & Filed & Form & Status / amount & Evidence snippet (model-generated description grounded in the section) \\\\\n\\midrule\n"
800 +tab = "\\begin{tabular}{lllp{2.1cm}p{5.4cm}}\n\\toprule\nAccession & Filed & Form & Status / amount & Evidence snippet (model-generated description) \\\\\n\\midrule\n"
455 801 for r in ex[:8]:
456 802 amt = f"{float(r['amount_usd'])/1e9:.1f} B USD" if r["amount_usd"] else "--"
457 803 snip = r["snippet"].replace("&", "\\&").replace("%", "\\%").replace("$", "\\$")[:DI["snippet_chars"]["value"]]
458 − body += f"\\texttt{{{r['accession_number']}}} & {r['filing_date']} & {r['form_type']} & {r['m_status'].replace('_', '\\_')} / {amt} & {snip} \\\\\n"
459 −body += "\\bottomrule\n\\end{tabular}"
460 −w("tab_provenance.tex", body)
804 + tab += f"\\texttt{{{r['accession_number']}}} & {r['filing_date']} & {r['form_type']} & {r['m_status'].replace('_', '\\_')} / {amt} & {snip} \\\\\n"
805 +tab += "\\bottomrule\n\\end{tabular}"
461 806 if ex:
462 807 forms = sorted({r["form_type"] for r in ex[:8]})
463 808 macro("provenanceForms", " and ".join(forms), "data/example_provenance.csv", "distinct form_type of the printed rows")
@@ -466,20 +811,36 @@ if ex:
466 811 macro("provenanceLast", ex[:8][-1]["filing_date"], "data/example_provenance.csv", "max filing_date")
467 812 macro("provenanceMaxAmountBusd", f"{max(float(r['amount_usd']) for r in ex if r['amount_usd'])/1e9:.1f}", "data/example_provenance.csv", "max(amount_usd)/1e9")
468 813 macro("provenanceNameYear", ex[:8][-1]["filing_date"][:4], "data/example_provenance.csv", "filing year of the last mention (representative name source)")
814 + macro("provenanceProjectId", ex[0]["project_id"][:8], "data/example_provenance.csv", "project_id[:8]")
469 815 json.dump({k: ex[0][k] for k in ("project_id", "ticker", "project_name", "project_type", "status", "total_amount_usd", "n_mentions", "first_seen", "last_seen")},
470 816 open(DATA_OUT / "example_project.json", "w"), indent=2)
817 + sc_ex = jload("resolver/composition.json")
818 + float_table("tab_provenance.tex", "tab:provenance", f"Provenance of one resolved project: Cheniere Energy, Corpus Christi liquefaction (project \\texttt{{{ex[0]['project_id'][:8]}\\ldots}})",
819 + tab, f"Snippets are the first {DI['snippet_chars']['value']} characters of the model-generated description stored in \\texttt{{project\\_timeline.snippet}}; "
820 + "the description is a paraphrase, not a quotation, and the character span of the supporting passage is not stored; the full source section is retrievable "
821 + f"through \\texttt{{project\\_mentions.section\\_id}}. All {len(ex[:8])} printed mentions are {' and '.join(forms)} filings. The representative name is that of the "
822 + f"highest-confidence mention (filed {ex[:8][-1]['filing_date'][:4]}) applied retroactively to the whole timeline, and is one admissible choice among "
823 + "mentions tied at the maximum confidence. The key for this issuer and type is the location token ``corpus christi'', so distinct phases share one identifier: "
824 + "the same mentions form "
825 + + (f"{sc_ex['project_count_range_045'].get('k_strict', '')} projects under the strict key and {sc_ex['project_count_range_045'].get('k_cik_type', '')} under the issuer $\\times$ type key" if sc_ex.get("project_count_range_045") else "different numbers of projects under alternative keys")
826 + + " (cluster sizes in Table~\\ref{tab:spec_curve}).", "data/example\\_provenance.csv, documented\\_inputs.json:snippet\\_chars", size="\\scriptsize", colsep="3pt", fit=True)
471 827
472 −# ---- Table 12: data-model audit (Appendix C) as a longtable -------------------------------------
828 +# ---- Table 12: data-model audit (Appendix C) as a longtable ---------------------------------------------------------
473 829 if (D / "datamodel_audit.csv").exists():
474 − body = ("\\begin{longtable}{p{3.1cm}p{8.6cm}p{4.3cm}}\n\\caption{Tables required by the research design, current implementation and status}"
830 + body = ("% Generated by code/make_tables.py from data/datamodel_audit.csv. Longtable: input outside a float.\n"
831 + "{\\footnotesize\n\\begin{longtable}{p{2.6cm}p{6.9cm}p{3.4cm}}\n\\caption{Tables required by the research design, current implementation and status}"
475 832 "\\label{tab:datamodel}\\\\\n\\toprule\nRequired table & Current implementation (database, table, key fields) & Status \\\\\n\\midrule\n\\endfirsthead\n"
476 − "\\toprule\nRequired table & Current implementation (database, table, key fields) & Status \\\\\n\\midrule\n\\endhead\n\\bottomrule\n\\endfoot\n")
833 + "\\multicolumn{3}{l}{\\itshape Table \\thetable{} (continued)}\\\\\n\\toprule\nRequired table & Current implementation (database, table, key fields) & Status \\\\\n\\midrule\n\\endhead\n"
834 + "\\midrule\n\\multicolumn{3}{r}{\\itshape continued on the next page}\\\\\n\\endfoot\n\\bottomrule\n"
835 + "\\multicolumn{3}{p{12.8cm}}{\\scriptsize Status at revision \\texttt{2324b58}; ``partial'' and ``proposed'' rows are schema changes to be added by migration. "
836 + "The \\texttt{amount\\_raw} field is a formatted copy of the coerced float, not the filing's string; the ledger stores no model, prompt or call status.}\\\\\n\\endlastfoot\n")
477 837 for r in rows("datamodel_audit"):
478 − body += f"\\texttt{{{r['required_table'].replace('_', '\\_')}}} & {r['implementation']} & {r['status']} \\\\\n"
479 − body += "\\end{longtable}"
838 + st_ = r['status'].replace('/', '/\\allowbreak{}')
839 + body += f"{ttb(r['required_table'])} & {r['implementation']} & {st_} \\\\\n"
840 + body += "\\end{longtable}\n}"
480 841 w("tab_datamodel.tex", body)
481 842
482 −# ---- Appendix B: candidate gate regex and system prompt, read from the frozen snapshot ----------
843 +# ---- Appendix B: candidate gate regex and system prompt, read from the frozen snapshot ---------------------------
483 844 def _snapshot(name):
484 845 for base in (SNAP, ROOT.parent.parent / "manuscripts" / "FIRC-0001" / "pipeline_code_2324b58" / "project-db" / "spid"):
485 846 for p in (base / name, base / "extract" / name):
@@ -493,15 +854,14 @@ if rules_py:
493 854 for node in ast.walk(tree):
494 855 if isinstance(node, ast.Assign) and any(isinstance(t, ast.Name) and t.id == "_PROJECT_GATE" for t in node.targets):
495 856 call = node.value; arg = call.args[0]
496 − # the pattern is written as adjacent raw-string literals; keep the author's line breaks
497 857 seg = rules_py.read_text().splitlines()[arg.lineno - 1: arg.end_lineno]
498 858 pieces = [re.match(r'\s*r"(.*)"\s*,?\s*$', s).group(1) for s in seg]
499 859 flags = ", ".join(ast.unparse(a) for a in call.args[1:])
500 860 if pieces:
501 861 full = "".join(pieces)
502 − lines = "\n".join(pieces)
503 − w("gate_regex.tex", "\\begin{verbatim}\n" + lines + "\n\\end{verbatim}\n")
504 − macro("gateRegexFlags", esc(flags), str(rules_py.relative_to(ROOT)) if rules_py.is_relative_to(ROOT) else str(rules_py), "re.compile flags")
862 + w("gate_regex.tex", "% Generated by code/make_tables.py from code/audit/spid_snapshot/rules.py (_PROJECT_GATE, three source lines concatenated at run time).\n"
863 + "{\\footnotesize\\begin{verbatim}\n" + "\n".join(pieces) + "\n\\end{verbatim}}\n")
864 + macro("gateRegexFlags", esc(flags), rel(rules_py), "re.compile flags")
505 865 macro("gateRegexLength", str(len(full)), "rules.py:_PROJECT_GATE", "len(pattern)")
506 866 macro("gateRegexAlternatives", str(full.count("|") + 1), "rules.py:_PROJECT_GATE", "number of alternatives")
507 867
@@ -522,127 +882,907 @@ if llm_py and tax_py:
522 882 if types and tmpl and "%s" in tmpl:
523 883 labels = "\n".join(f" - {k}: {v['label']}" for k, v in types.items())
524 884 prompt = tmpl % labels
525 − w("prompt_verbatim.tex", "\\begin{verbatim}\n" + prompt + "\n\\end{verbatim}\n")
885 + w("prompt_verbatim.tex", "% Generated by code/make_tables.py from code/audit/spid_snapshot/llm.py (_SYSTEM) and taxonomy.py (PROJECT_TYPES), substituted as llm.py does.\n"
886 + "{\\footnotesize\\begin{verbatim}\n" + prompt + "\n\\end{verbatim}}\n")
526 887 macro("taxonomyN", str(len(types)), "taxonomy.py:PROJECT_TYPES", "len")
527 − body = "\\begin{tabular}{ll}\n\\toprule\nCode & Label \\\\\n\\midrule\n"
528 − for k, v in types.items(): body += f"\\texttt{{{k.replace('_', '\\_')}}} & {esc(v['label'])} \\\\\n"
529 − body += "\\bottomrule\n\\end{tabular}"
530 − w("tab_taxonomy.tex", body)
531 −
532 −# ---- Stage D audit tables from results/ (generic CSV -> tabular; skipped when absent) ---------------
533 −def csv_table(texname, path, caption_cols=None, max_rows=60):
534 − if not path.exists():
535 − print("skip", texname, "(missing", path.relative_to(ROOT), ")"); return
536 − with open(path, newline="") as f:
537 − rd = csv.DictReader(f); cols = rd.fieldnames; data = list(rd)
538 − def fmt(v):
539 − try:
540 − x = float(v)
541 − if x.is_integer() and abs(x) >= 1e3: return n(x)
542 − return v if x.is_integer() else f"{x:,.3f}".rstrip("0").rstrip(".").replace(",", "{,}")
543 − except ValueError:
544 − return esc(v)
545 − spec = "l" + "r" * (len(cols) - 1)
546 − body = f"\\begin{{tabular}}{{{spec}}}\n\\toprule\n" + " & ".join(esc(c) for c in cols) + " \\\\\n\\midrule\n"
547 − for r in data[:max_rows]: body += " & ".join(fmt(r[c]) for c in cols) + " \\\\\n"
548 − if len(data) > max_rows: body += f"\\multicolumn{{{len(cols)}}}{{l}}{{\\ldots {len(data) - max_rows} more rows in \\texttt{{{esc(str(path.relative_to(ROOT)))}}}}} \\\\\n"
549 − body += "\\bottomrule\n\\end{tabular}"
550 − w(texname, body)
551 −
552 −csv_table("tab_spec_curve.tex", R / "resolver" / "spec_curve.csv")
553 −csv_table("tab_grounding.tex", R / "grounding" / "grounding_by_field_form_item.csv")
554 −csv_table("tab_focus.tex", R / "focus" / "focus_coverage_by_form_item.csv")
555 −csv_table("tab_cohort.tex", R / "runs" / "cohort_by_run.csv" if (R / "runs" / "cohort_by_run.csv").exists() else D / "cohort_by_run.csv")
556 −csv_table("tab_fp_classes.tex", R / "fp_classes" / "financing_regex_by_item_type.csv")
557 −csv_table("tab_timeseries_cohort.tex", R / "timeseries" / "first_seen_fixed_cohort.csv")
558 −csv_table("tab_benchmark_8k.tex", R / "benchmark_8k" / "item_vs_type.csv")
559 −csv_table("tab_rules_agreement.tex", R / "rules" / "agreement_by_form_item.csv")
560 −
561 −# ---- macros from the Stage D audit results (results/**.json; skipped when absent) ------------------
562 −def jload(rel):
563 − p = R / rel
564 − return json.load(open(p)) if p.exists() else {}
888 + tab = "\\begin{tabular}{ll}\n\\toprule\nCode & Label \\\\\n\\midrule\n"
889 + for k, v in types.items(): tab += f"{tt(k)} & {esc(v['label'])} \\\\\n"
890 + tab += "\\bottomrule\n\\end{tabular}"
891 + float_table("tab_taxonomy.tex", "tab:taxonomy", f"The {len(types)}-category SPID project taxonomy", tab,
892 + "Codes and labels read from \\texttt{spid/taxonomy.py} of the frozen snapshot (\\texttt{code/audit/spid\\_snapshot/}, SHA-256 in \\texttt{SHA256SUMS}); "
893 + "the labels are passed verbatim to the model in the order shown (Appendix~\\ref{app:prompt}). A label outside the list is mapped by substring to the "
894 + "closest code or, failing that, to \\texttt{technology\\_deployment}.", "code/audit/spid\\_snapshot/taxonomy.py")
895 +
896 +# ---- Table: field-level grounding (mechanical containment) --------------------------------------------------------
897 +FIELD = {"years": "Cited years", "partners": "Partners", "amount_number": "Amount (number)", "amount_with_currency": "Amount (number + currency token within 40 chars)",
898 + "locations": "Locations", "technologies": "Technology tags"}
899 +gg = R / "grounding" / "grounding_by_group.csv"; gas = R / "grounding" / "grounding_all_structured.csv"; gel = R / "grounding" / "grounding_element_level.csv"
900 +if gg.exists() and gas.exists():
901 + G = rows(gg.stem, gg.parent)
902 + forms = ["10-K", "10-Q", "8-K"]
903 + def gget(grouping, field, group):
904 + return next((r for r in G if r["grouping"] == grouping and r["field"] == field and r["group"] == group), None)
905 + tab = ("\\begin{tabular}{lrrrrr}\n\\toprule\n\\multicolumn{6}{l}{\\itshape Panel A: share of mentions whose field is found literally in the stored section text (\\%, 95\\% CI)} \\\\\n"
906 + "Field & Mentions with the field & All forms & 10-K & 10-Q & 8-K \\\\\n\\midrule\n")
907 + for f in ("years", "partners", "amount_number", "amount_with_currency", "locations", "technologies"):
908 + a = gget("all", f, "all")
909 + if not a: continue
910 + cells = [f"{100*float(a['grounded_share']):.1f} [{100*float(a['ci_low']):.1f}, {100*float(a['ci_high']):.1f}]"]
911 + for fm in forms:
912 + x = gget("form", f, fm); cells.append(f"{100*float(x['grounded_share']):.1f}" if x else "--")
913 + tab += f"{FIELD[f]} & {n(a['n_mentions'])} & " + " & ".join(cells) + " \\\\\n"
914 + if gel.exists():
915 + tab += "\\midrule\n\\multicolumn{6}{l}{\\itshape Panel B: element level (every listed year, partner, location or tag counted separately)} \\\\\n"
916 + for r in rows(gel.stem, gel.parent):
917 + tab += f"{FIELD.get(r['field'], r['field'])} & {n(r['elements'])} elements & {pct(r['pct'])} & & & \\\\\n"
918 + A = {r["g"]: r for r in rows(gas.stem, gas.parent)}
919 + tab += "\\midrule\n\\multicolumn{6}{l}{\\itshape Panel C: mentions with every structured field grounded (\\%), by form, run and confidence bin} \\\\\n"
920 + tab += f"All mentions with at least one structured field & {n(A['all']['n_with_fields'])} & {pct(A['all']['pct'])} & {pct(A['10-K']['pct'])} & {pct(A['10-Q']['pct'])} & {pct(A['8-K']['pct'])} \\\\\n"
921 + tab += f"By run: June (backfilled) / October & {n(A['backfilled_june']['n_with_fields'])} / {n(A['october']['n_with_fields'])} & {pct(A['backfilled_june']['pct'])} / {pct(A['october']['pct'])} & & & \\\\\n"
922 + bins = [k for k in A if "-" in k and k[0].isdigit()]
923 + for b in bins: tab += f"\\quad confidence bin {b} & {n(A[b]['n_with_fields'])} & {pct(A[b]['pct'])} & & & \\\\\n"
924 + tab += "\\bottomrule\n\\end{tabular}"
925 + fbd = jload("grounding/fallback_bounds.json")
926 + fb_note = ""
927 + if fbd:
928 + fb_note = (f" Upper bounds on the regex back-fill from the model's own paraphrase (\\texttt{{llm.py}}): the stored years equal the regex output on the description for "
929 + f"{n(fbd['years_eq_regex_desc'])} of {n(fbd['years_nonempty'])} mentions with years ({100*fbd['years_eq_regex_desc']/fbd['years_nonempty']:.0f}\\%) and the "
930 + f"technology list for {n(fbd['techs_eq_regex_desc'])} of {n(fbd['techs_nonempty'])} ({100*fbd['techs_eq_regex_desc']/fbd['techs_nonempty']:.0f}\\%); "
931 + f"{n(fbd['years_not_subset_of_text'])} mentions cite a year absent from the section text.")
932 + macro("yearsRegexEqualPct", f"{100*fbd['years_eq_regex_desc']/fbd['years_nonempty']:.0f}", "results/grounding/fallback_bounds.json", "100*years_eq_regex_desc/years_nonempty")
933 + macro("techsRegexEqualPct", f"{100*fbd['techs_eq_regex_desc']/fbd['techs_nonempty']:.0f}", "results/grounding/fallback_bounds.json", "100*techs_eq_regex_desc/techs_nonempty")
934 + macro("yearsNotInText", n(fbd["years_not_subset_of_text"]), "results/grounding/fallback_bounds.json", "years_not_subset_of_text")
935 + macro("techDeployMentionedNoSignal", n(fbd["tech_deploy_mentioned_no_any_signal"]), "results/grounding/fallback_bounds.json", "tech_deploy_mentioned_no_any_signal")
936 + macro("techDeployMentionedTotal", n(fbd["tech_deploy_total"][1]), "results/grounding/fallback_bounds.json", "tech_deploy_total[1]")
937 + float_table("tab_grounding.tex", "tab:grounding", "Mechanical grounding of the structured fields of all stored mentions in the stored section text", tab,
938 + f"Population: all {n(M)} stored mentions, joined to the text of their section as stored (legacy June text for the S\\&P~500 10-Ks). A field is ``grounded'' "
939 + "when every element of the list (years, partners, locations, technologies, case-folded) or the amount (tested in units, thousands, millions and billions with "
940 + "one to three significant digits) occurs literally in that text; a currency token is \\$, USD, dollar, million or billion within 40 characters of the number. "
941 + "Confidence intervals are percentile bootstraps with 1{,}000 replicates clustered by section. Grounding is a necessary condition for correctness, not a "
942 + "measure of it: a grounded year can belong to another initiative, and an ungrounded location can be a correct normalisation (``Texas'' for ``Austin''); "
943 + "precision and recall require the human labels of gate (d). Panel C counts mentions with at least one structured field." + fb_note,
944 + "results/grounding/grounding\\_by\\_group.csv, grounding\\_element\\_level.csv, grounding\\_all\\_structured.csv, fallback\\_bounds.json", size="\\footnotesize", colsep="4pt", fit=True)
945 + for f in ("years", "partners", "amount_number", "amount_with_currency", "locations", "technologies"):
946 + a = gget("all", f, "all")
947 + if a:
948 + cam = "".join(p.capitalize() for p in f.split("_"))
949 + macro(f"grounded{cam}Pct", f"{100*float(a['grounded_share']):.1f}", "results/grounding/grounding_by_group.csv", f"grounded_share all/{f}")
950 + macro(f"grounded{cam}CI", f"[{100*float(a['ci_low']):.1f}, {100*float(a['ci_high']):.1f}]", "results/grounding/grounding_by_group.csv", f"ci all/{f}")
951 + for fm in forms:
952 + x = gget("form", f, fm)
953 + if x: macro(f"grounded{cam}{fm.replace('-', '')}Pct", f"{100*float(x['grounded_share']):.1f}", "results/grounding/grounding_by_group.csv", f"grounded_share form={fm}/{f}")
954 + for k, mname in (("all", "groundedAllFieldsPct"), ("10-K", "groundedAllFieldsTenKPct"), ("10-Q", "groundedAllFieldsTenQPct"), ("8-K", "groundedAllFieldsEightKPct"),
955 + ("backfilled_june", "groundedAllFieldsJunePct"), ("october", "groundedAllFieldsOctoberPct")):
956 + if k in A: macro(mname, pct(A[k]["pct"]), "results/grounding/grounding_all_structured.csv", f"pct where g={k}")
957 + macro("groundedAllFieldsN", n(A["all"]["n_with_fields"]), "results/grounding/grounding_all_structured.csv", "n_with_fields where g=all")
565 958
959 +# ---- Table: specification curve of the project count over resolution keys -----------------------------------------
960 +KEYLAB = {"k_cik_type": "Issuer $\\times$ type (no location, no name)", "k_type_dropped": "Current key without the type", "k_name_only": "Issuer $\\times$ type $\\times$ name token (location ignored)",
961 + "k_current": "Current key (location, else name token)", "k_city_normalised": "Current key, city-normalised locations", "k_current_stopwords": "Current key, extended stop-word list",
962 + "k_two_tokens": "Issuer $\\times$ type $\\times$ two name tokens", "k_strict": "Strict: full normalised name + location", "k_mention_level": "No resolution (one project per mention)"}
963 +sc_path = R / "resolver" / "spec_curve.csv"; cp = jload("resolver/composition.json"); ti = jload("resolver/ties_idempotence.json")
964 +if sc_path.exists():
965 + sc = rows(sc_path.stem, sc_path.parent)
966 + thrs = sorted({float(r["threshold"]) for r in sc}); t0_, t1_ = thrs[0], thrs[-1]
967 + order = [k for k in KEYLAB if any(r["key"] == k for r in sc)]
968 + tab = ("\\begin{tabular}{lrrrrrr}\n\\toprule\nResolution key & " + H(f"Projects\\\\($\\geq {t0_}$)") + " & " + H("Single-mention\\\\projects (\\%)") + " & " +
969 + H("Projects with\\\\$> 10$ mentions (\\%)") + " & " + H("Mentions\\\\per project") + " & " + H("Cheniere\\\\cluster size") + " & " + H(f"Projects\\\\($\\geq {t1_}$)") + " \\\\\n\\midrule\n")
970 + for k in order:
971 + a = next(r for r in sc if r["key"] == k and float(r["threshold"]) == t0_); b = next(r for r in sc if r["key"] == k and float(r["threshold"]) == t1_)
972 + lab = KEYLAB[k] + (" $\\dagger$" if k == "k_current" else "")
973 + tab += f"{lab} & {n(a['projects'])} & {pct(a['single_mention_pct'])} & {pct(a['gt10_mention_pct'])} & {float(a['mean_mentions']):.2f} & {a['example_cluster_size_cheniere']} & {n(b['projects'])} \\\\\n"
974 + tab += "\\bottomrule\n\\end{tabular}"
975 + comp_note = ""
976 + if cp.get("projects_by_key_branch"):
977 + pb = dict((str(k), v) for k, v in cp["projects_by_key_branch"]); mb_ = dict((str(k), v) for k, v in cp.get("mentions_by_key_branch", []))
978 + tn = rows("top_name_tokens", R / "resolver") if (R / "resolver" / "top_name_tokens.csv").exists() else []
979 + comp_note = (f" Under the current key {n(pb.get('name_token', 0))} projects ({100*pb.get('name_token', 0)/P:.1f}\\%) are keyed on a name token because the mention has no "
980 + f"location, {n(pb.get('location', 0))} on a location and {n(cp.get('projects_keyed_general', 0))} on the fallback ``general''"
981 + + (f"; the single token ``{esc(tn[0]['name_tok'])}'' absorbs {n(tn[0]['mentions'])} mentions into {n(tn[0]['projects'])} projects (Table~\\ref{{tab:top_name_tokens}})" if tn else "")
982 + + ".")
983 + tie_note = (f" The stored table is not exactly reproducible: {n(ti['projects_with_tie_at_max_confidence'])} projects have several mentions at the maximum confidence "
984 + f"(\\texttt{{arg\\_max}} ties), and re-running the authors' SQL changes {n(ti['rebuilt_vs_stored_diff'][0])} representative names and {n(ti['rebuilt_vs_stored_diff'][2])} "
985 + "descriptions while reproducing every project identifier." if ti else "")
986 + float_table("tab_spec_curve.tex", "tab:spec_curve", "Specification curve of the project count over alternative resolution keys and confidence thresholds", tab,
987 + f"Every key is applied to the same {n(M)} stored mentions, rebuilt from \\texttt{{resolve.py}} in a temporary table on the master node; $\\dagger$ marks the key "
988 + "of the released \\texttt{projects} table, whose identifier set is reproduced exactly. ``Cheniere cluster size'' is the number of projects formed by the mentions "
989 + f"of the Table~\\ref{{tab:provenance}} example. Thresholds drop mentions below the stated confidence before resolution. The project count is therefore a "
990 + f"property of the key: {n(min(int(float(r['projects'])) for r in sc if float(r['threshold']) == t0_))}--{n(max(int(float(r['projects'])) for r in sc if float(r['threshold']) == t0_))} "
991 + f"at the release threshold, and the single-mention share and projects-per-issuer statistics move with it." + comp_note + tie_note,
992 + "results/resolver/spec\\_curve.csv, composition.json, ties\\_idempotence.json, top\\_name\\_tokens.csv", size="\\scriptsize", colsep="3pt", fit=True)
993 + at0 = [r for r in sc if float(r["threshold"]) == t0_]; pr = [int(float(r["projects"])) for r in at0]
994 + macro("projectCountRangeKeys", f"{n(min(pr))}--{n(max(pr))}", "results/resolver/spec_curve.csv", f"min/max projects over keys at threshold {t0_}")
995 + macro("projectCountRangeKeysN", str(len(at0)), "results/resolver/spec_curve.csv", f"number of keys at threshold {t0_}")
996 + nonml = [int(float(r["projects"])) for r in at0 if r["key"] != "k_mention_level"]
997 + macro("projectCountRangeResolvedKeys", f"{n(min(nonml))}--{n(max(nonml))}", "results/resolver/spec_curve.csv", f"min/max projects over keys at {t0_} excluding the mention level")
998 + pall = [int(float(r["projects"])) for r in sc]
999 + macro("projectCountRangeAll", f"{n(min(pall))}--{n(max(pall))}", "results/resolver/spec_curve.csv", "min/max projects over all keys x thresholds")
1000 + cur = [r for r in at0 if r["key"] == "k_current"]
1001 + if cur: macro("projectCountCurrentKey", n(cur[0]["projects"]), "results/resolver/spec_curve.csv", f"key=k_current at {t0_}")
1002 + for k in ("k_strict", "k_cik_type", "k_type_dropped", "k_name_only"):
1003 + r_ = next((r for r in at0 if r["key"] == k), None)
1004 + if r_: macro("projectCount" + "".join(p.capitalize() for p in k.split("_")[1:]), n(r_["projects"]), "results/resolver/spec_curve.csv", f"key={k} at {t0_}")
1005 + c9 = next((r for r in sc if r["key"] == "k_current" and float(r["threshold"]) == t1_), None)
1006 + if c9: macro("projectCountCurrentKeyHighThreshold", n(c9["projects"]), "results/resolver/spec_curve.csv", f"key=k_current at {t1_}")
1007 + macro("specCurveThresholdMax", str(t1_), "results/resolver/spec_curve.csv", "max threshold")
1008 +
1009 +# ---- Table: top name tokens (appendix) --------------------------------------------------------------------------------
1010 +tn_path = R / "resolver" / "top_name_tokens.csv"
1011 +if tn_path.exists():
1012 + tn = rows(tn_path.stem, tn_path.parent)
1013 + tab = "\\begin{tabular}{lrrrr}\n\\toprule\nName token (key) & Mentions & Projects & " + H("Share of token-keyed\\\\mentions (\\%)") + " & " + H("Share of token-keyed\\\\projects (\\%)") + " \\\\\n\\midrule\n"
1014 + for r in tn[:15]:
1015 + tab += f"{tt(r['name_tok'])} & {n(r['mentions'])} & {n(r['projects'])} & {pct(r['pct_of_tokenkeyed_mentions'])} & {pct(r['pct_of_tokenkeyed_projects'])} \\\\\n"
1016 + tab += "\\bottomrule\n\\end{tabular}"
1017 + float_table("tab_top_name_tokens.tex", "tab:top_name_tokens", "Most frequent name tokens used as resolution keys for location-less mentions", tab,
1018 + "The key for a mention without an extracted location is the first token of at least four letters in the normalised project name (after a short stop-word list). "
1019 + "Generic head words therefore merge unrelated initiatives of the same issuer and type into one project; the full list is in "
1020 + "\\texttt{results/resolver/top\\_name\\_tokens.csv}.", "results/resolver/top\\_name\\_tokens.csv")
1021 + macro("topNameTokens", ", ".join(f"\\texttt{{{esc(r['name_tok'])}}} ({float(r['pct_of_tokenkeyed_projects']):.1f}\\%)" for r in tn[:10]), "results/resolver/top_name_tokens.csv", "top-10 tokens, pct of token-keyed projects")
1022 + macro("topNameTokensProjectsPct", f"{sum(float(r['pct_of_tokenkeyed_projects']) for r in tn[:10]):.1f}", "results/resolver/top_name_tokens.csv", "sum of pct_of_tokenkeyed_projects over the top 10")
1023 + macro("topNameToken", esc(tn[0]["name_tok"]), "results/resolver/top_name_tokens.csv", "name_tok[0]")
1024 + macro("topNameTokenMentions", n(tn[0]["mentions"]), "results/resolver/top_name_tokens.csv", "mentions[0]")
1025 + macro("topNameTokenProjects", n(tn[0]["projects"]), "results/resolver/top_name_tokens.csv", "projects[0]")
1026 +
1027 +# ---- Table: over-merge indicators by category (appendix) -------------------------------------------------------------
1028 +if om:
1029 + tab = ("\\begin{tabular}{lrrrrr}\n\\toprule\nCategory & Projects & " + H("$\\geq 2$ distinct\\\\names (\\%)") + " & " + H("$\\geq 3$ distinct\\\\names (\\%)") + " & " +
1030 + H("$\\geq 3$ distinct first partners\\\\(\\% of projects with a partner)") + " & " + H("All names distinct\\\\(\\% of multi-mention)") + " \\\\\n\\midrule\n")
1031 + for r in om.values():
1032 + tab += f"{LAB.get(r['project_type'], r['project_type'])} & {n(r['projects'])} & {pct(r['pct_ge2_names'])} & {pct(r['pct_ge3_names'])} & {pct(r['pct_ge3_partners_among_with_partner'])} & {pct(r['pct_multi_all_names_distinct'])} \\\\\n"
1033 + tab += "\\bottomrule\n\\end{tabular}"
1034 + aoc = cp.get("amount_from_other_counterparty_ma", [0, 0, 0])
1035 + float_table("tab_overmerge.tex", "tab:overmerge", "Over-merge indicators of the resolution key, by category", tab,
1036 + "Distinct names and partners are counted over the mentions of each project (lower-cased); three or more distinct counterparties in one M\\&A project is an "
1037 + f"over-merge by construction. For {n(aoc[0])} of {n(aoc[1])} M\\&A projects in which both are named, the project amount comes from a mention naming a different "
1038 + "counterparty than the representative mention. These are indicators, not error rates: the linkage audit of gate (d) has not been run.",
1039 + "results/resolver/overmerge\\_by\\_type.csv, composition.json", size="\\scriptsize", colsep="3pt", fit=True)
1040 + macro("maProjectsAmountOtherCounterparty", n(aoc[0]), "results/resolver/composition.json", "amount_from_other_counterparty_ma[0]")
1041 + macro("maProjectsBothNamed", n(aoc[1]), "results/resolver/composition.json", "amount_from_other_counterparty_ma[1]")
1042 + macro("maGeThreeNamesPct", pct(om["ma_integration"]["pct_ge3_names"]), "results/resolver/overmerge_by_type.csv", "pct_ge3_names where project_type=ma_integration")
1043 +
1044 +# ---- Table: June -> October reconciliation (appendix) -----------------------------------------------------------------
1045 +jo = R / "resolver" / "june_october_reconciliation.csv"; joj = jload("resolver/june_october_reconciliation.json")
1046 +if jo.exists():
1047 + tab = "\\begin{tabular}{llrrrrr}\n\\toprule\nCohort & Run & Form & Mentions & " + H("Projects\\\\touched") + " & Filings & Issuers \\\\\n\\midrule\n"
1048 + for r in rows(jo.stem, jo.parent):
1049 + coh = "S\\&P~500" if r["in_sp500"] == "True" else "Russell proxy only"
1050 + tab += f"{coh} & {RUNLAB.get(r['run'], r['run'])} & {r['form_type']} & {n(r['mentions'])} & {n(r['projects_touched'])} & {n(r['filings'])} & {n(r['issuers'])} \\\\\n"
1051 + tab += "\\bottomrule\n\\end{tabular}"
1052 + float_table("tab_june_october.tex", "tab:june_october", "Mentions by cohort, run and form: reconciliation of the June (S\\&P~500) and October (Russell proxy) runs", tab,
1053 + "The June run covered the 10-Ks (legacy segmenter), the 8-Ks and 3{,}710 10-Qs of the S\\&P~500; the October run added the remaining S\\&P~500 10-Qs and the "
1054 + "whole Russell-only cohort. ``Projects touched'' counts distinct current-key projects with at least one mention in the row, so projects spanning rows are counted "
1055 + "more than once. The backfilled block alone resolves to the June release's project count, which reconciles the two releases without any resolver change.",
1056 + "results/resolver/june\\_october\\_reconciliation.csv")
1057 +
1058 +# ---- Table: focus-window coverage ----------------------------------------------------------------------------------------
1059 +fbf = R / "focus" / "focus_coverage_by_form.csv"; sk = jload("focus/stats_keys.json")
1060 +if fcp.exists() and fbf.exists():
1061 + tab = ("\\begin{tabular}{llrrrrrrrr}\n\\toprule\nForm & Item & " + H("Ledgered\\\\rows") + " & " + H("Over 9{,}000\\\\chars (\\%)") + " & " + H("Median\\\\chars") + " & " +
1062 + H("Share shown\\\\P10") + " & " + H("Share shown\\\\median") + " & " + H("Share shown\\\\P90") + " & " + H("Rows shown\\\\$< 25$\\% (\\%)") + " & " +
1063 + H("Mentions from rows\\\\shown $< 25$\\% (\\%)") + " \\\\\n\\midrule\n")
1064 + def frow(lab1, lab2, r):
1065 + return (f"{lab1} & {lab2} & {n(r['n'])} & {pct(r['pct_over_9000'])} & {n(r['chars_p50'])} & {100*float(r['shown_p10']):.0f} & {100*float(r['shown_p50']):.0f} & "
1066 + f"{100*float(r['shown_p90']):.0f} & {pct(r['pct_shown_lt_25'])} & {pct(r['pct_mentions_from_lt25'])} \\\\\n")
1067 + last = None
1068 + for r in rows(fcp.stem, fcp.parent):
1069 + if last and r["form"] != last: tab += "\\midrule\n"
1070 + tab += frow(r["form"], tt(r["item"]), r); last = r["form"]
1071 + tab += "\\midrule\n"
1072 + for r in rows(fbf.stem, fbf.parent): tab += frow(r["form"], "all items", r)
1073 + tab += "\\bottomrule\n\\end{tabular}"
1074 + float_table("tab_focus.tex", "tab:focus", "Focus-window coverage: share of each ledgered section's text actually shown to the model, by form and item", tab,
1075 + f"The snapshot's \\texttt{{\\_focus}} function was replayed on all {n(S['ledger_total'])} ledgered sections (the replicated spans equal the real output). "
1076 + "Sections up to 9{,}000 characters are shown whole; longer sections are reduced to windows around candidate-gate hits up to the budget, so the ``share shown'' is "
1077 + "the fraction of the section's characters contained in the text sent to the model. The last column is the share of the item's ledger mentions that come from "
1078 + f"sections of which less than a quarter was shown ({n(sk.get('mentions_from_sections_shown_lt_25', 0))} of {n(sk.get('mentions_total', 0))} ledger mentions overall). "
1079 + "No user message reached the 14{,}000-character cut. Shares are over all ledgered rows, including gate-rejected ones (calls-only shares in "
1080 + "\\texttt{results/focus/focus\\_coverage\\_calls\\_only\\_by\\_form\\_item.csv}). Coverage of the text is not recall: what the model missed inside the shown windows is unmeasured.",
1081 + "results/focus/focus\\_coverage\\_by\\_form\\_item.csv, focus\\_coverage\\_by\\_form.csv, stats\\_keys.json", size="\\scriptsize", colsep="2.5pt", fit=True)
1082 + for k, mname, fmt in (("ledger_10k_mdna_shown_p50", "tenKmdnaShownMedianPct", lambda v: f"{100*v:.1f}"), ("ledger_10k_mdna_last_p50", "tenKmdnaLastOffsetMedianPct", lambda v: f"{100*v:.0f}"),
1083 + ("ledger_10k_mdna_pct_shown_lt_25", "tenKmdnaShownLtQuarterPct", lambda v: f"{v:.1f}"), ("ledger_sections_over_9000_chars", "ledgerSectionsOverBudget", n),
1084 + ("calls_over_9000_chars", "callsOverBudget", n), ("mentions_from_sections_shown_lt_25", "mentionsFromShownLtQuarter", n),
1085 + ("mean_shown_frac_over_budget", "meanShownOverBudgetPct", lambda v: f"{100*v:.1f}"), ("ledger_10k_mdna_median_chars", "tenKmdnaMedianChars", n),
1086 + ("msg_truncated_14k", "messagesTruncated", n)):
1087 + if sk.get(k) is not None: macro(mname, fmt(sk[k]), "results/focus/stats_keys.json", k)
1088 + if sk.get("mentions_from_sections_shown_lt_25") and sk.get("mentions_total"):
1089 + macro("mentionsFromShownLtQuarterPct", f"{100*sk['mentions_from_sections_shown_lt_25']/sk['mentions_total']:.1f}", "results/focus/stats_keys.json", "100*mentions_from_sections_shown_lt_25/mentions_total")
1090 + if sk.get("ledger_sections_over_9000_chars") and S.get("ledger_total"):
1091 + macro("ledgerSectionsOverBudgetPct", f"{100*sk['ledger_sections_over_9000_chars']/S['ledger_total']:.0f}", "results/focus/stats_keys.json", "100*over_9000/ledger_total")
1092 + for r in rows(fbf.stem, fbf.parent):
1093 + macro("mentionsFromShownLtQuarter" + r["form"].replace("-", "") + "Pct", pct(r["pct_mentions_from_lt25"], 0), "results/focus/focus_coverage_by_form.csv", f"pct_mentions_from_lt25 where form={r['form']}")
1094 + mdl = R / "focus" / "mdna_10k_short_by_year.csv"
1095 + if mdl.exists():
1096 + md_ = rows(mdl.stem, mdl.parent)
1097 + macro("tenKmdnaShortSections", n(sum(int(r["lt30_words"]) for r in md_)), "results/focus/mdna_10k_short_by_year.csv", "sum(lt30_words)")
1098 + macro("tenKmdnaParsedSections", n(sum(int(r["mdna_sections"]) for r in md_)), "results/focus/mdna_10k_short_by_year.csv", "sum(mdna_sections)")
1099 + macro("tenKmdnaShortPct", f"{100*sum(int(r['lt30_words']) for r in md_)/sum(int(r['mdna_sections']) for r in md_):.1f}", "results/focus/mdna_10k_short_by_year.csv", "100*sum(lt30)/sum(sections)")
1100 +
1101 +# ---- Table: financing / buyback false-positive classes ----------------------------------------------------------------------
1102 +fpt = R / "fp_classes" / "financing_regex_by_type.csv"; fps = jload("fp_classes/summary.json"); fterms = R / "fp_classes" / "financing_regex_terms.csv"
1103 +if fpath.exists() and fpt.exists() and fps:
1104 + tab = "\\begin{tabular}{llrrr@{\\hspace{1.5em}}lrrr}\n\\toprule\n\\multicolumn{5}{l}{\\itshape Panel A: by form and item} & \\multicolumn{4}{l}{\\itshape Panel B: by category} \\\\\n"
1105 + tab += "Form & Item & Mentions & Matched & \\% & Category & Mentions & Matched & \\% \\\\\n\\midrule\n"
1106 + A_ = sorted(rows(fpath.stem, fpath.parent), key=lambda r: (r["form_type"], -int(r["mentions"])))
1107 + B_ = sorted([r for r in rows(fpt.stem, fpt.parent) if int(r["matched"]) > 0], key=lambda r: -int(r["matched"]))
1108 + for i in range(max(len(A_), len(B_))):
1109 + a = A_[i] if i < len(A_) else None; b = B_[i] if i < len(B_) else None
1110 + tab += ((f"{a['form_type']} & {tt(a['item'])} & {n(a['mentions'])} & {n(a['matched'])} & {pct(a['pct'])}" if a else " & & & & ") + " & " +
1111 + (f"{LAB.get(b['project_type'], b['project_type'])} & {n(b['mentions'])} & {n(b['matched'])} & {pct(b['pct'])}" if b else " & & & ") + " \\\\\n")
1112 + mm = fps["mentions_matched"]
1113 + tab += f"\\midrule\nAll & & {n(mm[1])} & {n(mm[0])} & {pct(mm[2])} & All & {n(mm[1])} & {n(mm[0])} & {pct(mm[2])} \\\\\n\\bottomrule\n\\end{{tabular}}"
1114 + terms = rows(fterms.stem, fterms.parent)[:6] if fterms.exists() else []
1115 + ic = fps.get("item2_collision", [])
1116 + float_table("tab_fp_classes.tex", "tab:fp_classes", "Financing-instrument, buyback and dividend mentions: a construct-violation class detectable by pattern", tab,
1117 + "A mention is matched when its lower-cased name or description contains \\texttt{repurchase|buy-?back|dividend|credit facility|revolving|term loan|notes? (due|offering)|"
1118 + "at-the-market|senior notes|commercial paper}" + (f" (most frequent terms: {', '.join(esc(t['fin_term']) + ' ' + n(t['n']) for t in terms)})" if terms else "") +
1119 + f". These instruments are not strategic projects under the construct of Section~\\ref{{sec:construct}}, yet the gate word ``program'' and the prompt admit them; "
1120 + f"{n(fps['projects_matched_rep'][1])} projects ({100*fps['projects_matched_rep'][1]/P:.1f}\\%) have at least one matched mention and {n(fps['projects_matched_rep'][0])} a matched "
1121 + f"representative name or description. Matched mentions carry {fps['matched_amount_gusd'][0]/1e3:.1f} of the {fps['matched_amount_gusd'][1]/1e3:.1f}~T USD of mention amounts. "
1122 + "The pattern is a lower bound on the class (no human label has confirmed any match or non-match) and is applied to the stored paraphrase, not to the filing text."
1123 + + (f" Part~I/Part~II ``Item~2'' collisions of the 10-Q segmenter affect {n(ic[3])} \\texttt{{unregistered\\_sales}} sections above 3{{,}}000 words ({ic[4]:.1f}\\% of {n(ic[0])} pairs), "
1124 + f"{n(ic[7])} of them with an MD\\&A sibling under 500 words." if ic else ""),
1125 + "results/fp\\_classes/financing\\_regex\\_by\\_item.csv, financing\\_regex\\_by\\_type.csv, financing\\_regex\\_terms.csv, summary.json", size="\\scriptsize", colsep="3pt", fit=True)
1126 + macro("financingMentions", n(mm[0]), "results/fp_classes/summary.json", "mentions_matched[0]")
1127 + macro("financingMentionsPct", pct(mm[2]), "results/fp_classes/summary.json", "mentions_matched[2]")
1128 + macro("financingProjectsAnyMention", n(fps["projects_matched_rep"][1]), "results/fp_classes/summary.json", "projects_matched_rep[1]")
1129 + macro("financingProjectsRep", n(fps["projects_matched_rep"][0]), "results/fp_classes/summary.json", "projects_matched_rep[0]")
1130 + macro("financingAmountTusd", f"{fps['matched_amount_gusd'][0]/1e3:.1f}", "results/fp_classes/summary.json", "matched_amount_gusd[0]/1e3")
1131 + macro("mentionAmountTotalTusd", f"{fps['matched_amount_gusd'][1]/1e3:.1f}", "results/fp_classes/summary.json", "matched_amount_gusd[1]/1e3")
1132 + us = fps.get("unregistered_sales_matched", [0, 1])
1133 + macro("financingUnregisteredSalesPct", f"{100*us[0]/us[1]:.1f}", "results/fp_classes/summary.json", "100*unregistered_sales_matched[0]/[1]")
1134 + for r in rows(fpt.stem, fpt.parent):
1135 + if r["project_type"] in ("capex_program", "cost_reduction", "ma_integration"):
1136 + macro("financing" + "".join(p.capitalize() for p in r["project_type"].split("_")) + "Pct", pct(r["pct"]), "results/fp_classes/financing_regex_by_type.csv", f"pct where project_type={r['project_type']}")
1137 + fpf = R / "fp_classes" / "financing_regex_by_form.csv"
1138 + if fpf.exists():
1139 + for r in rows(fpf.stem, fpf.parent): macro("financing" + r["form_type"].replace("-", "") + "Pct", pct(r["pct"]), "results/fp_classes/financing_regex_by_form.csv", f"pct where form_type={r['form_type']}")
1140 + if ic:
1141 + macro("itemTwoCollisionSections", n(ic[3]), "results/fp_classes/summary.json", "item2_collision[3] (unreg_gt_3000)")
1142 + macro("itemTwoCollisionSwapCandidates", n(ic[7]), "results/fp_classes/summary.json", "item2_collision[7]")
1143 +
1144 +# ---- Table: 8-K item-code consistency (proxy) ---------------------------------------------------------------------------------
1145 +b8 = R / "benchmark_8k" / "item_vs_type.csv"; b8s = jload("benchmark_8k/summary.json")
1146 +if b8.exists():
1147 + B8 = [r for r in rows(b8.stem, b8.parent) if r["scope"] == "all_8k_sections" and r["group"] == "all"]
1148 + tab = ("\\begin{tabular}{llrrrrr}\n\\toprule\nCategory & 8-K item code & " + H("Sections with\\\\the item") + " & " + H("P(category $\\mid$ item)\\\\\\%, 95\\% CI") + " & " +
1149 + H("P(item $\\mid$ category)\\\\\\%, 95\\% CI") + " & " + H("Base rate of\\\\the category (\\%)") + " & Lift \\\\\n\\midrule\n")
1150 + for r in B8:
1151 + tab += (f"{LAB.get(r['project_type'], r['project_type'].replace('-', ' '))} & {esc(r['item'])} & {n(r['n_item'])} & {100*float(r['p_type_given_item']):.1f} "
1152 + f"[{100*float(r['ci_low_1']):.1f}, {100*float(r['ci_high_1']):.1f}] & {100*float(r['p_item_given_type']):.1f} [{100*float(r['ci_low_2']):.1f}, {100*float(r['ci_high_2']):.1f}] & "
1153 + f"{100*float(r['base_rate_type']):.1f} & {float(r['lift_type_given_item']):.1f} \\\\\n")
1154 + tab += "\\bottomrule\n\\end{tabular}"
1155 + float_table("tab_benchmark_8k.tex", "tab:benchmark_8k", "External consistency of 8-K mentions with the 8-K item codes declared in the filing body", tab,
1156 + f"Item codes are read from the 8-K body with the pattern \\texttt{{Item\\textbackslash{{}}s+([1-9]\\textbackslash{{}}.[0-9]{{2}})}} "
1157 + f"({b8s.get('coverage_pct', 0):.1f}\\% of the {n(b8s.get('sections_8k', 0))} 8-K sections carry at least one code). ``P(category $\\mid$ item)'' is the share of "
1158 + "sections declaring the item in which the model returned at least one mention of the category; ``P(item $\\mid$ category)'' is the share of sections with such a "
1159 + "mention that declare the item; lift is the first probability divided by the category's base rate over all 8-K sections. Item~2.01 (completion of an acquisition or "
1160 + "disposition) and Item~2.05 (exit or disposal costs) are the natural counterparts of \\texttt{ma\\_integration} and \\texttt{cost\\_reduction}; Items~5.02 and 8.01 "
1161 + "are controls. Confidence intervals are Wilson intervals. These are consistency proxies: an item code says that an event of the kind was reported, not that the "
1162 + "model's mention is correct, so neither probability is a precision or a recall.",
1163 + "results/benchmark\\_8k/item\\_vs\\_type.csv, summary.json", size="\\scriptsize", colsep="3pt", fit=True)
1164 + for r in B8:
1165 + key = "".join(p.capitalize() for p in r["project_type"].replace("-", "_").split("_")) + "".join(ch for ch in r["item"] if ch.isalnum())
1166 + macro(f"pTypeGivenItem{key}", f"{100*float(r['p_type_given_item']):.1f}", "results/benchmark_8k/item_vs_type.csv", f"p_type_given_item {r['project_type']} {r['item']}")
1167 + macro(f"pItemGivenType{key}", f"{100*float(r['p_item_given_type']):.1f}", "results/benchmark_8k/item_vs_type.csv", f"p_item_given_type {r['project_type']} {r['item']}")
1168 + macro(f"lift{key}", f"{float(r['lift_type_given_item']):.0f}", "results/benchmark_8k/item_vs_type.csv", f"lift {r['project_type']} {r['item']}")
1169 +
1170 +# ---- Table: time series with the fixed 2010 cohort and windowed keys (appendix) ----------------------------------------------
1171 +tsp = R / "timeseries" / "first_seen_fixed_cohort.csv"; tss = jload("timeseries/summary.json")
1172 +TS = rows(tsp.stem, tsp.parent) if tsp.exists() else []
1173 +if TS:
1174 + allr = {r["year"]: r for r in TS if r["series"] == "all_issuers"}; coh = {r["year"]: r for r in TS if r["series"] == "fixed_2010_cohort"}
1175 + tab = ("\\begin{tabular}{lrrrrrrrrr}\n\\toprule\n & \\multicolumn{5}{c}{All issuers filing in the year} & \\multicolumn{4}{c}{Fixed cohort: issuers filing in every year " +
1176 + f"{min(coh)}--{max(y for y in coh if 'partial' not in coh[y]['flag'])}}} \\\\\n\\cmidrule(lr){{2-6}}\\cmidrule(lr){{7-10}}\nYear & Issuers & " + H("Mentions\\\\per issuer") +
1177 + " & " + H("First seen\\\\(current key)") + " & " + H("First seen\\\\($k = 3$)") + " & " + H("First seen\\\\($k = 5$)") + " & Issuers & " + H("Mentions\\\\per issuer") +
1178 + " & " + H("First seen\\\\(current key)") + " & " + H("First seen\\\\per issuer") + " \\\\\n\\midrule\n")
1179 + for y in sorted(allr):
1180 + a = allr[y]; c = coh[y]; flag = f"$^{{{'a' if 'left' in a['flag'] else 'b'}}}$" if a["flag"] else ""
1181 + tab += (f"{y}{flag} & {n(a['issuers_filing'])} & {pct(a['mentions_per_issuer_filing'])} & {n(a['first_seen_current_key'])} & {n(a['first_seen_k3'])} & {n(a['first_seen_k5'])} & "
1182 + f"{n(c['issuers_filing'])} & {pct(c['mentions_per_issuer_filing'])} & {n(c['first_seen_current_key'])} & {pct(c['first_seen_per_issuer'])} \\\\\n")
1183 + tab += "\\bottomrule\n\\end{tabular}"
1184 + float_table("tab_timeseries_cohort.tex", "tab:timeseries_cohort", "Mentions and projects first seen by filing year: all issuers versus a fixed issuer cohort and windowed keys", tab,
1185 + f"$^{{a}}$Left-censored year (a project under way before the corpus start is first seen at its first in-window filing); $^{{b}}$partial year (filings to {fdr[1]}). "
1186 + f"``First seen'' counts projects whose earliest mention falls in the year; the windowed keys split a current-key project into episodes whenever the gap between "
1187 + f"consecutive mentions exceeds $k$ years ({n(tss.get('episodes_k3_total', 0))} episodes at $k = 3$ and {n(tss.get('episodes_k5_total', 0))} at $k = 5$ against "
1188 + f"{n(tss.get('projects_current', 0))} projects). The fixed cohort holds the issuer composition constant: its mentions per issuer are flat while its new projects per "
1189 + "issuer fall, which is consistent with a time-invariant key attaching later mentions to existing projects, with a change in disclosure, or with both; the series do "
1190 + "not discriminate between these readings.", "results/timeseries/first\\_seen\\_fixed\\_cohort.csv, summary.json", size="\\scriptsize", colsep="3pt", fit=True)
1191 + inner_c = [y for y in sorted(coh) if not coh[y]["flag"]]
1192 + macro("cohortIssuers", n(tss.get("cohort_issuers", 0)), "results/timeseries/summary.json", "cohort_issuers")
1193 + macro("cohortMentionsPerIssuerFirst", pct(coh[inner_c[0]]["mentions_per_issuer_filing"]), "results/timeseries/first_seen_fixed_cohort.csv", f"fixed cohort mentions per issuer {inner_c[0]}")
1194 + macro("cohortMentionsPerIssuerLast", pct(coh[inner_c[-1]]["mentions_per_issuer_filing"]), "results/timeseries/first_seen_fixed_cohort.csv", f"fixed cohort mentions per issuer {inner_c[-1]}")
1195 + macro("cohortFirstSeenPerIssuerFirst", pct(coh[inner_c[0]]["first_seen_per_issuer"]), "results/timeseries/first_seen_fixed_cohort.csv", f"fixed cohort first seen per issuer {inner_c[0]}")
1196 + macro("cohortFirstSeenPerIssuerLast", pct(coh[inner_c[-1]]["first_seen_per_issuer"]), "results/timeseries/first_seen_fixed_cohort.csv", f"fixed cohort first seen per issuer {inner_c[-1]}")
1197 + macro("cohortFirstSeenFirst", n(coh[inner_c[0]]["first_seen_current_key"]), "results/timeseries/first_seen_fixed_cohort.csv", f"fixed cohort first seen {inner_c[0]}")
1198 + macro("cohortFirstSeenLast", n(coh[inner_c[-1]]["first_seen_current_key"]), "results/timeseries/first_seen_fixed_cohort.csv", f"fixed cohort first seen {inner_c[-1]}")
1199 + macro("episodesKThree", n(tss.get("episodes_k3_total", 0)), "results/timeseries/summary.json", "episodes_k3_total")
1200 + macro("episodesKFive", n(tss.get("episodes_k5_total", 0)), "results/timeseries/summary.json", "episodes_k5_total")
1201 + macro("newProjectsPerIssuerFilingFirstYear", pct(allr[min(allr)]["first_seen_per_issuer"]), "results/timeseries/first_seen_fixed_cohort.csv", "first seen / issuers filing, first year")
1202 + macro("newProjectsPerIssuerFilingLastFullYear", pct(allr[str(inner[-1])]["first_seen_per_issuer"]), "results/timeseries/first_seen_fixed_cohort.csv", f"first seen / issuers filing, {inner[-1]}")
1203 +macro("newProjectsPerIssuerFirstYear", f"{int(py[str(y_first)]['n'])/int(my[str(y_first)]['issuers']):.1f}", "data/projects_by_first_seen_year.csv, mentions_by_year.csv", "first seen / issuers with mentions")
1204 +macro("newProjectsPerIssuerLastFullYear", f"{int(py[str(inner[-1])]['n'])/int(my[str(inner[-1])]['issuers']):.1f}", "data/projects_by_first_seen_year.csv, mentions_by_year.csv", "first seen / issuers with mentions")
1205 +
1206 +# ---- Table: rule-based baseline vs LLM (appendix) ------------------------------------------------------------------------------
1207 +rab = R / "rules" / "agreement_by_form.csv"; rao = R / "rules" / "agreement_overall.csv"; rfl = R / "rules" / "focus_recall_loss.csv"; rflo = R / "rules" / "focus_recall_loss_overall.csv"
1208 +if rab.exists() and rao.exists():
1209 + RA = rows(rab.stem, rab.parent) + rows(rao.stem, rao.parent)
1210 + tab = ("\\begin{tabular}{lrrrrrrr}\n\\toprule\n\\multicolumn{8}{l}{\\itshape Panel A: section-level agreement between the rule-based extractor and the LLM (weighted to the ledger)} \\\\\n"
1211 + "Form & " + H("Sections\\\\sampled") + " & " + H("P(rules $\\geq 1 \\mid$\\\\LLM $\\geq 1$) \\%") + " & " + H("P(LLM $\\geq 1 \\mid$\\\\rules $\\geq 1$) \\%") + " & " +
1212 + H("Rules\\\\positive \\%") + " & " + H("LLM\\\\positive \\%") + " & " + H("Agreement\\\\\\%") + " & " + H("Same type on\\\\co-detected \\%") + " \\\\\n\\midrule\n")
1213 + for r in RA:
1214 + lab = r.get("form_type") or r.get("scope", "all")
1215 + tab += (f"{'All forms' if lab == 'all' else lab} & {n(r['n_sampled'])} & {pct(r['p_rules_given_llm'])} & {pct(r['p_llm_given_rules_weighted'])} & {pct(r['rules_pos_pct_weighted'])} & "
1216 + f"{pct(r['llm_pos_pct_weighted'])} & {pct(r['agreement_pct_w'])} & {pct(r['type_overlap_pct_codetected'])} \\\\\n")
1217 + if rfl.exists():
1218 + agg = {}
1219 + for r in rows(rfl.stem, rfl.parent):
1220 + a = agg.setdefault(r["form_type"], [0, 0, 0]); a[0] += int(r["n_over_budget"]); a[1] += int(r["rules_full"]); a[2] += int(r["rules_focused"])
1221 + tab += "\\midrule\n\\multicolumn{8}{l}{\\itshape Panel B: rule mentions recovered inside the focus windows, sections over the 9{,}000-character budget} \\\\\n"
1222 + tab += "Form & " + H("Sections over\\\\budget (sample)") + " & " + H("Rule mentions,\\\\full text") + " & " + H("Rule mentions,\\\\focused text") + " & " + H("Recovered\\\\\\%") + " & & & \\\\\n\\midrule\n"
1223 + for fm, a in agg.items():
1224 + tab += f"{fm} & {n(a[0])} & {n(a[1])} & {n(a[2])} & {100*a[2]/a[1]:.1f} & & & \\\\\n"
1225 + if rflo.exists():
1226 + o = rows(rflo.stem, rflo.parent)[0]
1227 + tab += f"All forms & {n(o['n'])} & {n(o['rules_full'])} & {n(o['rules_focused'])} & {100 - float(o['pct_lost']):.1f} & & & \\\\\n"
1228 + macro("focusRecallRecoveredPct", f"{100 - float(o['pct_lost']):.1f}", "results/rules/focus_recall_loss_overall.csv", "100 - pct_lost")
1229 + for fm, a in agg.items():
1230 + macro("focusRecallRecovered" + fm.replace("-", "") + "Pct", f"{100*a[2]/a[1]:.1f}", "results/rules/focus_recall_loss.csv", f"sum(rules_focused)/sum(rules_full) where form={fm}")
1231 + tab += "\\bottomrule\n\\end{tabular}"
1232 + ov = rows(rao.stem, rao.parent)[0]
1233 + float_table("tab_rules_agreement.tex", "tab:rules_agreement", "Rule-based extractor versus LLM: section-level agreement on a stratified sample, and the recall bound of the focus windows", tab,
1234 + f"Seeded stratified sample of {n(ov['n_sampled'])} ledgered sections ({n(ov['llm_pos'])} with at least one LLM mention and the same number without), weighted back to the "
1235 + f"{n(float(ov['n_weighted']))} ledger rows by inverse inclusion probability; the snapshot's \\texttt{{RuleExtractor}} was run on the stored text. The two extractors "
1236 + "have different constructs (the rules flag any gate-vocabulary sentence), so agreement is not accuracy and neither extractor is the reference. Panel B runs the rules "
1237 + "on the full text and on the focused text of the same over-budget sections: the share recovered is a deterministic upper bound on what any extractor can see "
1238 + "through the focus windows, not a recall estimate for the LLM.",
1239 + "results/rules/agreement\\_by\\_form.csv, agreement\\_overall.csv, focus\\_recall\\_loss.csv", size="\\scriptsize", colsep="3pt", fit=True)
1240 + macro("rulesGivenLlmPct", pct(ov["p_rules_given_llm"]), "results/rules/agreement_overall.csv", "p_rules_given_llm")
1241 + macro("llmGivenRulesPct", pct(ov["p_llm_given_rules_weighted"]), "results/rules/agreement_overall.csv", "p_llm_given_rules_weighted")
1242 + macro("rulesLlmAgreementPct", pct(ov["agreement_pct_w"]), "results/rules/agreement_overall.csv", "agreement_pct_w")
1243 + macro("rulesLlmTypeOverlapPct", pct(ov["type_overlap_pct_codetected"]), "results/rules/agreement_overall.csv", "type_overlap_pct_codetected")
1244 + macro("rulesSampleN", n(ov["n_sampled"]), "results/rules/agreement_overall.csv", "n_sampled")
1245 +
1246 +# ---- macros from the Stage D audit results (results/**.json; skipped when absent) --------------------------------------------
566 1247 def jmacro(name, obj, key, src, fmt=None):
567 1248 v = obj.get(key) if isinstance(obj, dict) else None
568 1249 if v is None or isinstance(v, (list, dict)): return
569 1250 macro(name, fmt(v) if fmt else (n(v) if isinstance(v, (int, float)) and float(v).is_integer() else str(v)), src, key)
570 1251
571 −gt = jload("ledger/gate_pass_totals.json")
572 1252 for k, mname, fmt in (("calls", "callsTotal", None), ("gate_pass", "gatePassSections", None), ("gate_rejected_zero", "gateRejectedSections", None),
573 1253 ("lt30_words", "ledgerUnderThirtyWords", None), ("productive_pct_calls", "productiveShareCalls", lambda v: f"{v:.1f}"),
574 1254 ("mentions_per_call", "mentionsPerCall", lambda v: f"{v:.2f}"), ("usd_per_call_paper_total_775", "usdPerCall", lambda v: f"{v:.4f}"),
575 1255 ("october_calls", "octoberCalls", None), ("october_rows", "octoberRows", None)):
576 1256 jmacro(mname, gt, k, "results/ledger/gate_pass_totals.json", fmt)
577 −tp = jload("ledger/throughput.json")
578 1257 for k, mname, fmt in (("wall_clock_hours_first_to_last_flush", "octoberWallClockHours", lambda v: f"{v:.1f}"), ("largest_gap_hours", "outageHours", lambda v: f"{v:.1f}"),
579 1258 ("effective_hours_excluding_largest_gap", "octoberEffectiveHours", lambda v: f"{v:.1f}"),
580 − ("rows_per_second_effective", "octoberRowsPerSecondEffective", lambda v: f"{v:.1f}"), ("rows_per_second_wall_clock", "octoberRowsPerSecondWallClock", lambda v: f"{v:.1f}"),
1259 + ("rows_per_second_effective", "octoberRowsPerSecondEffective", lambda v: f"{v:.1f}"), ("rows_per_second_wall", "octoberRowsPerSecondWallClock", lambda v: f"{v:.1f}"),
581 1260 ("calls_per_second_effective", "octoberCallsPerSecondEffective", lambda v: f"{v:.1f}"), ("october_first_flush", "octoberFirstFlush", lambda v: str(v)[:16]),
582 − ("october_last_flush", "octoberLastFlush", lambda v: str(v)[:16])):
1261 + ("october_last_flush", "octoberLastFlush", lambda v: str(v)[:16]), ("paper_rate_implied_by_12h", "paperRateImpliedByTwelveHours", lambda v: f"{v:.1f}")):
583 1262 jmacro(mname, tp, k, "results/ledger/throughput.json", fmt)
584 −bb = jload("ledger/backfill_block.json")
585 1263 for k, mname in (("rows_at_min_timestamp", "backfilledRows"), ("june_log_sections", "juneLogSections"), ("block_lt30_words", "backfilledUnderThirtyWords"),
586 1264 ("block_stored_mentions", "backfilledMentions"), ("block_ciks", "backfilledCiks"), ("block_gate_fail", "backfilledGateFail"), ("rows_in_outage_window", "rowsInOutageWindow")):
587 1265 jmacro(mname, bb, k, "results/ledger/backfill_block.json")
588 1266 if isinstance(bb.get("outage_window"), list) and len(bb["outage_window"]) == 2:
589 1267 macro("outageWindowStart", str(bb["outage_window"][0])[:16], "results/ledger/backfill_block.json", "outage_window[0]")
590 1268 macro("outageWindowEnd", str(bb["outage_window"][1])[:16], "results/ledger/backfill_block.json", "outage_window[1]")
591 −ls_ = jload("ledger/log_summary.json")
592 −oc_ = ls_.get("october", {}) if isinstance(ls_.get("october"), dict) else {}
593 −for k, mname in (("llm_call_failed_total", "llmCallFailedTotal"), ("llm_call_failed_inside_window", "llmCallFailedInsideOutage"), ("llm_call_failed_outside_window", "llmCallFailedOutsideOutage")):
594 − jmacro(mname, oc_, k, "results/ledger/log_summary.json:october")
1269 +jmacro("llmCallFailedTotal", oc_, "llm_call_failed_total", "results/ledger/log_summary.json:october")
1270 +jmacro("llmCallFailedInsideOutage", oc_, "llm_call_failed_inside_window", "results/ledger/log_summary.json:october")
1271 +# silent failures outside the outage = JSON-decode failures; the 128 retryable lines at 06:22:01-06:22:21 belong to the outage tail (log window 01:10:21-06:22:21)
1272 +jmacro("llmCallFailedOutsideOutage", oc_, "silent_empty_results_outside_outage", "results/ledger/log_summary.json:october")
1273 +if isinstance(oc_.get("outside_window_by_reason"), dict):
1274 + jmacro("llmRetryableTailLines", oc_["outside_window_by_reason"], "retryable_http_429_5xx", "results/ledger/log_summary.json:october.outside_window_by_reason")
595 1275 if isinstance(oc_.get("llm_call_failed_by_reason"), dict):
596 1276 for k, v in oc_["llm_call_failed_by_reason"].items(): macro("llmFailed" + "".join(p.capitalize() for p in k.split("_")), n(v), "results/ledger/log_summary.json:october.llm_call_failed_by_reason", k)
1277 +if isinstance(oc_.get("outage_window_from_log"), list) and len(oc_["outage_window_from_log"]) >= 2:
1278 + macro("outageLogWindowStart", str(oc_["outage_window_from_log"][0])[:16], "results/ledger/log_summary.json", "outage_window_from_log[0]")
1279 + macro("outageLogWindowEnd", str(oc_["outage_window_from_log"][1])[:16], "results/ledger/log_summary.json", "outage_window_from_log[1]")
1280 +if isinstance(oc_.get("outage_rows_reconciliation"), dict):
1281 + jmacro("outageRowsRemoved", oc_["outage_rows_reconciliation"], "difference", "results/ledger/log_summary.json:october.outage_rows_reconciliation")
597 1282 jn_ = ls_.get("june", {}) if isinstance(ls_.get("june"), dict) else {}
598 1283 jmacro("juneLlmCallFailed", jn_, "llm_call_failed_total", "results/ledger/log_summary.json:june")
599 1284 co = jload("ledger/collisions.json")
600 1285 for k, mname in (("sections_ledger_gt_stored", "collisionSections"), ("excess_mentions", "collisionMentions")):
601 1286 jmacro(mname, co, k, "results/ledger/collisions.json")
602 −cp = jload("resolver/composition.json")
603 1287 for k, mname in (("projects_keyed_general", "projectsKeyedGeneral"), ("mentions_keyed_general", "mentionsKeyedGeneral")):
604 1288 jmacro(mname, cp, k, "results/resolver/composition.json")
605 1289 if isinstance(cp.get("projects_by_key_branch"), list):
606 1290 for br, v in cp["projects_by_key_branch"]:
607 1291 macro("projectsKeyed" + "".join(p.capitalize() for p in str(br).split("_")), n(v), "results/resolver/composition.json", f"projects_by_key_branch[{br}]")
608 1292 macro("projectsKeyed" + "".join(p.capitalize() for p in str(br).split("_")) + "Pct", f"{100*v/P:.1f}", "results/resolver/composition.json", f"100*projects_by_key_branch[{br}]/projects")
609 −ti = jload("resolver/ties_idempotence.json")
610 1293 for k, mname in (("projects_with_tie_at_max_confidence", "projectsTieMaxConfidence"), ("projects_with_tie_and_distinct_names", "projectsTieDistinctNames"),
611 1294 ("projects_with_status_tie_on_last_seen", "projectsStatusTie"), ("mentions_at_confidence_1", "mentionsAtConfidenceOne")):
612 1295 jmacro(mname, ti, k, "results/resolver/ties_idempotence.json")
613 −sc_path = R / "resolver" / "spec_curve.csv"
614 −if sc_path.exists():
615 − sc = rows(sc_path.stem, sc_path.parent)
616 − thr = min(sc, key=lambda r: float(r["threshold"]))["threshold"]
617 − at = [r for r in sc if r["threshold"] == thr]
618 − pr = [int(float(r["projects"])) for r in at]
619 − macro("projectCountRangeKeys", f"{n(min(pr))}--{n(max(pr))}", "results/resolver/spec_curve.csv", f"min/max projects over keys at threshold {thr}")
620 − macro("projectCountRangeKeysN", str(len(at)), "results/resolver/spec_curve.csv", f"number of keys at threshold {thr}")
621 − pall = [int(float(r["projects"])) for r in sc]
622 − macro("projectCountRangeAll", f"{n(min(pall))}--{n(max(pall))}", "results/resolver/spec_curve.csv", "min/max projects over all keys x thresholds")
623 − cur = [r for r in at if "current" in r["key"].lower()]
624 − if cur: macro("projectCountCurrentKey", n(cur[0]["projects"]), "results/resolver/spec_curve.csv", f"key={cur[0]['key']} at {thr}")
625 −tn_path = R / "resolver" / "top_name_tokens.csv"
1296 +if ti.get("rebuilt_vs_stored_diff"):
1297 + macro("rebuiltNamesDiffer", n(ti["rebuilt_vs_stored_diff"][0]), "results/resolver/ties_idempotence.json", "rebuilt_vs_stored_diff[0]")
1298 + macro("rebuiltDescriptionsDiffer", n(ti["rebuilt_vs_stored_diff"][2]), "results/resolver/ties_idempotence.json", "rebuilt_vs_stored_diff[2]")
1299 +ad_ = jload("annotation_frame/design.json")
1300 +for k, mname, fmt in (("n_productive", "annotationFrameProductive", n), ("n_zero", "annotationFrameZero", n), ("n_strata_productive", "annotationStrata", n),
1301 + ("half_width_95_precision_p0.5", "annotationHalfWidthPrecision", lambda v: f"{100*v:.1f}"), ("mde_gate_recall_diff_at_p0.05", "annotationMdeGateRecall", lambda v: f"{100*v:.1f}")):
1302 + if ad_.get(k) is not None: macro(mname, fmt(ad_[k]), "results/annotation_frame/design.json", k)
1303 +if isinstance(ad_.get("core_subsample"), dict): macro("annotationCoreProductive", n(ad_["core_subsample"]["productive"]), "results/annotation_frame/design.json", "core_subsample.productive")
1304 +if isinstance(ad_.get("split"), dict):
1305 + macro("annotationDev", n(ad_["split"]["dev"]), "results/annotation_frame/design.json", "split.dev"); macro("annotationHoldout", n(ad_["split"]["holdout"]), "results/annotation_frame/design.json", "split.holdout")
1306 +seg = jload("runs/segmenters.json"); fu = jload("runs/funnel_10k.json")
1307 +if seg.get("full_body_rows"): macro("fullBodyFilings", n(seg["full_body_rows"][1]), "results/runs/segmenters.json", "full_body_rows[1]")
1308 +if seg.get("legacy_rows"): macro("legacyRows", n(seg["legacy_rows"]), "results/runs/segmenters.json", "legacy_rows"); macro("legacyAccessions", n(seg["legacy_accessions"]), "results/runs/segmenters.json", "legacy_accessions")
1309 +fy_ = jload("runs/fiscal_year_audit.json")
1310 +if S.get("fiscal_year_null_mentions") is not None: macro("fiscalYearNullMentions", n(S["fiscal_year_null_mentions"]), "stats.json:fiscal_year_null_mentions", "count(fiscal_year is null)")
1311 +
1312 +
1313 +# ---- macros requested by the writing stage (improvements/FIRC-0001/macro_requests_writing.json), each computed from its results/ source ----
1314 +WORDS = {0: "zero", 1: "one", 2: "two", 3: "three", 4: "four", 5: "five", 6: "six", 7: "seven", 8: "eight", 9: "nine", 10: "ten", 11: "eleven", 12: "twelve", 13: "thirteen", 14: "fourteen", 15: "fifteen"}
1315 +MONTHS = {1: "January", 2: "February", 3: "March", 4: "April", 5: "May", 6: "June", 7: "July", 8: "August", 9: "September", 10: "October", 11: "November", 12: "December"}
1316 +
1317 +
1318 +def word(v):
1319 + v = int(v); return WORDS.get(v, n(v))
1320 +
1321 +
1322 +def longdate(iso):
1323 + y, m, d = str(iso)[:10].split("-"); return f"{MONTHS[int(m)]}~{int(d)}, {y}"
1324 +
1325 +
1326 +def rxs(path, pattern, cast=str):
1327 + """First regex group in a source file of the frozen snapshot / archived pipeline code; None when absent."""
1328 + p = path if isinstance(path, Path) else _snapshot(path)
1329 + if p is None or not p.exists(): return None
1330 + m = re.search(pattern, p.read_text(errors="replace"))
1331 + return cast(m.group(1)) if m else None
1332 +
1333 +
1334 +def dim(key, name, source_suffix=""):
1335 + """Documented (author-reported or constant) input -> macro."""
1336 + if di(key) is not None: macro(name, di(key), f"data/documented_inputs.json:{key}", di_source(key) + source_suffix)
1337 +
1338 +
1339 +# -- ledger / outage (results/ledger) --
1340 +if tp.get("largest_gaps_seconds"):
1341 + g_ = tp["largest_gaps_seconds"][-1]
1342 + macro("outageLargestGapStart", str(g_[1])[11:16], "results/ledger/throughput.json", "largest_gaps_seconds[-1][1] hh:mm")
1343 + macro("outageLargestGapEnd", str(g_[2])[11:16], "results/ledger/throughput.json", "largest_gaps_seconds[-1][2] hh:mm")
1344 +if oc_:
1345 + an_all = [b for b in oc_.get("anomalous_batches", []) if isinstance(b, list) and str(oc_.get('outage_window_from_log', ['', ''])[0]) <= str(b[3]) <= str(oc_.get('outage_window_from_log', ['', ''])[1])]
1346 + if an_all:
1347 + ids_ = sorted(int(b[1]) for b in an_all); ts_ = sorted(str(b[3]) for b in an_all)
1348 + macro("outageZeroBatchRange", f"{ids_[0]}--{ids_[-1]}", "results/ledger/log_summary.json:october.anomalous_batches", "min--max batch id with 0 mentions inside the log window")
1349 + macro("outageZeroBatchWindow", f"{ts_[0][11:16]}--{ts_[-1][11:16]}", "results/ledger/log_summary.json:october.anomalous_batches", "first--last timestamp")
1350 + rs = oc_.get("resume_batch1", {})
1351 + if rs:
1352 + macro("resumeBatchMentions", n(rs.get("log_mentions", 0)), "results/ledger/log_summary.json:october.resume_batch1.log_mentions", "log")
1353 + macro("resumeBatchWindow", f"{str(rs['window'][0])[11:16]}--{str(rs['window'][1])[11:16]}", "results/ledger/log_summary.json:october.resume_batch1.window", "hh:mm")
1354 + rec = oc_.get("outage_rows_reconciliation", {})
1355 + macro("logExtractionCompleteSum", n(rec.get("extraction_complete_sum_sections", 0)), "results/ledger/log_summary.json:october.outage_rows_reconciliation", "extraction_complete_sum_sections")
1356 + macro("logPendingSecondStart", n(rec.get("pending_at_second_start", 0)), "results/ledger/log_summary.json:october.outage_rows_reconciliation", "pending_at_second_start")
1357 + ow = oc_.get("outside_window_list", []); w0 = str(oc_.get("window", ["", ""])[0])
1358 + jb = sum(1 for t, r in ow if r == "json_decode_error" and str(t) < w0); ja = sum(1 for t, r in ow if r == "json_decode_error" and str(t) > str(oc_.get("window", ["", ""])[1]))
1359 + macro("jsonFailBeforeOutage", word(jb), "results/ledger/log_summary.json:october.outside_window_list", "json_decode_error lines before the window")
1360 + macro("jsonFailAfterOutage", word(ja), "results/ledger/log_summary.json:october.outside_window_list", "json_decode_error lines after the window")
1361 + wv = oc_.get("workers_values", [])
1362 + if wv: macro("workers", str(max(int(x) for x in wv)), "results/ledger/log_summary.json:october.workers_values", "max")
1363 +if bb.get("rows_in_outage_window"):
1364 + macro("outageSurvivingRows", n(bb["rows_in_outage_window"][0]), "results/ledger/backfill_block.json", "rows_in_outage_window[0]")
1365 + macro("outageSurvivingMentions", n(bb["rows_in_outage_window"][1]), "results/ledger/backfill_block.json", "rows_in_outage_window[1]")
1366 +if bb.get("min_extracted_at"):
1367 + macro("backfillTimestamp", longdate(bb["min_extracted_at"]) + ", " + str(bb["min_extracted_at"])[11:16], "results/ledger/backfill_block.json:min_extracted_at", "date, hh:mm")
1368 +if rb1.exists():
1369 + macro("resumeBatchExpectedProductive", f"{rb_exp:.0f}", "results/ledger/resume_batch1_vs_expected.csv", "sum(expected_with_mentions), rounded")
1370 +fz = R / "ledger" / "flush_zero_groups_after_0622.csv"
1371 +if fz.exists():
1372 + fzr = rows(fz.stem, fz.parent)
1373 + if fzr: macro("resumeBatchZeroSharePct", pct(fzr[0]["zero_pct_among_calls"]), "results/ledger/flush_zero_groups_after_0622.csv", "zero_pct_among_calls of the first minute bin")
1374 +if gr.exists():
1375 + for r in rows(gr.stem, gr.parent):
1376 + if r["run"] == "backfilled_june":
1377 + macro("juneCalls", n(r["calls"]), "results/ledger/gate_pass_by_run.csv", "calls where run=backfilled_june")
1378 + macro("juneProductiveShareCalls", pct(r["productive_pct_calls"]), "results/ledger/gate_pass_by_run.csv", "productive_pct_calls where run=backfilled_june")
1379 + if r["run"] == "october":
1380 + macro("octoberProductiveShareCalls", pct(r["productive_pct_calls"]), "results/ledger/gate_pass_by_run.csv", "productive_pct_calls where run=october")
1381 +if gt:
1382 + macro("gateRejectedPct", f"{100*gt['gate_rejected_zero']/gt['ledger_rows']:.1f}", "results/ledger/gate_pass_totals.json", "100*gate_rejected_zero/ledger_rows")
1383 + macro("usdPerOctoberRow", f"{gt['usd_per_october_row_paper_total_775']:.4f}", "results/ledger/gate_pass_totals.json", "usd_per_october_row_paper_total_775")
1384 +if cvd:
1385 + macro("confExactDefault", n(cvd["confidence_exact_0600_total"]), "results/ledger/code_vs_data_checks.json", "confidence_exact_0600_total")
1386 + for run_, cnt in cvd.get("confidence_exact_0600_by_run", []):
1387 + macro("confExactDefault" + ("June" if run_ == "backfilled_june" else "October"), n(cnt), "results/ledger/code_vs_data_checks.json", f"confidence_exact_0600_by_run[{run_}]")
1388 + macro("ledgerBackendValue", esc(", ".join(cvd.get("distinct_backend_ledger", []))), "results/ledger/code_vs_data_checks.json", "distinct_backend_ledger")
1389 +# -- amounts / grounding (results/grounding) --
1390 +if at:
1391 + macro("amountNegative", n(at["lt_0"]), "results/grounding/amount_tail.json", "lt_0")
1392 + macro("amountZero", n(at["eq_0"]), "results/grounding/amount_tail.json", "eq_0")
1393 + mx = at["max_amount"]; e = int(math.floor(math.log10(mx))); macro("amountMaxSci", f"{mx/10**e:.1f} \\times 10^{{{e}}}", "results/grounding/amount_tail.json:max_amount", "mantissa x 10^exponent (math mode)")
1394 + macro("amountGeFiftyBMentions", n(at["ge_50e9"]), "results/grounding/amount_tail.json", "ge_50e9")
1395 + macro("amountGeFiftyBProjects", n(at["projects_max_amount_ge_50e9"]), "results/grounding/amount_tail.json", "projects_max_amount_ge_50e9")
1396 + macro("amountTopNumberFound", n(at["top200_grounded_number"][0]), "results/grounding/amount_tail.json", "top200_grounded_number[0]")
1397 + macro("amountTopCurrencyFound", n(at["top200_grounded_number"][1]), "results/grounding/amount_tail.json", "top200_grounded_number[1]")
1398 + macro("amountTopN", n(at["top200_grounded_number"][2]), "results/grounding/amount_tail.json", "top200_grounded_number[2]")
1399 + macro("amountNonUsdTokenN", n(at["nonusd_within_40_share"][0]), "results/grounding/amount_tail.json", "nonusd_within_40_share[0]")
1400 + macro("amountLocatedN", n(at["nonusd_within_40_share"][1]), "results/grounding/amount_tail.json", "nonusd_within_40_share[1]")
1401 + macro("amountNonUsdTokenPct", f"{100*at['nonusd_within_40_share'][0]/at['nonusd_within_40_share'][1]:.1f}", "results/grounding/amount_tail.json", "100*[0]/[1]")
1402 +if gg.exists():
1403 + macro("groundBootstrapReps", n(1e3), "code/audit/a02_grounding.py", "bootstrap replicates (B) of the grounding audit")
1404 + GF = {"years": "Years", "partners": "Partners", "amount_number": "AmountNumber", "amount_with_currency": "AmountCurrency", "locations": "Locations", "technologies": "Tech"}
1405 + for f, nm in GF.items():
1406 + a = gget("all", f, "all")
1407 + if a: macro(f"ground{nm}Pct", f"{100*float(a['grounded_share']):.1f}", "results/grounding/grounding_by_group.csv", f"all/{f} grounded_share")
1408 + a = gget("all", "years", "all")
1409 + if a:
1410 + macro("groundYearsCiLow", f"{100*float(a['ci_low']):.1f}", "results/grounding/grounding_by_group.csv", "all/years ci_low"); macro("groundYearsCiHigh", f"{100*float(a['ci_high']):.1f}", "results/grounding/grounding_by_group.csv", "all/years ci_high")
1411 + for fm, nm in (("10-K", "TenK"), ("10-Q", "TenQ"), ("8-K", "EightK")):
1412 + x = gget("form", "locations", fm)
1413 + if x: macro(f"groundLocations{nm}", f"{100*float(x['grounded_share']):.1f}", "results/grounding/grounding_by_group.csv", f"form/locations/{fm}")
1414 + if gel.exists():
1415 + for r in rows(gel.stem, gel.parent):
1416 + macro("groundElem" + {"years": "Years", "partners": "Partners", "locations": "Locations", "technologies": "Tech"}[r["field"]], pct(r["pct"]), "results/grounding/grounding_element_level.csv", r["field"])
1417 + macro("groundAllPct", pct(A["all"]["pct"]), "results/grounding/grounding_all_structured.csv", "all"); macro("groundAllN", n(A["all"]["n_with_fields"]), "results/grounding/grounding_all_structured.csv", "all n_with_fields")
1418 + for k, nm in (("10-K", "TenK"), ("10-Q", "TenQ"), ("8-K", "EightK"), ("backfilled_june", "June"), ("october", "October")):
1419 + macro(f"groundAll{nm}", pct(A[k]["pct"]), "results/grounding/grounding_all_structured.csv", k)
1420 + bins_ = sorted(k for k in A if re.match(r"^\d\.\d+-\d\.\d+$", k))
1421 + macro("groundAllTopBin", pct(A[bins_[-1]]["pct"]), "results/grounding/grounding_all_structured.csv", f"bin {bins_[-1]}")
1422 + lower = [float(A[b]["pct"]) for b in bins_[:-1]]
1423 + macro("groundAllLowerBinsRange", f"{min(lower):.1f}--{max(lower):.1f}", "results/grounding/grounding_all_structured.csv", f"min--max over bins {bins_[0]}..{bins_[-2]}")
1424 +if fbd:
1425 + macro("yearsAbsentFromText", n(fbd["years_not_subset_of_text"]), "results/grounding/fallback_bounds.json", "years_not_subset_of_text")
1426 + for t_, tot_, hit_, p_ in fbd.get("type_signal_in_name_desc_by_type", []):
1427 + if t_ == "ma_integration": macro("typeSignalMaPct", pct(100 * hit_ / tot_), "results/grounding/fallback_bounds.json", "type_signal_in_name_desc_by_type ma_integration")
1428 + if t_ == "technology_deployment": macro("typeSignalTechDeployPct", pct(100 * hit_ / tot_), "results/grounding/fallback_bounds.json", "type_signal_in_name_desc_by_type technology_deployment")
1429 + macro("techRegexEqualPct", f"{100*fbd['techs_eq_regex_desc']/fbd['techs_nonempty']:.0f}", "results/grounding/fallback_bounds.json", "100*techs_eq_regex_desc/techs_nonempty")
1430 + macro("techDeployMentionedN", n(fbd["tech_deploy_total"][1]), "results/grounding/fallback_bounds.json", "tech_deploy_total[1]")
1431 +# -- resolver (results/resolver) --
1432 +if cp.get("mentions_by_key_branch"):
1433 + mbk = dict((str(k), v) for k, v in cp["mentions_by_key_branch"])
1434 + macro("mentionsKeyedLocation", n(mbk.get("location", 0)), "results/resolver/composition.json", "mentions_by_key_branch[location]")
1435 + macro("mentionsKeyedNameToken", n(mbk.get("name_token", 0)), "results/resolver/composition.json", "mentions_by_key_branch[name_token]")
1436 + macro("mentionsKeyedNameTokenPct", f"{100*mbk.get('name_token', 0)/M:.1f}", "results/resolver/composition.json", "100*name_token/mentions")
1437 + macro("mentionsKeyedLocationPct", f"{100*mbk.get('location', 0)/M:.1f}", "results/resolver/composition.json", "100*location/mentions")
1438 + geo = dict((str(k), v) for k, v in cp.get("location_keyed_projects_by_geo_kind", [])); pbk = dict((str(k), v) for k, v in cp["projects_by_key_branch"])
1439 + macro("locationKeysCountry", n(geo.get("country", 0)), "results/resolver/composition.json", "location_keyed_projects_by_geo_kind[country]")
1440 + macro("locationKeysUsState", n(geo.get("us_state", 0)), "results/resolver/composition.json", "location_keyed_projects_by_geo_kind[us_state]")
1441 + macro("locationKeysCountryStatePct", f"{100*(geo.get('country', 0)+geo.get('us_state', 0))/pbk.get('location', 1):.0f}", "results/resolver/composition.json", "100*(country+us_state)/location-keyed projects")
1442 + aoc_ = cp.get("amount_from_other_counterparty", [0, 0, 0]); aom_ = cp.get("amount_from_other_counterparty_ma", [0, 0, 0])
1443 + macro("maAmountOtherCounterpartyN", n(aom_[0]), "results/resolver/composition.json", "amount_from_other_counterparty_ma[0]"); macro("maAmountOtherCounterpartyDenom", n(aom_[1]), "results/resolver/composition.json", "amount_from_other_counterparty_ma[1]")
1444 + macro("amountOtherCounterpartyN", n(aoc_[0]), "results/resolver/composition.json", "amount_from_other_counterparty[0]"); macro("amountOtherCounterpartyDenom", n(aoc_[1]), "results/resolver/composition.json", "amount_from_other_counterparty[1]")
626 1445 if tn_path.exists():
627 − tn = rows(tn_path.stem, tn_path.parent)[:10]
628 − macro("topNameTokens", ", ".join(f"\\texttt{{{esc(r['name_tok'])}}} ({float(r['pct_of_tokenkeyed_projects']):.1f}\\%)" for r in tn), "results/resolver/top_name_tokens.csv", "top-10 tokens, pct of token-keyed projects")
629 − macro("topNameTokensProjectsPct", f"{sum(float(r['pct_of_tokenkeyed_projects']) for r in tn):.1f}", "results/resolver/top_name_tokens.csv", "sum of pct_of_tokenkeyed_projects over the top 10")
630 −csv_table("tab_top_name_tokens.tex", R / "resolver" / "top_name_tokens.csv", max_rows=20)
631 −csv_table("tab_overmerge.tex", R / "resolver" / "overmerge_by_type.csv")
632 −csv_table("tab_june_october.tex", R / "resolver" / "june_october_reconciliation.csv")
633 −csv_table("tab_table3_calls.tex", R / "ledger" / "table3_ledger_vs_stored.csv")
634 −
635 −# ---- headline macros ---------------------------------------------------------------------------------
1446 + tn0 = rows(tn_path.stem, tn_path.parent)[0]
1447 + macro("topTokenMentions", n(tn0["mentions"]), "results/resolver/top_name_tokens.csv", "mentions of the top token"); macro("topTokenProjects", n(tn0["projects"]), "results/resolver/top_name_tokens.csv", "projects of the top token")
1448 + macro("topTokenSharePct", pct(tn0["pct_of_tokenkeyed_mentions"]), "results/resolver/top_name_tokens.csv", "pct_of_tokenkeyed_mentions of the top token")
1449 +tl = R / "resolver" / "top_location_keys.csv"
1450 +if tl.exists():
1451 + us = next((r for r in rows(tl.stem, tl.parent) if r["loc1"] == "united states"), None)
1452 + if us: macro("locationKeyUnitedStatesProjects", n(us["projects"]), "results/resolver/top_location_keys.csv", "projects where loc1=united states")
1453 +if sc_path.exists():
1454 + def scv(key, thr, col):
1455 + r_ = next((r for r in sc if r["key"] == key and float(r["threshold"]) == thr), None); return r_[col] if r_ else None
1456 + for key, nm in (("k_cik_type", "CikType"), ("k_type_dropped", "TypeDropped"), ("k_name_only", "NameOnly"), ("k_city_normalised", "CityNorm"), ("k_current_stopwords", "Stopwords"), ("k_two_tokens", "TwoTokens"), ("k_strict", "Strict"), ("k_mention_level", "MentionLevel")):
1457 + v = scv(key, t0_, "projects")
1458 + if v is not None: macro(f"projectsKey{nm}", n(v), "results/resolver/spec_curve.csv", f"projects {key} at {t0_}")
1459 + v = scv("k_current", t1_, "projects")
1460 + if v is not None: macro("projectsCurrentKeyAtNine", n(v), "results/resolver/spec_curve.csv", f"projects k_current at {t1_}")
1461 + for key, nm in (("k_strict", "Strict"), ("k_cik_type", "CikType")):
1462 + v = scv(key, t0_, "single_mention_pct")
1463 + if v is not None: macro(f"singleMentionShare{nm}", pct(v), "results/resolver/spec_curve.csv", f"single_mention_pct {key} at {t0_}")
1464 + for key, nm in (("k_current", "Current"), ("k_strict", "Strict"), ("k_name_only", "NameOnly"), ("k_cik_type", "CikType")):
1465 + v = scv(key, t0_, "example_cluster_size_cheniere")
1466 + if v is not None: macro(f"chenierCluster{nm}", n(v), "results/resolver/spec_curve.csv", f"example_cluster_size_cheniere {key} at {t0_}")
1467 +omb = R / "resolver" / "overmerge_ma_by_bucket.csv"
1468 +if omb.exists():
1469 + r_ = next((r for r in rows(omb.stem, omb.parent) if r["bucket"].startswith(">")), None)
1470 + if r_: macro("maGeThreeNamesOverTenPct", pct(r_["pct_ge3_names"]), "results/resolver/overmerge_ma_by_bucket.csv", "pct_ge3_names bucket >10")
1471 +if om and "ma_integration" in om: macro("maGeThreePartnersPct", pct(om["ma_integration"]["pct_ge3_partners_among_with_partner"]), "results/resolver/overmerge_by_type.csv", "ma_integration pct_ge3_partners_among_with_partner")
1472 +if ti:
1473 + macro("projectsTieDistinctDescriptions", n(ti["projects_with_tie_and_distinct_descriptions"]), "results/resolver/ties_idempotence.json", "projects_with_tie_and_distinct_descriptions")
1474 + macro("rebuiltNameDiff", n(ti["rebuilt_vs_stored_diff"][0]), "results/resolver/ties_idempotence.json", "rebuilt_vs_stored_diff[0]"); macro("rebuiltDescDiff", n(ti["rebuilt_vs_stored_diff"][2]), "results/resolver/ties_idempotence.json", "rebuilt_vs_stored_diff[2]")
1475 + dv = ti["deterministic_vs_stored_diff"]
1476 + macro("tiebreakNameDiff", n(dv[0]), "results/resolver/ties_idempotence.json", "deterministic_vs_stored_diff[0]"); macro("tiebreakStatusDiff", n(dv[1]), "results/resolver/ties_idempotence.json", "deterministic_vs_stored_diff[1]"); macro("tiebreakDescDiff", n(dv[2]), "results/resolver/ties_idempotence.json", "deterministic_vs_stored_diff[2]")
1477 +if joj:
1478 + macro("juneProjects", n(joj["projects_from_backfilled_block_only"]), "results/resolver/june_october_reconciliation.json", "projects_from_backfilled_block_only")
1479 + macro("spMentions", n(joj["sp500_mentions_total"]), "results/resolver/june_october_reconciliation.json", "sp500_mentions_total"); macro("spProjects", n(joj["sp500_projects_total"]), "results/resolver/june_october_reconciliation.json", "sp500_projects_total")
1480 + comp_ = dict((str(k), v) for k, v in joj.get("sp500_projects_by_run_composition", []))
1481 + macro("spProjectsJuneOnly", n(comp_.get("june only", 0)), "results/resolver/june_october_reconciliation.json", "sp500_projects_by_run_composition[june only]")
1482 + macro("spProjectsBothRuns", n(comp_.get("both runs", 0)), "results/resolver/june_october_reconciliation.json", "sp500_projects_by_run_composition[both runs]")
1483 + macro("spProjectsOctoberOnly", n(comp_.get("october only", 0)), "results/resolver/june_october_reconciliation.json", "sp500_projects_by_run_composition[october only]")
1484 + ol = {r[0]: r for r in joj.get("sp500_october_ledger_by_form", [])}; bl = {r[0]: r for r in joj.get("ledger_block_accessions_by_form", [])}
1485 + mrf = {(r[0], r[1]): r for r in joj.get("sp500_mentions_by_run_form", [])}
1486 + if "10-Q" in ol: macro("octoberSpTenQSections", n(ol["10-Q"][2]), "results/resolver/june_october_reconciliation.json", "sp500_october_ledger_by_form 10-Q sections"); macro("octoberSpTenQFilings", n(ol["10-Q"][1]), "results/resolver/june_october_reconciliation.json", "sp500_october_ledger_by_form 10-Q filings")
1487 + if ("october", "10-Q") in mrf: macro("octoberSpTenQMentions", n(mrf[("october", "10-Q")][2]), "results/resolver/june_october_reconciliation.json", "sp500_mentions_by_run_form october 10-Q")
1488 + if ("october", "10-K") in mrf: macro("octoberSpTenKMentions", n(mrf[("october", "10-K")][2]), "results/resolver/june_october_reconciliation.json", "sp500_mentions_by_run_form october 10-K")
1489 + if ("october", "8-K") in mrf: macro("octoberSpEightKMentions", n(mrf[("october", "8-K")][2]), "results/resolver/june_october_reconciliation.json", "sp500_mentions_by_run_form october 8-K")
1490 + if ("backfilled_june", "10-Q") in mrf: macro("juneTenQMentions", n(mrf[("backfilled_june", "10-Q")][2]), "results/resolver/june_october_reconciliation.json", "sp500_mentions_by_run_form backfilled_june 10-Q")
1491 + macro("juneTenQFilings", n(joj["june_10q_accessions_in_block_ledger"]), "results/resolver/june_october_reconciliation.json", "june_10q_accessions_in_block_ledger")
1492 + if "10-Q" in bl: macro("juneTenQSections", n(bl["10-Q"][2]), "results/resolver/june_october_reconciliation.json", "ledger_block_accessions_by_form 10-Q sections")
1493 +# -- two runs / segmenters (results/runs) --
1494 +ge_md = R / "runs" / "git_evidence.md"
1495 +if ge_md.exists():
1496 + gtxt = ge_md.read_text()
1497 + m_ = re.search(r"## All commits.*?```\n(.*?)```", gtxt, re.S)
1498 + if m_: macro("repoCommits", word(len([l for l in m_.group(1).splitlines() if re.match(r"^[0-9a-f]{7} ", l)])), "results/runs/git_evidence.md", "number of commit lines")
1499 + m_ = re.search(r"extract/llm\.py\s+(\d{4}-\d{2}-\d{2})", gtxt)
1500 + if m_: macro("extractorMtimeDate", longdate(m_.group(1)), "results/runs/git_evidence.md", "mtime of extract/llm.py")
1501 +for pf, nm in (("git_diff_df7905d_2324b58.patch", "diffStoreLines"), ("git_diff_0304133_2324b58.patch", "diffParserLines")):
1502 + pp = R / "runs" / pf
1503 + if pp.exists():
1504 + txt_ = pp.read_text(errors="replace"); parts_ = re.split(r"^diff --git ", txt_, flags=re.M)
1505 + want_ = "filing_parser" if "Parser" in nm else "store.py"
1506 + sel_ = [q for q in parts_ if q.strip() and want_ in q.splitlines()[0]] if len(parts_) > 1 else parts_
1507 + ls__ = "\n".join(sel_).splitlines()
1508 + plus = sum(1 for l in ls__ if l.startswith("+") and not l.startswith("+++")); minus = sum(1 for l in ls__ if l.startswith("-") and not l.startswith("---"))
1509 + macro(nm, f"$+{plus}/-{minus}$", f"results/runs/{pf}", f"added/removed lines of the {want_} hunks")
1510 +if seg:
1511 + macro("legacyTenKRows", n(seg["legacy_rows"]), "results/runs/segmenters.json", "legacy_rows"); macro("legacyTenKFilings", n(seg["legacy_accessions"]), "results/runs/segmenters.json", "legacy_accessions")
1512 + macro("segPairs", n(seg["legacy_rows_matched_by_item"]), "results/runs/segmenters.json", "legacy_rows_matched_by_item")
1513 + macro("fullBodyMedianWords", n(seg["full_body_rows"][2]), "results/runs/segmenters.json", "full_body_rows[2]")
1514 + fa = seg.get("full_body_accessions_parsed_items_available", [None, None])
1515 + if fa[0] is not None: macro("fullBodyWithParsedItems", n(fa[0]), "results/runs/segmenters.json", "full_body_accessions_parsed_items_available[0]"); macro("fullBodyUnsubmittedSections", n(fa[1]), "results/runs/segmenters.json", "full_body_accessions_parsed_items_available[1]")
1516 + macro("fullDocumentTenK", n(seg["full_document_10k"][0]), "results/runs/segmenters.json", "full_document_10k[0]"); macro("fullDocumentTenKLegacy", n(seg["full_document_10k_in_legacy"]), "results/runs/segmenters.json", "full_document_10k_in_legacy")
1517 + macro("fullDocumentTenKInvisible", n(seg["full_document_10k_invisible_accessions"]), "results/runs/segmenters.json", "full_document_10k_invisible_accessions")
1518 + fdb = {r[0]: r for r in seg.get("full_document_by_form", [])}
1519 + if "10-Q" in fdb: macro("fullDocumentTenQ", n(fdb["10-Q"][1]), "results/runs/segmenters.json", "full_document_by_form 10-Q rows"); macro("fullDocumentTenQLedgered", n(fdb["10-Q"][3]), "results/runs/segmenters.json", "full_document_by_form 10-Q ledgered")
1520 + if seg.get("full_body_ledger_yield"):
1521 + fby = seg["full_body_ledger_yield"]; macro("fullBodyYield", f"{fby[3]:.2f}", "results/runs/segmenters.json", "full_body_ledger_yield[3] mentions per row"); macro("fullBodyProductivePct", f"{fby[4]:.1f}", "results/runs/segmenters.json", "full_body_ledger_yield[4]")
1522 +if fu:
1523 + for k, nm in (("parsed_10k_rows_total", "tenKparsedRows"), ("parsed_10k_rows_out_of_scope_item", "tenKoutOfScopeRows"), ("parsed_10k_in_scope_rows_of_legacy_accessions", "tenKlegacyAccessionRows"), ("parsed_10k_in_scope_rows_lt30_words_non_legacy", "tenKunderThirtyRows"), ("parsed_10k_in_scope_rows_ge30_non_legacy", "tenKparsedLedgered")):
1524 + macro(nm, n(fu[k]), "results/runs/funnel_10k.json", k)
1525 + if seg and seg.get("legacy_rows") and fu.get("ledger_10k_rows"): macro("legacyShareTenKLedgerPct", f"{100*seg['legacy_rows']/fu['ledger_10k_rows']:.0f}", "results/runs/segmenters.json, funnel_10k.json", "100*legacy_rows/ledger_10k_rows")
1526 +sic = R / "runs" / "segmenter_item_comparison.csv"
1527 +if sic.exists():
1528 + sd = {r["section_name"]: r for r in rows(sic.stem, sic.parent)}
1529 + if "md_and_a" in sd:
1530 + m = sd["md_and_a"]
1531 + macro("legacyMdnaDollar", n(m['legacy_mean_dollar']), "results/runs/segmenter_item_comparison.csv", "md_and_a legacy_mean_dollar"); macro("parsedMdnaDollar", n(m['parsed_mean_dollar']), "results/runs/segmenter_item_comparison.csv", "md_and_a parsed_mean_dollar")
1532 + macro("legacyMdnaWords", n(m["legacy_median_words"]), "results/runs/segmenter_item_comparison.csv", "md_and_a legacy_median_words"); macro("parsedMdnaWords", n(m["parsed_median_words"]), "results/runs/segmenter_item_comparison.csv", "md_and_a parsed_median_words")
1533 + macro("legacyFewerMoneyPct", pct(m["pct_legacy_fewer_money_tokens"]), "results/runs/segmenter_item_comparison.csv", "md_and_a pct_legacy_fewer_money_tokens")
1534 + macro("legacyMdnaNumeric", n(m['legacy_mean_numeric']), "results/runs/segmenter_item_comparison.csv", "md_and_a legacy_mean_numeric"); macro("parsedMdnaNumeric", n(m['parsed_mean_numeric']), "results/runs/segmenter_item_comparison.csv", "md_and_a parsed_mean_numeric")
1535 + if "properties" in sd: macro("propertiesLtHalfPct", pct(sd["properties"]["pct_legacy_lt_half_words"]), "results/runs/segmenter_item_comparison.csv", "properties pct_legacy_lt_half_words")
1536 +wsf = R / "runs" / "within_sp500_by_run_form.csv"
1537 +if wsf.exists():
1538 + for r in rows(wsf.stem, wsf.parent):
1539 + if r["form_type"] == "10-Q":
1540 + nm = "June" if r["run"] == "backfilled_june" else "October"
1541 + macro(f"withinProductive{nm}", pct(r["productive_pct"]), "results/runs/within_sp500_by_run_form.csv", f"{r['run']} 10-Q productive_pct"); macro(f"withinMentionsPerRow{nm}", pct(r['mentions_per_row'], 3), "results/runs/within_sp500_by_run_form.csv", f"{r['run']} 10-Q mentions_per_row")
1542 +wsm = R / "runs" / "within_sp500_10q_mentions_by_run.csv"
1543 +if wsm.exists():
1544 + for r in rows(wsm.stem, wsm.parent):
1545 + macro("withinConf" + ("June" if r["run"] == "backfilled_june" else "October"), f"{float(r['mean_conf']):.3f}", "results/runs/within_sp500_10q_mentions_by_run.csv", f"{r['run']} mean_conf")
1546 +wst = R / "runs" / "within_sp500_10q_type_mix_by_run.csv"
1547 +if wst.exists():
1548 + r_ = next((r for r in rows(wst.stem, wst.parent) if r["project_type"] == "ma_integration"), None)
1549 + if r_: macro("withinMaShareJune", pct(r_["june_pct"]), "results/runs/within_sp500_10q_type_mix_by_run.csv", "ma_integration june_pct"); macro("withinMaShareOctober", pct(r_["oct_pct"]), "results/runs/within_sp500_10q_type_mix_by_run.csv", "ma_integration oct_pct")
1550 +wp = jload("runs/within_issuer_paired_10q.json")
1551 +if wp:
1552 + macro("pairedIssuers", n(wp["issuers_paired"]), "results/runs/within_issuer_paired_10q.json", "issuers_paired"); macro("pairedDeltaPp", f"{100*wp['mean_diff_productive_share_oct_minus_june']:.1f}", "results/runs/within_issuer_paired_10q.json", "100*mean_diff_productive_share_oct_minus_june"); macro("pairedSePp", f"{100*wp['se']:.1f}", "results/runs/within_issuer_paired_10q.json", "100*se")
1553 +if t6.exists() and t6r:
1554 + crd = {r["cohort"]: r for r in rows(t6.stem, t6.parent)}
1555 + macro("cohortBothPerIssuerAll", pct(crd["both"]["per_issuer_all"]), "results/runs/table6_cohort.csv", "both per_issuer_all"); macro("cohortRussellOnlyPerIssuer", pct(crd["russell_only"]["per_issuer_all"]), "results/runs/table6_cohort.csv", "russell_only per_issuer_all"); macro("cohortBothPerIssuerOctober", pct(crd["both"]["per_issuer_october_only"]), "results/runs/table6_cohort.csv", "both per_issuer_october_only")
1556 + for k_, nm in (("projects_all_on_sp500", "All"), ("projects_october_only_on_sp500", "October"), ("projects_all_on_sp500_log_rows", "Controlled")):
1557 + m = t6r[k_]["in_sp500"]; macro(f"cohortOls{nm}", f"{m['coef']:.2f}", "results/runs/table6_cohort_regression.json", f"{k_}.in_sp500.coef"); macro(f"cohortOls{nm}Se", f"{m['hc1_se']:.2f}", "results/runs/table6_cohort_regression.json", f"{k_}.in_sp500.hc1_se")
1558 + macro("cohortOlsN", n(t6r["projects_all_on_sp500"]["n"]), "results/runs/table6_cohort_regression.json", "projects_all_on_sp500.n")
1559 +if fy_:
1560 + for run_, form_, nul, tot_ in fy_.get("mentions_fiscal_year_null_by_run_form", []):
1561 + if run_ == "october" and form_ == "10-Q": macro("fiscalYearNullOctTenQ", n(nul), "results/runs/fiscal_year_audit.json", "mentions_fiscal_year_null_by_run_form october 10-Q")
1562 + if run_ == "october" and form_ == "10-K": macro("fiscalYearNullOctTenK", n(nul), "results/runs/fiscal_year_audit.json", "mentions_fiscal_year_null_by_run_form october 10-K")
1563 + macro("fiscalYearNullFilings", n(sum(r[1] for r in fy_.get("src_filings_fiscal_year_null_by_form", []))), "results/runs/fiscal_year_audit.json", "sum src_filings_fiscal_year_null_by_form")
1564 +ffa = R / "runs" / "fiscal_year_fill_by_accession.csv"
1565 +if ffa.exists():
1566 + with open(ffa, newline="") as f: macro("fiscalYearFillAccessions", n(sum(1 for _ in csv.DictReader(f))), "results/runs/fiscal_year_fill_by_accession.csv", "row count")
1567 +# -- focus windows (results/focus) --
1568 +if sk:
1569 + macro("focusOverBudgetSections", n(sk["ledger_sections_over_9000_chars"]), "results/focus/stats_keys.json", "ledger_sections_over_9000_chars"); macro("focusOverBudgetSectionsPct", f"{100*sk['ledger_sections_over_9000_chars']/sk['ledger_sections']:.0f}", "results/focus/stats_keys.json", "100*over/ledger_sections")
1570 + macro("focusOverBudgetCalls", n(sk["calls_over_9000_chars"]), "results/focus/stats_keys.json", "calls_over_9000_chars"); macro("focusOverBudgetCallsPct", f"{100*sk['calls_over_9000_chars']/sk['calls']:.0f}", "results/focus/stats_keys.json", "100*calls_over/calls")
1571 + macro("focusMeanShownOverBudgetPct", f"{100*sk['mean_shown_frac_over_budget']:.1f}", "results/focus/stats_keys.json", "100*mean_shown_frac_over_budget")
1572 + macro("mdnaN", n(sk["ledger_10k_mdna_n"]), "results/focus/stats_keys.json", "ledger_10k_mdna_n"); macro("mdnaMedianWords", n(sk["ledger_10k_mdna_median_words"]), "results/focus/stats_keys.json", "ledger_10k_mdna_median_words"); macro("mdnaMedianChars", n(sk["ledger_10k_mdna_median_chars"]), "results/focus/stats_keys.json", "ledger_10k_mdna_median_chars")
1573 + macro("mdnaShownMedianPct", f"{100*sk['ledger_10k_mdna_shown_p50']:.1f}", "results/focus/stats_keys.json", "100*ledger_10k_mdna_shown_p50"); macro("mdnaLastShownMedianPct", f"{100*sk['ledger_10k_mdna_last_p50']:.0f}", "results/focus/stats_keys.json", "100*ledger_10k_mdna_last_p50")
1574 + macro("mdnaShownLtTwentyFivePct", f"{sk['ledger_10k_mdna_pct_shown_lt_25']:.1f}", "results/focus/stats_keys.json", "ledger_10k_mdna_pct_shown_lt_25"); macro("msgTruncatedN", n(sk["msg_truncated_14k"]), "results/focus/stats_keys.json", "msg_truncated_14k")
1575 + macro("mentionsFromLtTwentyFive", n(sk["mentions_from_sections_shown_lt_25"]), "results/focus/stats_keys.json", "mentions_from_sections_shown_lt_25"); macro("mentionsFromLtTwentyFivePct", f"{100*sk['mentions_from_sections_shown_lt_25']/sk['mentions_total']:.1f}", "results/focus/stats_keys.json", "100*mentions_from_sections_shown_lt_25/mentions_total")
1576 +if foc:
1577 + k_ = ("10-K", "md_and_a")
1578 + if k_ in foc:
1579 + macro("mdnaShownPTenPct", f"{100*float(foc[k_]['shown_p10']):.1f}", "results/focus/focus_coverage_by_form_item.csv", "10-K md_and_a shown_p10"); macro("mdnaShownPNinetyPct", f"{100*float(foc[k_]['shown_p90']):.0f}", "results/focus/focus_coverage_by_form_item.csv", "10-K md_and_a shown_p90"); macro("mdnaHitsShownMedianPct", f"{100*float(foc[k_]['hits_shown_p50']):.1f}", "results/focus/focus_coverage_by_form_item.csv", "10-K md_and_a hits_shown_p50")
1580 + for k_, nm in ((("10-K", "business"), "businessShownMedianPct"), (("10-K", "risk_factors"), "riskShownMedianPct"), (("10-Q", "md_and_a"), "tenQmdnaShownMedianPct"), (("10-Q", "financial_statements"), "tenQfinShownMedianPct")):
1581 + if k_ in foc: macro(nm, f"{100*float(foc[k_]['shown_p50']):.1f}", "results/focus/focus_coverage_by_form_item.csv", f"{k_[0]} {k_[1]} shown_p50")
1582 + for k_, nm in ((("10-K", "md_and_a"), "capexVocabShownMdnaPct"), (("10-K", "business"), "capexVocabShownBusinessPct"), (("10-Q", "md_and_a"), "capexVocabShownTenQmdnaPct")):
1583 + if k_ in foc: macro(nm, pct(foc[k_]["pct_capex_vocab_shown_over_budget"]), "results/focus/focus_coverage_by_form_item.csv", f"{k_[0]} {k_[1]} pct_capex_vocab_shown_over_budget")
1584 + if ("8-K", "full_body") in foc: macro("eightKWholePct", f"{100-float(foc[('8-K', 'full_body')]['pct_over_9000']):.0f}", "results/focus/focus_coverage_by_form_item.csv", "100 - 8-K pct_over_9000")
1585 +if fbf.exists():
1586 + for r in rows(fbf.stem, fbf.parent): macro("mentionsFromLtTwentyFive" + {"10-K": "TenK", "10-Q": "TenQ", "8-K": "EightK"}[r["form"]], pct(r["pct_mentions_from_lt25"], 0), "results/focus/focus_coverage_by_form.csv", f"{r['form']} pct_mentions_from_lt25")
1587 +mvl = R / "focus" / "mentions_vs_length_by_item.csv"
1588 +if mvl.exists():
1589 + md_rows = [r for r in rows(mvl.stem, mvl.parent) if r["form"] == "10-K" and r["item"] == "md_and_a"]
1590 + if md_rows:
1591 + low_ = next((r for r in md_rows if r["len_bin"].startswith("b")), md_rows[0]); plat = [r for r in md_rows if r["len_bin"] >= "f"]
1592 + macro("plateauLow", pct(low_['mean_mentions']), "results/focus/mentions_vs_length_by_item.csv", "10-K md_and_a mean_mentions, 3-6k bin"); macro("plateauHigh", pct(plat[0]['mean_mentions']), "results/focus/mentions_vs_length_by_item.csv", "10-K md_and_a mean_mentions, 20-40k bin (plateau start)")
1593 + macro("plateauRange", f"{min(float(r['mean_mentions']) for r in plat):.1f}--{max(float(r['mean_mentions']) for r in plat):.1f}", "results/focus/mentions_vs_length_by_item.csv", "10-K md_and_a mean_mentions over bins >= 20k"); macro("plateauKchars", n(20e3), "results/focus/mentions_vs_length_by_item.csv", "lower edge of the f20-40k bin")
1594 + macro("mentionsPerTenKShownChars", pct(sorted(float(r['mentions_per_10k_shown_chars']) for r in plat)[len(plat) // 2]), "results/focus/mentions_vs_length_by_item.csv", "median mentions_per_10k_shown_chars over bins >= 20k")
1595 +if mdl.exists():
1596 + md_ = rows(mdl.stem, mdl.parent); a_ = sum(int(r["lt30_words"]) for r in md_); b_ = sum(int(r["mdna_sections"]) for r in md_)
1597 + macro("shortMdnaN", n(a_), "results/focus/mdna_10k_short_by_year.csv", "sum(lt30_words)"); macro("shortMdnaDenom", n(b_), "results/focus/mdna_10k_short_by_year.csv", "sum(mdna_sections)"); macro("shortMdnaPct", f"{100*a_/b_:.1f}", "results/focus/mdna_10k_short_by_year.csv", "100*sum(lt30)/sum(sections)")
1598 + macro("shortMdnaIncorporatedN", n(sum(int(r["lt300_incorporated_by_ref"]) for r in md_)), "results/focus/mdna_10k_short_by_year.csv", "sum(lt300_incorporated_by_ref)")
1599 +# -- rules baseline (results/rules) --
1600 +if rflo.exists():
1601 + o = rows(rflo.stem, rflo.parent)[0]
1602 + macro("rulesFocusRecovered", n(o["rules_focused"]), "results/rules/focus_recall_loss_overall.csv", "rules_focused"); macro("rulesFocusTotal", n(o["rules_full"]), "results/rules/focus_recall_loss_overall.csv", "rules_full"); macro("rulesFocusRecoveredPct", f"{100-float(o['pct_lost']):.1f}", "results/rules/focus_recall_loss_overall.csv", "100 - pct_lost")
1603 +if rfl.exists():
1604 + for r in rows(rfl.stem, rfl.parent):
1605 + nm = {("10-K", "md_and_a"): "rulesFocusMdnaPct", ("10-K", "business"): "rulesFocusBusinessPct", ("10-Q", "md_and_a"): "rulesFocusTenQmdnaPct", ("8-K", "full_body"): "rulesFocusEightKPct"}.get((r["form_type"], r["item"]))
1606 + if nm: macro(nm, f"{100-float(r['pct_rules_mentions_lost_to_focus']):.1f}", "results/rules/focus_recall_loss.csv", f"{r['form_type']} {r['item']} 100 - pct_rules_mentions_lost_to_focus")
1607 +if rao.exists():
1608 + ov = rows(rao.stem, rao.parent)[0]
1609 + macro("rulesSampleProductive", n(ov["llm_pos"]), "results/rules/agreement_overall.csv", "llm_pos (sampled productive sections)"); macro("rulesSampleZero", n(int(ov["n_sampled"]) - int(ov["llm_pos"])), "results/rules/agreement_overall.csv", "n_sampled - llm_pos")
1610 + macro("rulesFlagPct", pct(ov["rules_pos_pct_weighted"]), "results/rules/agreement_overall.csv", "rules_pos_pct_weighted"); macro("rulesAgreementPct", pct(ov["agreement_pct_w"]), "results/rules/agreement_overall.csv", "agreement_pct_w")
1611 + macro("rulesLlmOnlyPct", pct(ov["llm_only_pct_w"]), "results/rules/agreement_overall.csv", "llm_only_pct_w"); macro("rulesOnlyPct", pct(ov["rules_only_pct_w"]), "results/rules/agreement_overall.csv", "rules_only_pct_w"); macro("rulesTypeOverlapPct", pct(ov["type_overlap_pct_codetected"]), "results/rules/agreement_overall.csv", "type_overlap_pct_codetected")
1612 +if rab.exists():
1613 + for r in rows(rab.stem, rab.parent): macro("rulesGivenLlm" + {"10-K": "TenK", "10-Q": "TenQ", "8-K": "EightK"}[r["form_type"]], pct(r["p_rules_given_llm"]), "results/rules/agreement_by_form.csv", f"{r['form_type']} p_rules_given_llm")
1614 +rar = R / "rules" / "agreement_by_run.csv"
1615 +if rar.exists():
1616 + for r in rows(rar.stem, rar.parent): macro("rulesGivenLlm" + ("June" if r["run"] == "backfilled_june" else "October"), pct(r["p_rules_given_llm"]), "results/rules/agreement_by_run.csv", f"{r['run']} p_rules_given_llm")
1617 +rta = R / "rules" / "type_agreement.csv"
1618 +if rta.exists():
1619 + for r in rows(rta.stem, rta.parent):
1620 + nm = {"ma_integration": "Ma", "drug_pipeline": "Drug", "cost_reduction": "Cost", "capex_program": "Capex", "plant_construction": "Plant", "geographic_expansion": "Geo"}.get(r["llm_type"])
1621 + if nm: macro(f"rulesType{nm}", pct(r["pct"]), "results/rules/type_agreement.csv", f"{r['llm_type']} pct")
1622 +# -- financing class (results/fp_classes) --
1623 +if fps:
1624 + mm = fps["mentions_matched"]; macro("finMentions", n(mm[0]), "results/fp_classes/summary.json", "mentions_matched[0]"); macro("finMentionsPct", pct(mm[2]), "results/fp_classes/summary.json", "mentions_matched[2]")
1625 + macro("finAmountB", f"{fps['matched_amount_gusd'][0]/1e3:.1f}", "results/fp_classes/summary.json", "matched_amount_gusd[0]/1e3 (T USD)"); macro("finAmountDenomB", f"{fps['matched_amount_gusd'][1]/1e3:.1f}", "results/fp_classes/summary.json", "matched_amount_gusd[1]/1e3 (T USD)")
1626 + macro("finAmountSharePct", f"{100*fps['matched_amount_gusd'][0]/fps['matched_amount_gusd'][1]:.1f}", "results/fp_classes/summary.json", "100*matched_amount_gusd[0]/[1]")
1627 + us_ = fps["unregistered_sales_matched"]; macro("finUnregPct", f"{100*us_[0]/us_[1]:.1f}", "results/fp_classes/summary.json", "100*unregistered_sales_matched[0]/[1]"); macro("finUnregN", n(us_[0]), "results/fp_classes/summary.json", "unregistered_sales_matched[0]"); macro("finUnregDenom", n(us_[1]), "results/fp_classes/summary.json", "unregistered_sales_matched[1]")
1628 + fs_ = fps["financial_statements_matched"]; macro("finFinStatementsPct", f"{100*fs_[0]/fs_[1]:.1f}", "results/fp_classes/summary.json", "100*financial_statements_matched[0]/[1]")
1629 + cm_ = fps["controls_matched"]; macro("finControlsPct", f"{100*cm_[0]/cm_[1]:.1f}", "results/fp_classes/summary.json", "100*controls_matched[0]/[1]")
1630 + macro("finProjectsRep", n(fps["projects_matched_rep"][0]), "results/fp_classes/summary.json", "projects_matched_rep[0]"); macro("finProjectsRepPct", f"{100*fps['projects_matched_rep'][0]/P:.1f}", "results/fp_classes/summary.json", "100*projects_matched_rep[0]/projects"); macro("finProjectsAny", n(fps["projects_matched_rep"][1]), "results/fp_classes/summary.json", "projects_matched_rep[1]")
1631 + ic = fps.get("item2_collision", [])
1632 + if ic:
1633 + macro("itemTwoPairs", n(ic[0]), "results/fp_classes/summary.json", "item2_collision pairs"); macro("unregMedianWords", n(ic[1]), "results/fp_classes/summary.json", "item2_collision median_unreg_words"); macro("tenQmdnaMedianWords", n(ic[2]), "results/fp_classes/summary.json", "item2_collision median_mdna_words")
1634 + macro("unregGtThreeK", n(ic[3]), "results/fp_classes/summary.json", "item2_collision unreg_gt_3000"); macro("unregGtThreeKPct", f"{ic[4]:.1f}", "results/fp_classes/summary.json", "item2_collision pct_gt_3000"); macro("swapCandidates", n(ic[7]), "results/fp_classes/summary.json", "item2_collision swapped_candidates")
1635 + macro("unregLongThreshold", n(3e3), "results/fp_classes/summary.json", "item2_collision threshold (unreg_gt_3000)")
1636 + if fps.get("unregistered_sales_mentions_from_gt3000"): macro("unregGtThreeKMentions", n(fps["unregistered_sales_mentions_from_gt3000"][0]), "results/fp_classes/summary.json", "unregistered_sales_mentions_from_gt3000[0]")
1637 +if fpath.exists():
1638 + r_ = next((r for r in rows(fpath.stem, fpath.parent) if r["form_type"] == "8-K"), None)
1639 + if r_: macro("finEightKPct", pct(r_["pct"]), "results/fp_classes/financing_regex_by_item.csv", "8-K full_body pct")
1640 +if fpt.exists():
1641 + for r in rows(fpt.stem, fpt.parent):
1642 + nm = {"capex_program": "finCapexPct", "cost_reduction": "finCostPct", "ma_integration": "finMaPct"}.get(r["project_type"])
1643 + if nm: macro(nm, pct(r["pct"]), "results/fp_classes/financing_regex_by_type.csv", f"{r['project_type']} pct")
1644 +if fterms.exists():
1645 + for r in rows(fterms.stem, fterms.parent):
1646 + nm = {"repurchase": "finTermRepurchase", "senior notes": "finTermSeniorNotes", "term loan": "finTermTermLoan"}.get(r["fin_term"])
1647 + if nm: macro(nm, n(r["n"]), "results/fp_classes/financing_regex_terms.csv", f"{r['fin_term']} n")
1648 +if rx:
1649 + for code, nm in (("capex_program", "capex"), ("cost_reduction", "cost"), ("ma_integration", "ma")):
1650 + if code in rx: macro(f"{nm}ProjectsExcl", n(rx[code]["n_excl_rep"]), "results/fp_classes/table5_restated_excl_financing.csv", f"{code} n_excl_rep")
1651 + if "capex_program" in rx: macro("capexShareExcl", pct(rx["capex_program"]["pct_excl_rep"]), "results/fp_classes/table5_restated_excl_financing.csv", "capex_program pct_excl_rep")
1652 +# -- 8-K benchmark --
1653 +if b8.exists():
1654 + def b8get(ptype, item): return next((r for r in B8 if r["project_type"] == ptype and r["item"] == item), None)
1655 + macro("eightKItemCodePct", f"{b8s.get('coverage_pct', 0):.1f}", "results/benchmark_8k/summary.json", "coverage_pct")
1656 + r_ = b8get("ma_integration", "Item 2.01")
1657 + if r_:
1658 + macro("benchMaGivenTwoOhOne", f"{float(r_['p_type_given_item']):.3f}", "results/benchmark_8k/item_vs_type.csv", "ma_integration Item 2.01 p_type_given_item"); macro("benchMaGivenTwoOhOneCiLow", f"{float(r_['ci_low_1']):.3f}", "results/benchmark_8k/item_vs_type.csv", "ci_low_1"); macro("benchMaGivenTwoOhOneCiHigh", f"{float(r_['ci_high_1']):.3f}", "results/benchmark_8k/item_vs_type.csv", "ci_high_1")
1659 + macro("benchTwoOhOneN", n(r_["n_item"]), "results/benchmark_8k/item_vs_type.csv", "n_item Item 2.01"); macro("benchMaBase", f"{float(r_['base_rate_type']):.3f}", "results/benchmark_8k/item_vs_type.csv", "ma_integration base_rate_type")
1660 + r_ = b8get("ma_integration", "Item 8.01 (control)")
1661 + if r_: macro("benchMaGivenEightOhOne", f"{float(r_['p_type_given_item']):.3f}", "results/benchmark_8k/item_vs_type.csv", "ma_integration Item 8.01 p_type_given_item")
1662 + r_ = b8get("ma_integration", "Item 5.02 (control)")
1663 + if r_: macro("benchMaGivenFiveOhTwo", f"{float(r_['p_type_given_item']):.3f}", "results/benchmark_8k/item_vs_type.csv", "ma_integration Item 5.02 p_type_given_item")
1664 + r_ = b8get("ma_integration", "Item 2.01 or 1.01")
1665 + if r_: macro("benchItemsGivenMa", f"{float(r_['p_item_given_type']):.3f}", "results/benchmark_8k/item_vs_type.csv", "ma_integration Item 2.01 or 1.01 p_item_given_type")
1666 + r_ = b8get("cost_reduction", "Item 2.05")
1667 + if r_:
1668 + macro("benchCostGivenTwoOhFive", f"{float(r_['p_type_given_item']):.3f}", "results/benchmark_8k/item_vs_type.csv", "cost_reduction Item 2.05 p_type_given_item"); macro("benchCostGivenTwoOhFiveCiLow", f"{float(r_['ci_low_1']):.3f}", "results/benchmark_8k/item_vs_type.csv", "ci_low_1"); macro("benchCostGivenTwoOhFiveCiHigh", f"{float(r_['ci_high_1']):.3f}", "results/benchmark_8k/item_vs_type.csv", "ci_high_1")
1669 + macro("benchTwoOhFiveN", n(r_["n_item"]), "results/benchmark_8k/item_vs_type.csv", "n_item Item 2.05"); macro("benchCostLift", f"{float(r_['lift_type_given_item']):.0f}", "results/benchmark_8k/item_vs_type.csv", "lift_type_given_item"); macro("benchTwoOhFiveGivenCost", f"{float(r_['p_item_given_type']):.3f}", "results/benchmark_8k/item_vs_type.csv", "p_item_given_type")
1670 + r_ = b8get("partnership", "Item 1.01")
1671 + if r_: macro("benchPartnershipGivenOneOhOne", f"{float(r_['p_type_given_item']):.3f}", "results/benchmark_8k/item_vs_type.csv", "partnership Item 1.01 p_type_given_item"); macro("benchPartnershipBase", f"{float(r_['base_rate_type']):.3f}", "results/benchmark_8k/item_vs_type.csv", "partnership base_rate_type")
1672 +# -- annotation frame (results/annotation_frame/design.json) --
1673 +if ad_:
1674 + for k, nm, fmt in (("seed", "annSeed", str), ("n_strata_productive", "annStrata", n), ("n_productive", "annNProductive", n), ("n_zero", "annNZero", n), ("zero_frame_gate_pass", "annZeroGatePass", n), ("zero_frame_gate_reject", "annZeroGateReject", n),
1675 + ("deff_productive", "annDeffProductive", lambda v: f"{v:.1f}"), ("deff_zero", "annDeffZero", lambda v: f"{v:.1f}"), ("half_width_95_precision_p0.5", "annHalfWidthPrecision", lambda v: f"{100*v:.1f}"),
1676 + ("mde_gate_recall_diff_at_p0.05", "annMde", lambda v: f"{100*v:.1f}"), ("floor", "annFloor", n), ("oversample_conf_0.45_0.7", "annOversample", lambda v: f"{v:.0f}"), ("population_productive", "annPopProductive", n), ("population_zero", "annPopZero", n)):
1677 + if ad_.get(k) is not None: macro(nm, fmt(ad_[k]), "results/annotation_frame/design.json", k)
1678 + if isinstance(ad_.get("half_width_95_zero_fn_rate"), dict): macro("annHalfWidthFn", f"{100*ad_['half_width_95_zero_fn_rate']['0.05']:.1f}", "results/annotation_frame/design.json", "half_width_95_zero_fn_rate[0.05]")
1679 + if isinstance(ad_.get("core_subsample"), dict): macro("annCore", n(ad_["core_subsample"]["productive"]), "results/annotation_frame/design.json", "core_subsample.productive")
1680 + if isinstance(ad_.get("split"), dict): macro("annDev", n(ad_["split"]["dev"]), "results/annotation_frame/design.json", "split.dev"); macro("annHoldout", n(ad_["split"]["holdout"]), "results/annotation_frame/design.json", "split.holdout")
1681 + macro("annTextChars", n(2e3), "results/annotation_frame/frame_dev.csv", "text truncation of the worktree frames (characters)")
1682 + dim("annotation_frame_mb", "annFrameMb")
1683 +# -- time series --
1684 +if TS:
1685 + macro("firstSeenLastYear", n(allr[max(allr)]["first_seen_current_key"]), "results/timeseries/first_seen_fixed_cohort.csv", "all_issuers last year first_seen_current_key")
1686 + macro("fixedCohortIssuers", n(tss["cohort_issuers"]), "results/timeseries/summary.json", "cohort_issuers")
1687 + macro("fixedCohortMentionsPerIssuerFirst", pct(coh[inner_c[0]]["mentions_per_issuer_filing"]), "results/timeseries/first_seen_fixed_cohort.csv", f"fixed cohort {inner_c[0]}"); macro("fixedCohortMentionsPerIssuerLast", pct(coh[inner_c[-1]]["mentions_per_issuer_filing"]), "results/timeseries/first_seen_fixed_cohort.csv", f"fixed cohort {inner_c[-1]}")
1688 + macro("fixedCohortNewPerIssuerFirst", pct(coh[inner_c[0]]["first_seen_per_issuer"]), "results/timeseries/first_seen_fixed_cohort.csv", f"fixed cohort {inner_c[0]}"); macro("fixedCohortNewPerIssuerLast", pct(coh[inner_c[-1]]["first_seen_per_issuer"]), "results/timeseries/first_seen_fixed_cohort.csv", f"fixed cohort {inner_c[-1]}")
1689 + macro("fixedCohortFirstSeenFirst", n(coh[inner_c[0]]["first_seen_current_key"]), "results/timeseries/first_seen_fixed_cohort.csv", f"fixed cohort {inner_c[0]}"); macro("fixedCohortFirstSeenLast", n(coh[inner_c[-1]]["first_seen_current_key"]), "results/timeseries/first_seen_fixed_cohort.csv", f"fixed cohort {inner_c[-1]}")
1690 + macro("episodesKthree", n(tss["episodes_k3_total"]), "results/timeseries/summary.json", "episodes_k3_total"); macro("episodesKfive", n(tss["episodes_k5_total"]), "results/timeseries/summary.json", "episodes_k5_total")
1691 +# -- universe --
1692 +macro("dualClassCiks", n(U["russell_equity_lines_mapped"] - U["russell_distinct_ciks"]), "stats.json:universe", "mapped lines - distinct CIKs")
1693 +macro("universeBoth", n(U["both"]), "stats.json:universe.both", "count"); macro("universeSpOnly", n(U["sp_only"]), "stats.json:universe.sp_only", "count"); macro("universeRuOnly", n(U["ru_only"]), "stats.json:universe.ru_only", "count")
1694 +if rc.get("index_constituents"):
1695 + macro("russellGapMax", n(rc["index_constituents"] - U["russell_distinct_ciks"]), "results/russell_coverage.json", "index_constituents - russell_distinct_ciks"); macro("russellGapMaxPct", f"{100*(rc['index_constituents'] - U['russell_distinct_ciks'])/rc['index_constituents']:.1f}", "results/russell_coverage.json", "100*(index - proxy)/index")
1696 + macro("factsheetDate", longdate(rc["index_as_of"]), "results/russell_coverage.json:index_as_of", "date")
1697 +try:
1698 + import datetime as _dt
1699 + macro("iwvHoldingsDate", longdate(_dt.datetime.strptime(U["russell_holdings_as_of"], "%b %d, %Y").date().isoformat()), "stats.json:universe.russell_holdings_as_of", "date")
1700 +except Exception: pass
1701 +macro("iwvFetchDate", longdate(U["russell_fetched_at"]), "stats.json:universe.russell_fetched_at", "date"); macro("spWikipediaRows", n(U["sp500_rows"]), "stats.json:universe.sp500_rows", "count"); macro("spWikipediaDate", longdate(U["sp500_fetched_at"]), "stats.json:universe.sp500_fetched_at", "date")
1702 +if ua.get("cik_mapping_scalars"): macro("tickerMapSize", n(ua["cik_mapping_scalars"]["count"]), "results/universe/universe_artefacts.json", "cik_mapping_scalars.count")
1703 +macro("issuersFilingsNoProject", n(S["issuers_with_filings"] - S["issuers_with_projects"]), "stats.json", "issuers_with_filings - issuers_with_projects")
1704 +macro("parseErrors", str(perr), "data/parse_status.csv", "sum(error)"); macro("filingsNotParsedPct", f"{100*not_parsed/S['filings_total']:.3f}", "data/parse_status.csv, stats.json", "100*not_parsed/filings_total")
1705 +# -- environment / package --
1706 +for pk in ("rules", "n0_probe", "ledger"):
1707 + mf_ = jload(f"{pk}/manifest.json")
1708 + if isinstance(mf_.get("databases"), dict):
1709 + for pth, meta in mf_["databases"].items():
1710 + if pth.endswith("edgar_research.duckdb"): macro("corpusDbGb", f"{meta['bytes']/2**30:.0f}", f"results/{pk}/manifest.json", "edgar_research.duckdb bytes / 2^30")
1711 + if pth.endswith("spid.duckdb"): macro("spidDbGb", f"{meta['bytes']/1e9:.1f}", f"results/{pk}/manifest.json", "spid.duckdb bytes / 1e9")
1712 + break
1713 +dim("corpus_parquet_gb", "corpusParquetGb")
1714 +rl = ROOT / "requirements.lock"
1715 +if rl.exists(): macro("requirementsLockPackages", str(sum(1 for l in rl.read_text().splitlines() if l.strip() and not l.startswith("#"))), "requirements.lock", "non-comment lines")
1716 +pv = ROOT / ".python-version"
1717 +if pv.exists(): macro("pythonVersion", pv.read_text().strip(), ".python-version", "file content")
1718 +em = ROOT / "environment.md"
1719 +if em.exists():
1720 + m_ = re.search(r"duckdb \(python\): ([0-9.]+)", em.read_text())
1721 + if m_: macro("duckdbVersion", m_.group(1), "environment.md", "duckdb (python)")
1722 +tt_ = ROOT / "tests" / "test_tables.py"
1723 +if tt_.exists():
1724 + src_ = tt_.read_text(); ntests = len(re.findall(r"^def test_", src_, re.M)); npar = sum(len(re.findall(r"\n\s*\(", m)) for m in re.findall(r"parametrize\((.*?)\)\ndef", src_, re.S))
1725 + macro("testsN", str(ntests - 1 + npar if npar else ntests), "tests/test_tables.py", "test functions, parametrised cases expanded")
1726 +sh_ = SNAP / "SHA256SUMS"
1727 +if sh_.exists(): macro("snapshotFilesN", word(sum(1 for l in sh_.read_text().splitlines() if l.strip())), "code/audit/spid_snapshot/SHA256SUMS", "lines")
1728 +ft_ = D / "factor_tables.csv"
1729 +if ft_.exists():
1730 + for r in rows("factor_tables"):
1731 + if r["t"] == "annual_panel": macro("annualPanelRows", n(r["n"]), "data/factor_tables.csv", "annual_panel n")
1732 + if r["t"] == "quarterly_panel": macro("quarterlyPanelRows", n(r["n"]), "data/factor_tables.csv", "quarterly_panel n")
1733 +macro("mentionsPerProjectDrug", f"{float(ptd['drug_pipeline']['mean_mentions']):.2f}", "data/projects_by_type.csv", "drug_pipeline mean_mentions") if "drug_pipeline" in ptd else None
1734 +macro("mentionsPerProjectTechDeploy", f"{float(ptd['technology_deployment']['mean_mentions']):.2f}", "data/projects_by_type.csv", "technology_deployment mean_mentions") if "technology_deployment" in ptd else None
1735 +if "cost_reduction" in ptd: macro("nCostReduction", n(ptd["cost_reduction"]["n"]), "data/projects_by_type.csv", "cost_reduction n")
1736 +macro("amountPTwentyFiveMusd", f"{q[1]/1e6:,.0f}".replace(",", "{,}"), "data/amount_dist.csv", "q[1]/1e6")
1737 +macro("spanZeroN", n(dus["0"]), "data/duration.csv", "n where span_years=0")
1738 +macro("confShareHalf", f"{100*cfd.get(0.5, 0)/M:.1f}", "data/confidence_dist.csv", "100*n(conf=0.5)/mentions")
1739 +kge = {r["node_type"]: r["n"] for r in kg if r["k"] == "edges"}
1740 +for e_, nm in (("owns", "kgEdgesOwns"), ("located_in", "kgEdgesLocatedIn"), ("uses", "kgEdgesUses")):
1741 + if e_ in kge: macro(nm, n(kge[e_]), "data/kg.csv", f"edges {e_}")
1742 +macro("projectsPerIssuerMax", n(rows("projects_per_issuer")[0]["mx"]), "data/projects_per_issuer.csv", "mx")
1743 +# -- pipeline constants read from the frozen snapshot and the archived pipeline code (manuscripts/.../pipeline_code_2324b58) --
1744 +PIPE = ROOT.parent.parent / "manuscripts" / "FIRC-0001" / "pipeline_code_2324b58"
1745 +llm_src = _snapshot("llm.py"); cfg_src = _snapshot("config.py"); pipe_src = _snapshot("pipeline.py")
1746 +v = rxs(llm_src, r"m\.start\(\) - (\d+)", int); macro("focusWindowBefore", n(v), rel(llm_src), "_focus: characters before a gate hit") if v else None
1747 +v = rxs(llm_src, r"m\.end\(\) \+ (\d+)", int); macro("focusWindowAfter", n(v), rel(llm_src), "_focus: characters after a gate hit") if v else None
1748 +bud = rxs(llm_src, r"def _focus\(text: str, budget: int = (\d+)\)", int)
1749 +if bud:
1750 + macro("focusEmitBudget", n(bud), rel(llm_src), "_focus budget"); mult = rxs(llm_src, r"> budget \* ([0-9.]+)", float)
1751 + if mult: macro("focusCollectBudget", n(bud * mult), rel(llm_src), "budget * collection multiplier")
1752 +v = rxs(llm_src, r"_focus\(text\)\)\[:(\d+)\]", int); macro("userMessageCap", n(v), rel(llm_src), "user message cut") if v else None
1753 +v = rxs(llm_src, r"get\(\"confidence\", ([0-9.]+)\)", str); macro("confDefault", v, rel(llm_src), "default confidence") if v else None
1754 +v = rxs(llm_src, r"conf[^\n]*< ?([0-9]\.[0-9]+)", str) or rxs(llm_src, r"min_conf[^\n]*=\s*([0-9]\.[0-9]+)", str) or rxs(cfg_src, r"(0\.45)", str); macro("confThreshold", v, rel(llm_src), "confidence threshold") if v else None
1755 +v = rxs(llm_src, r"\"max_tokens\": (\d+)", int); macro("completionTokens", n(v), rel(llm_src), "max_tokens") if v else None
1756 +v = rxs(llm_src, r"\]\[:(\d+)\]\s*$", int) or rxs(llm_src, r"strip\(\)\]\[:(\d+)\]", int); macro("listItemsMax", word(v), rel(llm_src), "list truncation (items)") if v else None
1757 +v = rxs(llm_src, r"strip\(\)\[:(\d+)\] for x in v", int); macro("listItemChars", n(v), rel(llm_src), "list item truncation (characters)") if v else None
1758 +v = rxs(llm_src, r"project_name',''\)\)\[:(\d+)\]", int); macro("idNameChars", n(v), rel(llm_src), "anchor name prefix length") if v else None
1759 +v = rxs(llm_src, r"retries: int = (\d+)", int); macro("retries", word(v), rel(llm_src), "_call retries") if v else None
1760 +v = rxs(cfg_src, r"llm_timeout: float = ([0-9.]+)", float); macro("timeoutSeconds", n(v), rel(cfg_src), "llm_timeout") if v else None
1761 +v = rxs(pipe_src, r"min_words: int = (\d+)", int); macro("minWords", n(v), rel(pipe_src), "min_words") if v else None
1762 +v = rxs(PIPE / "src/parsing/chunker.py", r"chunk_size: int = (\d+)", int); macro("chunkWords", n(v), "src/parsing/chunker.py", "chunk_size") if v else None
1763 +v = rxs(PIPE / "src/parsing/chunker.py", r"overlap: int = (\d+)", int); macro("chunkOverlap", n(v), "src/parsing/chunker.py", "overlap") if v else None
1764 +v = rxs(PIPE / "src/parsing/html_parser.py", r"max_file_size_mb\", (\d+)", int); macro("maxFileMb", n(v), "src/parsing/html_parser.py", "max_file_size_mb default") if v else None
1765 +v = rxs(PIPE / "src/acquisition/bulk_downloader.py", r"COOLDOWN_SECONDS = ([0-9.]+)", float); macro("cooldownSeconds", n(v), "src/acquisition/bulk_downloader.py", "COOLDOWN_SECONDS") if v else None
1766 +v = rxs(PIPE / "src/acquisition/bulk_downloader.py", r"SEC allows (\d+) req/s", int); macro("secRateLimit", word(v), "src/acquisition/bulk_downloader.py (docstring) / secfairaccess", "requests per second per IP") if v else None
1767 +v = rxs(PIPE / "src/acquisition/bulk_downloader.py", r"rate: float = ([0-9.]+)", float); macro("acqGatewayDivisor", word(v), "src/acquisition/bulk_downloader.py", "default aggregate rate shared behind one IP") if v else None
1768 +for key_, nm in (("acq_new_docs", "acqNewDocs"), ("acq_hours", "acqHours"), ("acq_req_per_sec", "acqReqPerSec"), ("acq_nodes", "acqNodes"), ("acq_node_rate", "acqNodeRate"), ("acq_gateway_rate", "acqGatewayRate"),
1769 + ("parse_filings_per_sec", "parseFilingsPerSec"), ("parse_minutes_range", "parseMinutesRange"), ("embed_minutes_range", "embedMinutesRange"), ("merge_minutes", "mergeMinutes"), ("total_cost_usd", "totalCostUsd"),
1770 + ("stability_sections", "stabilitySections"), ("stability_calls", "stabilityCalls"), ("embedding_dim", "embeddingDim"), ("factor_anchors", "factorAnchors"), ("tenk_sections_max", "tenKsectionsMax"), ("tenq_sections_n", "tenQsectionsN")):
1771 + dim(key_, nm)
1772 +
1773 +# ---- headline macros ---------------------------------------------------------------------------------------------------------
636 1774 macro("projects", n(P), "stats.json:projects", "count(projects)")
637 1775 macro("mentions", n(M), "stats.json:mentions", "count(project_mentions)")
638 1776 macro("issuersWithProjects", n(S["issuers_with_projects"]), "stats.json:issuers_with_projects", "count(distinct cik)")
639 1777 macro("issuersWithFilings", n(S["issuers_with_filings"]), "stats.json:issuers_with_filings", "count(distinct cik) in filings")
1778 +macro("issuersWithoutFilings", n(S["issuers_without_filings"]), "stats.json:issuers_without_filings", "count")
640 1779 macro("sectionsTotal", n(S["sections_total"]), "stats.json:sections_total", "count(filing_sections)")
641 1780 macro("chunks", n(S["chunks"][0]), "stats.json:chunks[0]", "count(filing_chunks)")
642 1781 macro("projectsWithLocation", n(S["projects_fields"][1]), "stats.json:projects_fields[1]", "count(canonical_location is not null)")
643 1782 macro("projectsTokenKeyedShare", f"{100*(P - S['projects_fields'][1])/P:.1f}", "stats.json:projects_fields", "100*(projects - with location)/projects")
644 1783 macro("projectsPerIssuerMean", f"{float(rows('projects_per_issuer')[0]['mean']):.1f}", "data/projects_per_issuer.csv", "mean")
645 1784 macro("projectsPerIssuerMedian", f"{ppi[2]:.0f}", "data/projects_per_issuer.csv", "q[2]")
1785 +macro("mentionsPerProject", f"{M/P:.2f}", "stats.json", "mentions/projects")
646 1786 macro("extractedAtFirst", S["extracted_at_range"][0][:19], "stats.json:extracted_at_range[0]", "min(extracted_at)")
647 1787 macro("extractedAtLast", S["extracted_at_range"][1][:19], "stats.json:extracted_at_range[1]", "max(extracted_at)")
648 1788 for key, mname in (("ledger_10k_mdna_median_words", "tenKmdnaMedianWords"), ("annual_panel_firms", "annualPanelFirms"), ("sp500_ciks", "spFiveHundredCiks"),
@@ -656,8 +1796,15 @@ if S.get("spid_runs"):
656 1796 if vv is not None: macro("run" + "".join(p.capitalize() for p in k.split("_")) + "".join(p.capitalize() for p in kk.split("_")), esc(vv), f"stats.json:spid_runs.{k}.{kk}", "export_stats.py")
657 1797 if di("brief_definition"): macro("brief", di("brief_definition"), "data/documented_inputs.json:brief_definition", "documented input (author to confirm)")
658 1798
659 −# ---- Figures ---------------------------------------------------------------------------------------------
660 −BLUE, GOLD, GREY = "#16365c", "#c9a227", "#8a8a8a"
1799 +# ---- Figures: one design system (Okabe-Ito, markers + line styles, vector PDF, width = textwidth) ------------------------------
1800 +OI = {"blue": "#0072B2", "orange": "#E69F00", "green": "#009E73", "verm": "#D55E00", "purple": "#CC79A7", "sky": "#56B4E9", "yellow": "#F0E442", "black": "#000000"}
1801 +GREY = "#8a8a8a"
1802 +TW = 6.5 # \textwidth in inches (letter, 1 in margins)
1803 +plt.rcParams.update({"font.family": "serif", "font.serif": ["Times New Roman", "Nimbus Roman", "TeX Gyre Termes", "DejaVu Serif"], "font.size": 9, "axes.labelsize": 9,
1804 + "axes.titlesize": 9, "legend.fontsize": 8, "xtick.labelsize": 8, "ytick.labelsize": 8, "pdf.fonttype": 42, "ps.fonttype": 42,
1805 + "axes.spines.top": False, "axes.spines.right": False, "axes.linewidth": 0.6, "lines.linewidth": 1.3, "lines.markersize": 4, "legend.frameon": False,
1806 + "savefig.bbox": "tight", "savefig.pad_inches": 0.02})
1807 +thousands = FuncFormatter(lambda v, _: f"{v:,.0f}")
661 1808
662 1809
663 1810 def save(fig, name):
@@ -665,46 +1812,167 @@ def save(fig, name):
665 1812 fig.savefig(F / f"{name}.pdf", metadata={"CreationDate": None})
666 1813 fig.savefig(F / f"{name}.png", dpi=int(DI["png_dpi"]["value"]))
667 1814 plt.close(fig)
1815 +
1816 +
1817 +# Figure 1: coverage by year
668 1818 yrs = [int(r["yr"]) for r in iy]
669 −fig, ax1 = plt.subplots(figsize=(7.2, 3.4))
670 −ax1.bar(yrs, [int(r["filings"]) for r in iy], color=BLUE, alpha=.85, label="Filings (10-K, 10-Q, 8-K)")
671 −ax1.set_ylabel("Filings per year"); ax1.set_xlabel("Filing year")
672 −ax1.xaxis.set_major_locator(MaxNLocator(integer=True))
673 −ax2 = ax1.twinx(); ax2.plot(yrs, [int(r["issuers"]) for r in iy], color=GOLD, marker="o", lw=2, label="Issuers with $\\geq$1 filing")
674 −ax2.set_ylabel("Issuers"); ax2.set_ylim(0, U["n"] * 1.05)
675 −h1, l1 = ax1.get_legend_handles_labels(); h2, l2 = ax2.get_legend_handles_labels(); ax1.legend(h1 + h2, l1 + l2, loc="upper left", frameon=False, fontsize=8)
676 −for a in (ax1, ax2): a.spines[["top"]].set_visible(False)
1819 +fig, ax1 = plt.subplots(figsize=(TW, 3.2))
1820 +fil = [int(r["filings"]) for r in iy]
1821 +bars = ax1.bar(yrs, fil, color=OI["blue"], alpha=.9, label="Filings (10-K, 10-Q, 8-K), left axis", width=0.75)
1822 +bars[-1].set_hatch("////"); bars[-1].set_edgecolor("white")
1823 +ax1.set_ylabel("Filings per year"); ax1.set_xlabel("Filing year"); ax1.yaxis.set_major_formatter(thousands)
1824 +ax1.xaxis.set_major_locator(MaxNLocator(integer=True)); ax1.set_xticks(yrs); ax1.tick_params(axis="x", labelrotation=90)
1825 +ax2 = ax1.twinx(); ax2.spines["right"].set_visible(True)
1826 +ax2.plot(yrs, [int(r["issuers"]) for r in iy], color=OI["verm"], marker="o", ls="-", label="Issuers with $\\geq$ 1 filing, right axis")
1827 +ax2.set_ylabel("Issuers"); ax2.set_ylim(0, U["n"] * 1.38); ax2.yaxis.set_major_formatter(thousands)
1828 +ax2.axhline(U["n"], color=GREY, lw=0.8, ls=":"); ax2.text(yrs[0] - 0.4, U["n"] * 0.985, f"universe = {U['n']:,}", fontsize=7, color=GREY, va="top")
1829 +h1, l1 = ax1.get_legend_handles_labels(); h2, l2 = ax2.get_legend_handles_labels(); ax1.legend(h1 + h2, l1 + l2, loc="upper left")
1830 +ax1.set_ylim(0, max(fil) * 1.38); ax1.text(yrs[-1], fil[-1] + max(fil) * 0.02, "partial", fontsize=7, ha="center", color=GREY)
677 1831 fig.tight_layout(); save(fig, "fig_coverage")
1832 +float_figure("fig_coverage.tex", "fig:coverage", f"Filings and issuers per year in the corpus, {y_first}--{y_last}. Bars: primary documents of Forms 10-K, 10-Q and 8-K by filing year "
1833 + f"(left axis; the hatched {y_last} bar covers January~1 to {fdr[1]}). Line: issuers with at least one filing in the year (right axis), against the "
1834 + f"{U['n']:,} issuers of the snapshot universe (dotted). Issuers that went public after {y_first} enter the panel at their first filing, so the number of observed "
1835 + "issuers rises mechanically under the snapshot design (Section~\\ref{sec:sample}); counts are exact, no sampling uncertainty applies.", "fig_coverage.pdf",
1836 + "data/issuers\\_by\\_year.csv, stats.json")
678 1837
679 −fig, ax = plt.subplots(figsize=(7.2, 5.2))
1838 +# Figure 3: projects by type (all vs excluding the financing class)
1839 +fig, ax = plt.subplots(figsize=(TW, 5.0))
680 1840 labs = [LAB[r["project_type"]].replace("\\&", "&") for r in pt][::-1]; vals = [int(r["n"]) for r in pt][::-1]
681 −ax.barh(labs, vals, color=BLUE); ax.set_xlabel("Resolved projects"); ax.spines[["top", "right"]].set_visible(False)
682 −for i, v in enumerate(vals): ax.text(v + max(vals) * 0.007, i, f"{v:,}", va="center", fontsize=7)
683 −ax.xaxis.set_major_locator(MaxNLocator(integer=True))
1841 +ypos = list(range(len(labs)))
1842 +if rx:
1843 + ex_vals = [int(rx[r["project_type"]]["n_excl_any"]) if r["project_type"] in rx else int(r["n"]) for r in pt][::-1]
1844 + ax.barh([y + 0.2 for y in ypos], vals, height=0.4, color=OI["blue"], label="All projects (current key)")
1845 + ax.barh([y - 0.2 for y in ypos], ex_vals, height=0.4, color=OI["orange"], hatch="////", edgecolor="white", label="Excluding projects with a financing-class mention")
1846 + for i, (v, e) in enumerate(zip(vals, ex_vals)): ax.text(v + max(vals) * 0.007, i + 0.2, f"{v:,}", va="center", fontsize=7); ax.text(e + max(vals) * 0.007, i - 0.2, f"{e:,}", va="center", fontsize=7, color="#555555")
1847 + ax.legend(loc="lower right")
1848 +else:
1849 + ax.barh(ypos, vals, color=OI["blue"])
1850 + for i, v in enumerate(vals): ax.text(v + max(vals) * 0.007, i, f"{v:,}", va="center", fontsize=7)
1851 +ax.set_yticks(ypos); ax.set_yticklabels(labs); ax.set_xlabel("Resolved projects (current key, confidence $\\geq$ 0.45)"); ax.xaxis.set_major_formatter(thousands)
1852 +ax.set_xlim(0, max(vals) * 1.12)
684 1853 fig.tight_layout(); save(fig, "fig_types")
1854 +float_figure("fig_types.tex", "fig:types", f"Resolved projects by taxonomy category ({P:,} projects under the current resolution key). "
1855 + + ("Hatched bars remove the projects with at least one mention matching the financing-instrument / buyback / dividend pattern of Table~\\ref{tab:fp_classes}; "
1856 + "the two bars bracket a construct violation detectable by pattern, not precision. " if rx else "")
1857 + + "Counts are exact database counts; the dependence of every count on the key is shown in Table~\\ref{tab:spec_curve}.", "fig_types.pdf",
1858 + "data/projects\\_by\\_type.csv, results/fp\\_classes/table5\\_restated\\_excl\\_financing.csv", width="0.95\\textwidth")
1859 +
1860 +# Figure 4: confidence by run
1861 +fig, ax = plt.subplots(figsize=(TW, 2.9))
1862 +xs = [float(r["conf"]) for r in cf]
1863 +if byrun:
1864 + octv = [byrun.get(x, {}).get("october", 0) for x in xs]; junv = [byrun.get(x, {}).get("backfilled_june", 0) for x in xs]
1865 + ax.bar(xs, octv, width=0.08, color=OI["blue"], label="October run")
1866 + ax.bar(xs, junv, width=0.08, bottom=octv, color=OI["orange"], hatch="////", edgecolor="white", label="June run (backfilled)")
1867 + ax.legend(loc="upper left")
1868 +else:
1869 + ax.bar(xs, [int(r["n"]) for r in cf], width=0.08, color=OI["blue"])
1870 +ax.set_xlabel("Self-reported extraction confidence (rounded to one decimal)"); ax.set_ylabel("Stored mentions"); ax.yaxis.set_major_formatter(thousands)
1871 +ax.set_xticks(xs); ax.set_ylim(0, None)
1872 +if cdef is not None:
1873 + ax.annotate(f"0.6 = post-processing default\nwhen the field is missing\n({cdef:,} mentions at exactly 0.600)", xy=(0.6, cfd.get(0.6, 0)), xytext=(0.62, max(cfd.values()) * 0.45),
1874 + fontsize=7, color="#444444", arrowprops={"arrowstyle": "-", "color": GREY, "lw": 0.6})
1875 +fig.tight_layout(); save(fig, "fig_confidence")
1876 +float_figure("fig_confidence.tex", "fig:confidence", f"Self-reported extraction confidence of the {M:,} stored mentions, by run (mentions below 0.45 are discarded before storage). "
1877 + "The value is the model's own JSON field, rounded to one decimal; a missing field is set to 0.6 by the post-processing code. The distribution describes a reporting "
1878 + "habit, not accuracy: calibration requires the human labels of gate (d). Counts are exact.", "fig_confidence.pdf",
1879 + "data/confidence\\_dist.csv, results/ledger/code\\_vs\\_data\\_checks.json", width="0.85\\textwidth")
685 1880
686 −fig, (ax, axb) = plt.subplots(2, 1, figsize=(7.2, 5.6), sharex=True, gridspec_kw={"height_ratios": [3, 2]})
687 −ax.plot(yrs, [int(my[str(y)]["mentions"]) for y in yrs], color=BLUE, marker="o", lw=2, label="Project mentions")
688 −ax.plot(yrs, [int(py[str(y)]["n"]) for y in yrs], color=GOLD, marker="s", lw=2, label="Projects first observed")
689 −ax.set_ylabel("Count"); ax.set_ylim(0, None); ax.legend(frameon=False, fontsize=8); ax.spines[["top", "right"]].set_visible(False)
690 −ax.axvspan(yrs[0] - 0.5, yrs[0] + 0.5, color=GREY, alpha=.15); ax.axvspan(yrs[-1] - 0.5, yrs[-1] + 0.5, color=GREY, alpha=.15)
691 −ax.text(yrs[0], ax.get_ylim()[1] * 0.97, "left-censored", fontsize=7, ha="center", va="top", color=GREY)
692 −ax.text(yrs[-1], ax.get_ylim()[1] * 0.97, "partial year", fontsize=7, ha="center", va="top", color=GREY)
693 −axb.plot(yrs, [int(my[str(y)]["mentions"]) / int(my[str(y)]["issuers"]) for y in yrs], color=BLUE, marker="o", lw=2, label="Mentions per issuer with $\\geq$1 mention")
694 −axb.plot(yrs, [int(py[str(y)]["n"]) / int(my[str(y)]["issuers"]) for y in yrs], color=GOLD, marker="s", lw=2, label="Projects first observed per issuer with $\\geq$1 mention")
695 −axb.set_xlabel("Filing year"); axb.set_ylabel("Per issuer"); axb.set_ylim(0, None); axb.legend(frameon=False, fontsize=8); axb.spines[["top", "right"]].set_visible(False)
696 −axb.xaxis.set_major_locator(MaxNLocator(integer=True))
1881 +# Figure 5: mentions and new projects by year, all issuers vs fixed cohort
1882 +fig, (ax, axb) = plt.subplots(2, 1, figsize=(TW, 5.6), sharex=True, gridspec_kw={"height_ratios": [3, 3]})
1883 +ax.plot(yrs, [int(my[str(y)]["mentions"]) for y in yrs], color=OI["blue"], marker="o", ls="-", label="Stored mentions")
1884 +ax.plot(yrs, [int(py[str(y)]["n"]) for y in yrs], color=OI["verm"], marker="s", ls="--", label="Projects first seen (current key)")
1885 +if TS:
1886 + ax.plot(yrs, [int(allr[str(y)]["first_seen_k3"]) for y in yrs], color=OI["green"], marker="^", ls=":", label="Episodes first seen (windowed key, $k = 3$)")
1887 +ax.set_ylabel("Count per filing year"); ax.set_ylim(0, None); ax.yaxis.set_major_formatter(thousands); ax.legend(loc="lower right", ncol=1)
1888 +for a in (ax, axb):
1889 + a.axvspan(yrs[0] - 0.5, yrs[0] + 0.5, color=GREY, alpha=.15, lw=0); a.axvspan(yrs[-1] - 0.5, yrs[-1] + 0.5, color=GREY, alpha=.15, lw=0)
1890 +ax.text(yrs[0], ax.get_ylim()[1] * 0.02, "left-\ncensored", fontsize=7, ha="center", va="bottom", color=GREY)
1891 +ax.text(yrs[-1], ax.get_ylim()[1] * 0.98, "partial\nyear", fontsize=7, ha="center", va="top", color=GREY)
1892 +axb.plot(yrs, [int(my[str(y)]["mentions"]) / int(iy[i]["issuers"]) for i, y in enumerate(yrs)], color=OI["blue"], marker="o", ls="-", label="Mentions per issuer filing, all issuers")
1893 +axb.plot(yrs, [int(py[str(y)]["n"]) / int(iy[i]["issuers"]) for i, y in enumerate(yrs)], color=OI["verm"], marker="s", ls="--", label="Projects first seen per issuer filing, all issuers")
1894 +if TS:
1895 + axb.plot(yrs, [float(coh[str(y)]["mentions_per_issuer_filing"]) for y in yrs], color=OI["blue"], marker="o", mfc="white", ls="-.", label=f"Mentions per issuer, fixed cohort ({tss.get('cohort_issuers', 0):,} issuers)")
1896 + axb.plot(yrs, [float(coh[str(y)]["first_seen_per_issuer"]) for y in yrs], color=OI["verm"], marker="s", mfc="white", ls=":", label="Projects first seen per issuer, fixed cohort")
1897 +axb.set_xlabel("Filing year"); axb.set_ylabel("Per issuer filing in the year"); axb.set_ylim(0, axb.get_ylim()[1] * 1.55); axb.legend(loc="upper center", ncol=2)
1898 +axb.xaxis.set_major_locator(MaxNLocator(integer=True)); axb.set_xticks(yrs); axb.tick_params(axis="x", labelrotation=90)
697 1899 fig.tight_layout(); save(fig, "fig_mentions_year")
698 −macro("newProjectsPerIssuerFirstYear", f"{int(py[str(y_first)]['n'])/int(my[str(y_first)]['issuers']):.1f}", "data/projects_by_first_seen_year.csv, mentions_by_year.csv", "first seen / issuers with mentions")
699 −macro("newProjectsPerIssuerLastFullYear", f"{int(py[str(inner[-1])]['n'])/int(my[str(inner[-1])]['issuers']):.1f}", "data/projects_by_first_seen_year.csv, mentions_by_year.csv", "first seen / issuers with mentions")
1900 +float_figure("fig_mentions_year.tex", "fig:mentions_year", "Mentions and projects first seen by filing year. Top: stored mentions, projects first seen under the current key and "
1901 + "episodes first seen under a windowed key that splits a project when consecutive mentions are more than three years apart. Bottom: the same quantities per issuer "
1902 + f"filing in the year, for all issuers (filled markers) and for the fixed cohort of issuers filing in every year {inner[0]}--{inner[-1]} (open markers), which holds "
1903 + f"the panel composition constant. {y_first} is left-censored and {y_last} is partial (shaded); both axes start at zero. The flat mentions-per-issuer series "
1904 + "and the falling new-projects-per-issuer series of the cohort are consistent with a time-invariant key attaching later mentions to existing projects; the "
1905 + "figure does not identify disclosure behaviour. Counts are exact.", "fig_mentions_year.pdf",
1906 + "data/mentions\\_by\\_year.csv, projects\\_by\\_first\\_seen\\_year.csv, issuers\\_by\\_year.csv, results/timeseries/first\\_seen\\_fixed\\_cohort.csv")
700 1907
701 −fig, ax = plt.subplots(figsize=(7.2, 3.0))
702 −ax.bar([float(r["conf"]) for r in cf], [int(r["n"]) for r in cf], width=0.08, color=BLUE)
703 −ax.set_xlabel("Self-reported extraction confidence"); ax.set_ylabel("Mentions"); ax.spines[["top", "right"]].set_visible(False)
704 −fig.tight_layout(); save(fig, "fig_confidence")
1908 +# Figure: grounding by field and form with bootstrap CIs
1909 +if gg.exists():
1910 + fields = ["years", "partners", "amount_number", "amount_with_currency", "locations", "technologies"]
1911 + forms_ = ["10-K", "10-Q", "8-K"]; mk = {"10-K": "o", "10-Q": "s", "8-K": "^"}; col = {"10-K": OI["blue"], "10-Q": OI["green"], "8-K": OI["verm"]}
1912 + fig, ax = plt.subplots(figsize=(TW, 3.4))
1913 + for j, fm in enumerate(forms_):
1914 + xs_, ys_, lo_, hi_ = [], [], [], []
1915 + for i, f in enumerate(fields):
1916 + r = gget("form", f, fm)
1917 + if not r: continue
1918 + xs_.append(100 * float(r["grounded_share"])); ys_.append(i + (j - 1) * 0.22); lo_.append(100 * (float(r["grounded_share"]) - float(r["ci_low"]))); hi_.append(100 * (float(r["ci_high"]) - float(r["grounded_share"])))
1919 + ax.errorbar(xs_, ys_, xerr=[lo_, hi_], fmt=mk[fm], color=col[fm], ecolor=col[fm], capsize=2, elinewidth=0.8, label=fm, ls="none")
1920 + allv = [100 * float(gget("all", f, "all")["grounded_share"]) for f in fields]
1921 + ax.scatter(allv, range(len(fields)), marker="|", s=12e1, color="black", label="All forms", zorder=3)
1922 + ax.set_yticks(range(len(fields))); ax.set_yticklabels([FIELD[f].replace("Amount (number + currency token within 40 chars)", "Amount (number + currency)") for f in fields])
1923 + ax.invert_yaxis(); ax.set_xlabel("Mentions whose field is found literally in the stored section text (%)"); ax.set_xlim(50, 100 + 1); ax.axvline(100, color=GREY, lw=0.5, ls=":")
1924 + ax.legend(loc="upper left", ncol=1); ax.grid(axis="x", color="#dddddd", lw=0.5)
1925 + fig.tight_layout(); save(fig, "fig_grounding")
1926 + float_figure("fig_grounding.tex", "fig:grounding", f"Mechanical grounding of the structured fields of all {M:,} stored mentions, by field and form. Markers: share of mentions "
1927 + "whose field (every listed element, or the amount under its usual renderings) occurs literally in the stored section text; horizontal bars: 95\\% percentile-bootstrap "
1928 + "intervals with 1{,}000 replicates clustered by section (narrower than the marker for most fields); black ticks: all forms pooled. The axis is truncated at 50\\% "
1929 + "(no value lies below it). Grounding is a necessary condition for correctness, not a measure of precision (Table~\\ref{tab:grounding}).", "fig_grounding.pdf",
1930 + "results/grounding/grounding\\_by\\_group.csv")
1931 +
1932 +# Figure: specification curve
1933 +if sc_path.exists():
1934 + fig, ax = plt.subplots(figsize=(TW, 3.4))
1935 + order_ = sorted(order, key=lambda k: int(float(next(r["projects"] for r in sc if r["key"] == k and float(r["threshold"]) == t0_))))
1936 + cmap = matplotlib.colormaps["viridis"]; mks = ["o", "s", "^", "D", "v"]
1937 + for i, t in enumerate(thrs):
1938 + ys_ = [int(float(next(r["projects"] for r in sc if r["key"] == k and float(r["threshold"]) == t))) for k in order_]
1939 + ax.plot(range(len(order_)), ys_, marker=mks[i % len(mks)], ls=["-", "--", "-.", ":", "-"][i % 5], color=cmap(0.1 + 0.8 * i / max(1, len(thrs) - 1)), label=f"confidence $\\geq$ {t}")
1940 + ax.axhline(P, color=GREY, lw=0.6, ls=":"); ax.text(0, P * 1.03, f"released count = {P:,}", fontsize=7, color=GREY)
1941 + short = {"k_cik_type": "issuer × type", "k_type_dropped": "type dropped", "k_name_only": "name token only", "k_current": "current key", "k_city_normalised": "city-normalised",
1942 + "k_current_stopwords": "extended stop-words", "k_two_tokens": "two name tokens", "k_strict": "strict (name + location)", "k_mention_level": "no resolution"}
1943 + ax.set_xticks(range(len(order_))); ax.set_xticklabels([short.get(k, k) for k in order_], rotation=30, ha="right")
1944 + ax.set_ylabel("Projects"); ax.yaxis.set_major_formatter(thousands); ax.set_ylim(0, None); ax.legend(loc="upper left")
1945 + fig.tight_layout(); save(fig, "fig_spec_curve")
1946 + float_figure("fig_spec_curve.tex", "fig:spec_curve", f"Specification curve of the project count. Each line applies one confidence threshold to the {M:,} stored mentions and "
1947 + "resolves them under nine keys ordered by the count they produce at the release threshold; the released table corresponds to the current key at 0.45 (dotted "
1948 + "line). The count spans an order of magnitude across keys and moves little with the threshold below 0.9, so it is a property of the resolution rule rather than "
1949 + "a count of initiatives (Table~\\ref{tab:spec_curve}). Counts are exact.", "fig_spec_curve.pdf", "results/resolver/spec\\_curve.csv")
1950 +
1951 +# Figure: focus-window coverage by item (P10-median-P90 of the share shown)
1952 +if fcp.exists():
1953 + FR = [r for r in rows(fcp.stem, fcp.parent) if int(r["n"]) >= 1e3]
1954 + FR.sort(key=lambda r: (["10-K", "10-Q", "8-K"].index(r["form"]), float(r["shown_p50"])))
1955 + fig, ax = plt.subplots(figsize=(TW, 3.6))
1956 + col = {"10-K": OI["blue"], "10-Q": OI["green"], "8-K": OI["verm"]}; mk = {"10-K": "o", "10-Q": "s", "8-K": "^"}
1957 + for i, r in enumerate(FR):
1958 + p10, p50, p90 = 100 * float(r["shown_p10"]), 100 * float(r["shown_p50"]), 100 * float(r["shown_p90"])
1959 + ax.plot([p10, p90], [i, i], color=col[r["form"]], lw=2, alpha=0.5, solid_capstyle="butt")
1960 + ax.plot([p50], [i], marker=mk[r["form"]], color=col[r["form"]], ls="none")
1961 + ax.text(100 + 1, i, f"{float(r['pct_mentions_from_lt25']):.0f}%", fontsize=7, va="center", color="#444444")
1962 + ax.text(100 + 1, -1.1, "mentions from\nrows shown < 25%", fontsize=7, va="center", color="#444444")
1963 + ax.set_yticks(range(len(FR))); ax.set_yticklabels([f"{r['form']} {r['item'].replace('_', ' ')}" for r in FR]); ax.invert_yaxis()
1964 + ax.set_xlabel("Share of the section's characters shown to the model (%): P10–median–P90 over ledgered rows"); ax.set_xlim(0, 100 + 12); ax.set_xticks([0, 25, 50, 75, 100])
1965 + ax.axvline(25, color=GREY, lw=0.6, ls=":")
1966 + from matplotlib.lines import Line2D
1967 + ax.legend([Line2D([], [], marker=mk[f], color=col[f], ls="none") for f in col], list(col), loc="lower left", title=None)
1968 + fig.tight_layout(); save(fig, "fig_focus")
1969 + float_figure("fig_focus.tex", "fig:focus", "Focus-window coverage by form and item: the fraction of each ledgered section's text that reached the model. Bars span the 10th to "
1970 + "90th percentile over the item's ledgered rows and markers show the median (items with at least 1{,}000 rows); the right-hand labels give the share of the item's "
1971 + "ledger mentions that come from sections of which less than a quarter was shown. Coverage of the text is not recall: what the model missed inside the shown "
1972 + "windows is unmeasured (Table~\\ref{tab:focus}).", "fig_focus.pdf", "results/focus/focus\\_coverage\\_by\\_form\\_item.csv")
705 1973 print("figures ok")
706 1974
707 −# ---- inline-number macros ---------------------------------------------------------------------------------
1975 +# ---- inline-number macros -----------------------------------------------------------------------------------------------------------
708 1976 lines = ["% Generated by code/make_tables.py — inline numbers of the paper. Do not edit; use \\SPID<name> in the text.",
709 1977 "% Source and formula of every macro: results/inline_numbers.json"]
710 1978 for k, v in INLINE.items():
modified data/datamodel_audit.csv +1 −1
@@ -3,7 +3,7 @@ universe_snapshots,"\texttt{data/metadata/universe.json} + \texttt{companies} (C
3 3 issuers,\texttt{companies} (one row per CIK; former names from SEC header stored in metadata JSON only),"Partial: no name history, no parent/subsidiary links"
4 4 filings,"\texttt{filings} (accession PK, CIK FK, form, filing/report dates, SEC URL, local path, size, download and parse status)","Implemented; no acceptance timestamp, no checksum"
5 5 sections,"\texttt{filing\_sections} (UUID PK, accession FK, name, item, order, text, counts)",Implemented; no character offsets into raw HTML
6 −project_mentions,"\texttt{project\_mentions} (SHA-1 id, accession, CIK, section id, name, type, description, objective, amount, raw amount, lists, years, status, confidence, backend, issuer context)","Implemented; no evidence span, no prompt hash, no five-way label"
6 +project_mentions,"\texttt{project\_mentions} (SHA-1 id, accession, CIK, section id, name, type, description, objective, amount, formatted amount string (\texttt{amount\_raw}, not the filing's string), lists, years, status, confidence, backend, issuer context)","Implemented; no evidence span, no prompt hash, no five-way label"
7 7 projects,"\texttt{projects} (MD5 of CIK$|$type$|$location-or-name, representative fields, max amount, counts, first/last seen and cited years)",Implemented (deterministic key)
8 8 project_mention_links,implicit in the key (every mention maps to exactly one project),"Proposed: explicit table with score, resolver version, adjudication"
9 9 project_events,"\texttt{project\_timeline} (one row per mention: date, form, status, amount, confidence, snippet)","Partial: mention rows, not typed events"
modified data/documented_inputs.json +95 −0
@@ -24,5 +24,100 @@
24 24 "value": 200,
25 25 "source": "raster resolution of the PNG copies used by code/tex2docx",
26 26 "status": "convention"
27 + },
28 + "acq_new_docs": {
29 + "value": "about 400{,}000",
30 + "source": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible",
31 + "status": "author-reported"
32 + },
33 + "acq_hours": {
34 + "value": "seven",
35 + "source": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible",
36 + "status": "author-reported"
37 + },
38 + "acq_req_per_sec": {
39 + "value": "17",
40 + "source": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible",
41 + "status": "author-reported"
42 + },
43 + "acq_nodes": {
44 + "value": "ten",
45 + "source": "docs/research_log.md 2026-10-27 (10 MacLustr nodes + 1 external gateway)",
46 + "status": "author-reported"
47 + },
48 + "acq_node_rate": {
49 + "value": "0.9",
50 + "source": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible (requests per second per node)",
51 + "status": "author-reported"
52 + },
53 + "acq_gateway_rate": {
54 + "value": "one",
55 + "source": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible (requests per second per shard on the gateway)",
56 + "status": "author-reported"
57 + },
58 + "parse_filings_per_sec": {
59 + "value": "100",
60 + "source": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible",
61 + "status": "author-reported"
62 + },
63 + "parse_minutes_range": {
64 + "value": "five to thirteen",
65 + "source": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible",
66 + "status": "author-reported"
67 + },
68 + "embed_minutes_range": {
69 + "value": "15--40",
70 + "source": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible",
71 + "status": "author-reported"
72 + },
73 + "merge_minutes": {
74 + "value": "seven",
75 + "source": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible",
76 + "status": "author-reported"
77 + },
78 + "total_cost_usd": {
79 + "value": "775",
80 + "source": "author-reported total of the October 2026 extraction (docs/research_log.md); the API invoice is not archived",
81 + "status": "author-reported"
82 + },
83 + "stability_sections": {
84 + "value": "500",
85 + "source": "X1 protocol of peer_reviews/FIRC-0001/consolidated_review.md §6 item 11 (500 sections x 3 re-submissions); not executed (AR-LLM-1 not granted)",
86 + "status": "protocol constant"
87 + },
88 + "stability_calls": {
89 + "value": "about 2{,}500",
90 + "source": "consolidated_review.md §6 item 11 (cost estimate of the X1/X2 protocol); not executed",
91 + "status": "protocol constant"
92 + },
93 + "annotation_frame_mb": {
94 + "value": "77",
95 + "source": "size of the full-text frames kept on the node (M3U96b:~/firc0001_review/frames/, N11 implemented_changes.md); not shipped",
96 + "status": "node artefact"
97 + },
98 + "embedding_dim": {
99 + "value": "384",
100 + "source": "all-MiniLM-L6-v2 embedding dimension (scripts/build_embeddings.py default model)",
101 + "status": "model constant"
102 + },
103 + "factor_anchors": {
104 + "value": "8",
105 + "source": "src/factors/anchors.py registry (thematic anchors), as described in docs/research_log.md",
106 + "status": "code constant"
107 + },
108 + "tenk_sections_max": {
109 + "value": "fourteen",
110 + "source": "src/parsing/section_extractor.py FORM_10K_SECTIONS (Items 1 to 9B)",
111 + "status": "code constant"
112 + },
113 + "tenq_sections_n": {
114 + "value": "seven",
115 + "source": "src/parsing/section_extractor.py FORM_10Q_SECTIONS",
116 + "status": "code constant"
117 + },
118 + "corpus_parquet_gb": {
119 + "value": "29.1",
120 + "source": "N0 schema probe (results/n0_probe, commit 7680606): parquet corpus 1,342,283 sections / 29.1 GB on the master node",
121 + "status": "node measurement"
27 122 }
28 123 }
\ No newline at end of file
modified paper/figures/fig_confidence.pdf +0 −0

Binary file not shown.

modified paper/figures/fig_confidence.png +0 −0

Binary file not shown.

added paper/figures/fig_confidence.tex +6 −0
@@ -0,0 +1,6 @@
1 +% Generated by code/make_tables.py from data/confidence\_dist.csv, results/ledger/code\_vs\_data\_checks.json. Do not edit by hand.
2 +\begin{figure}[H]
3 +\centering
4 +\includegraphics[width=0.85\textwidth]{figures/fig_confidence.pdf}
5 +\caption{Self-reported extraction confidence of the 308,065 stored mentions, by run (mentions below 0.45 are discarded before storage). The value is the model's own JSON field, rounded to one decimal; a missing field is set to 0.6 by the post-processing code. The distribution describes a reporting habit, not accuracy: calibration requires the human labels of gate (d). Counts are exact.}\label{fig:confidence}
6 +\end{figure}
modified paper/figures/fig_coverage.pdf +0 −0

Binary file not shown.

modified paper/figures/fig_coverage.png +0 −0

Binary file not shown.

added paper/figures/fig_coverage.tex +6 −0
@@ -0,0 +1,6 @@
1 +% Generated by code/make_tables.py from data/issuers\_by\_year.csv, stats.json. Do not edit by hand.
2 +\begin{figure}[H]
3 +\centering
4 +\includegraphics[width=\textwidth]{figures/fig_coverage.pdf}
5 +\caption{Filings and issuers per year in the corpus, 2010--2026. Bars: primary documents of Forms 10-K, 10-Q and 8-K by filing year (left axis; the hatched 2026 bar covers January~1 to 2026-10-27). Line: issuers with at least one filing in the year (right axis), against the 2,564 issuers of the snapshot universe (dotted). Issuers that went public after 2010 enter the panel at their first filing, so the number of observed issuers rises mechanically under the snapshot design (Section~\ref{sec:sample}); counts are exact, no sampling uncertainty applies.}\label{fig:coverage}
6 +\end{figure}
added paper/figures/fig_focus.pdf +0 −0

Binary file not shown.

added paper/figures/fig_focus.png +0 −0

Binary file not shown.

added paper/figures/fig_focus.tex +6 −0
@@ -0,0 +1,6 @@
1 +% Generated by code/make_tables.py from results/focus/focus\_coverage\_by\_form\_item.csv. Do not edit by hand.
2 +\begin{figure}[H]
3 +\centering
4 +\includegraphics[width=\textwidth]{figures/fig_focus.pdf}
5 +\caption{Focus-window coverage by form and item: the fraction of each ledgered section's text that reached the model. Bars span the 10th to 90th percentile over the item's ledgered rows and markers show the median (items with at least 1{,}000 rows); the right-hand labels give the share of the item's ledger mentions that come from sections of which less than a quarter was shown. Coverage of the text is not recall: what the model missed inside the shown windows is unmeasured (Table~\ref{tab:focus}).}\label{fig:focus}
6 +\end{figure}
added paper/figures/fig_grounding.pdf +0 −0

Binary file not shown.

added paper/figures/fig_grounding.png +0 −0

Binary file not shown.

added paper/figures/fig_grounding.tex +6 −0
@@ -0,0 +1,6 @@
1 +% Generated by code/make_tables.py from results/grounding/grounding\_by\_group.csv. Do not edit by hand.
2 +\begin{figure}[H]
3 +\centering
4 +\includegraphics[width=\textwidth]{figures/fig_grounding.pdf}
5 +\caption{Mechanical grounding of the structured fields of all 308,065 stored mentions, by field and form. Markers: share of mentions whose field (every listed element, or the amount under its usual renderings) occurs literally in the stored section text; horizontal bars: 95\% percentile-bootstrap intervals with 1{,}000 replicates clustered by section (narrower than the marker for most fields); black ticks: all forms pooled. The axis is truncated at 50\% (no value lies below it). Grounding is a necessary condition for correctness, not a measure of precision (Table~\ref{tab:grounding}).}\label{fig:grounding}
6 +\end{figure}
modified paper/figures/fig_mentions_year.pdf +0 −0

Binary file not shown.

modified paper/figures/fig_mentions_year.png +0 −0

Binary file not shown.

added paper/figures/fig_mentions_year.tex +6 −0
@@ -0,0 +1,6 @@
1 +% Generated by code/make_tables.py from data/mentions\_by\_year.csv, projects\_by\_first\_seen\_year.csv, issuers\_by\_year.csv, results/timeseries/first\_seen\_fixed\_cohort.csv. Do not edit by hand.
2 +\begin{figure}[H]
3 +\centering
4 +\includegraphics[width=\textwidth]{figures/fig_mentions_year.pdf}
5 +\caption{Mentions and projects first seen by filing year. Top: stored mentions, projects first seen under the current key and episodes first seen under a windowed key that splits a project when consecutive mentions are more than three years apart. Bottom: the same quantities per issuer filing in the year, for all issuers (filled markers) and for the fixed cohort of issuers filing in every year 2011--2025 (open markers), which holds the panel composition constant. 2010 is left-censored and 2026 is partial (shaded); both axes start at zero. The flat mentions-per-issuer series and the falling new-projects-per-issuer series of the cohort are consistent with a time-invariant key attaching later mentions to existing projects; the figure does not identify disclosure behaviour. Counts are exact.}\label{fig:mentions_year}
6 +\end{figure}
added paper/figures/fig_spec_curve.pdf +0 −0

Binary file not shown.

added paper/figures/fig_spec_curve.png +0 −0

Binary file not shown.

added paper/figures/fig_spec_curve.tex +6 −0
@@ -0,0 +1,6 @@
1 +% Generated by code/make_tables.py from results/resolver/spec\_curve.csv. Do not edit by hand.
2 +\begin{figure}[H]
3 +\centering
4 +\includegraphics[width=\textwidth]{figures/fig_spec_curve.pdf}
5 +\caption{Specification curve of the project count. Each line applies one confidence threshold to the 308,065 stored mentions and resolves them under nine keys ordered by the count they produce at the release threshold; the released table corresponds to the current key at 0.45 (dotted line). The count spans an order of magnitude across keys and moves little with the threshold below 0.9, so it is a property of the resolution rule rather than a count of initiatives (Table~\ref{tab:spec_curve}). Counts are exact.}\label{fig:spec_curve}
6 +\end{figure}
modified paper/figures/fig_types.pdf +0 −0

Binary file not shown.

modified paper/figures/fig_types.png +0 −0

Binary file not shown.

added paper/figures/fig_types.tex +6 −0
@@ -0,0 +1,6 @@
1 +% Generated by code/make_tables.py from data/projects\_by\_type.csv, results/fp\_classes/table5\_restated\_excl\_financing.csv. Do not edit by hand.
2 +\begin{figure}[H]
3 +\centering
4 +\includegraphics[width=0.95\textwidth]{figures/fig_types.pdf}
5 +\caption{Resolved projects by taxonomy category (121,099 projects under the current resolution key). Hatched bars remove the projects with at least one mention matching the financing-instrument / buyback / dividend pattern of Table~\ref{tab:fp_classes}; the two bars bracket a construct violation detectable by pattern, not precision. Counts are exact database counts; the dependence of every count on the key is shown in Table~\ref{tab:spec_curve}.}\label{fig:types}
6 +\end{figure}
modified paper/main.tex +0 −2
@@ -93,7 +93,6 @@
93 93 \usetikzlibrary{positioning,arrows.meta,shapes.misc}
94 94 \usepackage{pdflscape}
95 95 \usepackage{adjustbox}
96 −\usepackage{makecell} % multi-line column headers of the generated tables (code/make_tables.py)
97 96 \usepackage{upquote} % straight quotes in verbatim (extraction contract, gate regex)
98 97 \usepackage{listings} % \lstinputlisting (breaklines) of the inter-revision patches (Appendix, results/runs/*.patch)
99 98 \lstset{basicstyle=\ttfamily\scriptsize, breaklines=true, breakatwhitespace=false, columns=fullflexible, keepspaces=true, frame=none, xleftmargin=0pt}
@@ -102,7 +101,6 @@
102 101 \newcommand{\widenotesitem}{\par}
103 102 \newenvironment{widenotes}{\par\vspace{3pt}\begin{minipage}{\textwidth}\footnotesize\setlength{\parindent}{0pt}\let\item\widenotesitem}{\end{minipage}}
104 103 \input{tables/numbers} % generated inline-number macros (code/make_tables.py); never edit by hand
105 −\input{sections/numbers_pending} % PROVISIONAL \providecommand macros for Stage D audit numbers not yet emitted by the generator (Agent 10); each line names its results/ source
106 104
107 105 % ============================================================================
108 106 % METADATA — Edit these fields for each working paper
deleted paper/sections/numbers_pending.tex +0 −465
@@ -1,465 +0,0 @@
1 −% ----------------------------------------------------------------------------
2 −% PROVISIONAL inline-number macros for the Stage E prose (Agent 10, 2026-11-05).
3 −% Every value below is copied from a Stage D audit output under results/ (file and
4 −% field given on each line) and is defined with \providecommand so that the
5 −% generated definition in tables/numbers.tex (code/make_tables.py, Agent 9) wins
6 −% as soon as it exists. The same list, with value/source/formula, is filed for the
7 −% generator in improvements/FIRC-0001/macro_requests_writing.json. Delete this
8 −% file once make_tables.py emits every macro (check: grep providecommand).
9 −% ----------------------------------------------------------------------------
10 −
11 −% ---- ledger, calls, outage (results/ledger/*.json, gate_pass_by_run.csv) ----
12 −\providecommand{\SPIDoutageRowsRemoved}{149{,}352} % log_summary.json:october.outage_rows_reconciliation.difference
13 −\providecommand{\SPIDoutageLargestGapStart}{01:25} % throughput.json:largest_gaps_seconds[-1] (2026-10-28)
14 −\providecommand{\SPIDoutageLargestGapEnd}{06:40} % throughput.json:largest_gaps_seconds[-1]
15 −\providecommand{\SPIDoutageZeroBatchRange}{47--60} % log_summary.json:october.anomalous_batches (batch ids with 0 mentions)
16 −\providecommand{\SPIDoutageZeroBatchWindow}{01:44--06:05} % log_summary.json:october.anomalous_batches (first/last timestamp)
17 −\providecommand{\SPIDoutageSurvivingRows}{504} % backfill_block.json:rows_in_outage_window[0]
18 −\providecommand{\SPIDoutageSurvivingMentions}{1{,}011} % backfill_block.json:rows_in_outage_window[1]
19 −\providecommand{\SPIDresumeBatchSections}{5{,}198} % log_summary.json:october.resume_batch1.log_sections
20 −\providecommand{\SPIDresumeBatchCiks}{20} % log_summary.json:october.resume_batch1.ciks (length)
21 −\providecommand{\SPIDresumeBatchCalls}{2{,}686} % log_summary.json:october.resume_batch1.ledger_calls
22 −\providecommand{\SPIDresumeBatchProductive}{23} % log_summary.json:october.resume_batch1.ledger_with_mentions
23 −\providecommand{\SPIDresumeBatchExpectedProductive}{536} % resume_batch1_vs_expected.csv: sum(expected_with_mentions) = 536.2
24 −\providecommand{\SPIDresumeBatchMentions}{34} % log_summary.json:october.resume_batch1.log_mentions
25 −\providecommand{\SPIDresumeBatchWindow}{06:38--06:40} % log_summary.json:october.resume_batch1.window (2026-10-28)
26 −\providecommand{\SPIDresumeBatchZeroSharePct}{99.2} % flush_zero_groups_after_0622.csv (06:40 minute bin, 99.15)
27 −\providecommand{\SPIDjuneCalls}{95{,}286} % gate_pass_by_run.csv:backfilled_june.calls
28 −\providecommand{\SPIDjuneProductiveShareCalls}{25.6} % gate_pass_by_run.csv:backfilled_june.productive_pct_calls
29 −\providecommand{\SPIDoctoberProductiveShareCalls}{23.6} % gate_pass_by_run.csv:october.productive_pct_calls
30 −\providecommand{\SPIDlogExtractionCompleteSum}{1{,}117{,}479} % log_summary.json:october.extraction_complete_sum_sections
31 −\providecommand{\SPIDlogPendingSecondStart}{968{,}127} % log_summary.json:october.pending_lines[1]
32 −\providecommand{\SPIDconfExactDefault}{3{,}278} % code_vs_data_checks.json:confidence_exact_0600_total
33 −\providecommand{\SPIDconfExactDefaultJune}{304} % code_vs_data_checks.json:confidence_exact_0600_by_run
34 −\providecommand{\SPIDconfExactDefaultOctober}{2{,}974} % code_vs_data_checks.json:confidence_exact_0600_by_run
35 −\providecommand{\SPIDamountRawDeviations}{584} % code_vs_data_checks.json:amount_raw_rule_mismatch
36 −\providecommand{\SPIDamountNegative}{24} % results/grounding/amount_tail.json:lt_0
37 −\providecommand{\SPIDamountZero}{584} % results/grounding/amount_tail.json:eq_0
38 −\providecommand{\SPIDledgerBackendValue}{llm} % code_vs_data_checks.json:distinct_backend_ledger
39 −
40 −% ---- grounding (results/grounding/grounding_by_group.csv, grounding_all_structured.csv, grounding_element_level.csv, fallback_bounds.json, amount_tail.json) ----
41 −\providecommand{\SPIDgroundBootstrapReps}{1{,}000} % a02_grounding.py (bootstrap replicates, clustered by section)
42 −\providecommand{\SPIDgroundYearsPct}{99.8} % grounding_by_group.csv all/years 0.9976
43 −\providecommand{\SPIDgroundYearsCiLow}{99.7} % ci_low 0.9974
44 −\providecommand{\SPIDgroundYearsCiHigh}{99.8} % ci_high 0.9978
45 −\providecommand{\SPIDgroundPartnersPct}{99.4} % all/partners 0.9940
46 −\providecommand{\SPIDgroundAmountNumberPct}{93.7} % all/amount_number 0.9372
47 −\providecommand{\SPIDgroundAmountCurrencyPct}{80.5} % all/amount_with_currency 0.8047
48 −\providecommand{\SPIDgroundLocationsPct}{78.3} % all/locations 0.7832
49 −\providecommand{\SPIDgroundLocationsTenK}{85.7} % form/locations/10-K 0.8571
50 −\providecommand{\SPIDgroundLocationsTenQ}{82.1} % form/locations/10-Q 0.8207
51 −\providecommand{\SPIDgroundLocationsEightK}{67.8} % form/locations/8-K 0.6780
52 −\providecommand{\SPIDgroundTechPct}{63.6} % all/technologies 0.6358
53 −\providecommand{\SPIDgroundElemYears}{99.7} % grounding_element_level.csv years
54 −\providecommand{\SPIDgroundElemPartners}{99.6} % partners
55 −\providecommand{\SPIDgroundElemLocations}{84.2} % locations
56 −\providecommand{\SPIDgroundElemTech}{70.6} % technologies
57 −\providecommand{\SPIDgroundAllPct}{88.2} % grounding_all_structured.csv all 88.17
58 −\providecommand{\SPIDgroundAllN}{276{,}168} % grounding_all_structured.csv all n_with_fields
59 −\providecommand{\SPIDgroundAllTenK}{92.2} % 10-K 92.15
60 −\providecommand{\SPIDgroundAllTenQ}{92.4} % 10-Q 92.41
61 −\providecommand{\SPIDgroundAllEightK}{76.6} % 8-K 76.57
62 −\providecommand{\SPIDgroundAllJune}{84.5} % backfilled_june 84.51
63 −\providecommand{\SPIDgroundAllOctober}{88.7} % october 88.74
64 −\providecommand{\SPIDgroundAllTopBin}{86.4} % 0.9-1.0 bin 86.40
65 −\providecommand{\SPIDgroundAllLowerBinsRange}{90.7--94.2} % bins 0.45-0.6 ... 0.8-0.9
66 −\providecommand{\SPIDyearsNonEmptyN}{252{,}469} % fallback_bounds.json:years_nonempty
67 −\providecommand{\SPIDyearsRegexEqualN}{98{,}438} % fallback_bounds.json:years_eq_regex_desc
68 −\providecommand{\SPIDyearsRegexEqualPct}{39} % 98,438 / 252,469
69 −\providecommand{\SPIDtechNonEmptyN}{36{,}740} % fallback_bounds.json:techs_nonempty
70 −\providecommand{\SPIDtechRegexEqualN}{16{,}949} % fallback_bounds.json:techs_eq_regex_desc
71 −\providecommand{\SPIDtechRegexEqualPct}{46} % 16,949 / 36,740
72 −\providecommand{\SPIDyearsAbsentFromText}{604} % fallback_bounds.json:years_not_subset_of_text
73 −\providecommand{\SPIDtypeSignalMaPct}{79.8} % fallback_bounds.json:type_signal_in_name_desc_by_type ma_integration
74 −\providecommand{\SPIDtypeSignalTechDeployPct}{5.4} % technology_deployment 5.35
75 −\providecommand{\SPIDtechDeployMentionedN}{124} % fallback_bounds.json:tech_deploy_total[1]
76 −\providecommand{\SPIDtechDeployMentionedNoSignal}{90} % fallback_bounds.json:tech_deploy_mentioned_no_any_signal
77 −\providecommand{\SPIDamountMaxSci}{1.0 \times 10^{12}} % amount_tail.json:max_amount (math mode)
78 −\providecommand{\SPIDamountGeFiftyBMentions}{161} % amount_tail.json:ge_50e9
79 −\providecommand{\SPIDamountGeFiftyBProjects}{104} % amount_tail.json:projects_max_amount_ge_50e9
80 −\providecommand{\SPIDamountTopNumberFound}{191} % amount_tail.json:top200_grounded_number[0]
81 −\providecommand{\SPIDamountTopCurrencyFound}{178} % amount_tail.json:top200_grounded_number[1]
82 −\providecommand{\SPIDamountTopN}{200} % amount_tail.json:top200_grounded_number[2]
83 −\providecommand{\SPIDamountNonUsdTokenN}{1{,}837} % amount_tail.json:nonusd_within_40_share[0]
84 −\providecommand{\SPIDamountLocatedN}{112{,}692} % amount_tail.json:nonusd_within_40_share[1]
85 −\providecommand{\SPIDamountNonUsdTokenPct}{1.6} % 1,837 / 112,692
86 −
87 −% ---- resolver (results/resolver/composition.json, spec_curve.csv, top_name_tokens.csv, overmerge_by_type.csv, ties_idempotence.json, june_october_reconciliation.json) ----
88 −\providecommand{\SPIDmentionsKeyedLocation}{118{,}783} % composition.json:mentions_by_key_branch location
89 −\providecommand{\SPIDmentionsKeyedNameToken}{187{,}212} % composition.json:mentions_by_key_branch name_token
90 −\providecommand{\SPIDmentionsKeyedNameTokenPct}{60.8} % 187,212 / 308,065
91 −\providecommand{\SPIDtopTokenMentions}{40{,}407} % top_name_tokens.csv acquisition
92 −\providecommand{\SPIDtopTokenProjects}{2{,}256} % top_name_tokens.csv acquisition
93 −\providecommand{\SPIDtopTokenSharePct}{21.4} % pct_of_tokenkeyed_mentions
94 −\providecommand{\SPIDlocationKeysCountry}{8{,}126} % composition.json:location_keyed_projects_by_geo_kind country
95 −\providecommand{\SPIDlocationKeysUsState}{6{,}110} % us_state
96 −\providecommand{\SPIDlocationKeysCountryStatePct}{26} % (8,126 + 6,110) / 54,658
97 −\providecommand{\SPIDlocationKeyUnitedStatesProjects}{2{,}551}% top_location_keys.csv 'united states'
98 −\providecommand{\SPIDprojectsKeyCikType}{21{,}027} % spec_curve.csv k_cik_type 0.45
99 −\providecommand{\SPIDprojectsKeyTypeDropped}{96{,}749} % k_type_dropped 0.45
100 −\providecommand{\SPIDprojectsKeyNameOnly}{114{,}244} % k_name_only 0.45
101 −\providecommand{\SPIDprojectsKeyCityNorm}{123{,}246} % k_city_normalised 0.45
102 −\providecommand{\SPIDprojectsKeyStopwords}{130{,}101} % k_current_stopwords 0.45
103 −\providecommand{\SPIDprojectsKeyTwoTokens}{145{,}697} % k_two_tokens 0.45
104 −\providecommand{\SPIDprojectsKeyStrict}{198{,}488} % k_strict 0.45
105 −\providecommand{\SPIDprojectsKeyMentionLevel}{308{,}065} % k_mention_level 0.45
106 −\providecommand{\SPIDprojectsCurrentKeyAtNine}{83{,}483} % k_current 0.9
107 −\providecommand{\SPIDsingleMentionShareStrict}{75.8} % k_strict 0.45 single_mention_pct
108 −\providecommand{\SPIDsingleMentionShareCikType}{20.7} % k_cik_type 0.45
109 −\providecommand{\SPIDchenierClusterCurrent}{8} % example_cluster_size_cheniere k_current
110 −\providecommand{\SPIDchenierClusterStrict}{1} % k_strict
111 −\providecommand{\SPIDchenierClusterNameOnly}{40} % k_name_only
112 −\providecommand{\SPIDchenierClusterCikType}{176} % k_cik_type
113 −\providecommand{\SPIDmaGeThreeNamesPct}{14.6} % overmerge_by_type.csv ma_integration pct_ge3_names
114 −\providecommand{\SPIDmaGeThreeNamesOverTenPct}{86.6} % overmerge_ma_by_bucket.csv >10 mentions
115 −\providecommand{\SPIDmaGeThreePartnersPct}{10.9} % overmerge_by_type.csv ma_integration pct_ge3_partners_among_with_partner
116 −\providecommand{\SPIDmaAmountOtherCounterpartyN}{1{,}630} % composition.json:amount_from_other_counterparty_ma[0]
117 −\providecommand{\SPIDmaAmountOtherCounterpartyDenom}{12{,}372}% composition.json:amount_from_other_counterparty_ma[1]
118 −\providecommand{\SPIDamountOtherCounterpartyN}{2{,}347} % composition.json:amount_from_other_counterparty[0]
119 −\providecommand{\SPIDamountOtherCounterpartyDenom}{21{,}908} % composition.json:amount_from_other_counterparty[1]
120 −\providecommand{\SPIDprojectsTieDistinctDescriptions}{29{,}954} % ties_idempotence.json
121 −\providecommand{\SPIDrebuiltNameDiff}{394} % ties_idempotence.json:rebuilt_vs_stored_diff[0]
122 −\providecommand{\SPIDrebuiltDescDiff}{600} % ties_idempotence.json:rebuilt_vs_stored_diff[2]
123 −\providecommand{\SPIDtiebreakNameDiff}{11{,}484} % ties_idempotence.json:deterministic_vs_stored_diff[0]
124 −\providecommand{\SPIDtiebreakStatusDiff}{503} % [1]
125 −\providecommand{\SPIDtiebreakDescDiff}{18{,}256} % [2]
126 −\providecommand{\SPIDjuneProjects}{19{,}227} % june_october_reconciliation.json:projects_from_backfilled_block_only
127 −\providecommand{\SPIDspMentions}{70{,}367} % sp500_mentions_total
128 −\providecommand{\SPIDspProjects}{27{,}766} % sp500_projects_total
129 −\providecommand{\SPIDspProjectsJuneOnly}{15{,}910} % sp500_projects_by_run_composition
130 −\providecommand{\SPIDspProjectsBothRuns}{3{,}317}
131 −\providecommand{\SPIDspProjectsOctoberOnly}{8{,}539}
132 −\providecommand{\SPIDoctoberSpTenQSections}{116{,}231} % sp500_october_ledger_by_form 10-Q
133 −\providecommand{\SPIDoctoberSpTenQFilings}{19{,}399}
134 −\providecommand{\SPIDoctoberSpTenQMentions}{28{,}963} % sp500_mentions_by_run_form october 10-Q
135 −\providecommand{\SPIDjuneTenQFilings}{3{,}710} % june_10q_accessions_in_block_ledger
136 −\providecommand{\SPIDjuneTenQSections}{23{,}873} % ledger_block_accessions_by_form 10-Q
137 −\providecommand{\SPIDjuneTenQMentions}{5{,}817} % sp500_mentions_by_run_form backfilled_june 10-Q
138 −\providecommand{\SPIDoctoberSpTenKMentions}{910} % october 10-K
139 −\providecommand{\SPIDoctoberSpEightKMentions}{564} % october 8-K
140 −
141 −% ---- two runs / two segmenters (results/runs/git_evidence.md, segmenters.json, segmenter_item_comparison.csv, funnel_10k.json, within_*.csv, table6_cohort*.json/csv, fiscal_year_audit.json) ----
142 −\providecommand{\SPIDrepoCommits}{six} % git_evidence.md: all commits dated 2026-10-27/28
143 −\providecommand{\SPIDextractorMtimeDate}{June~17, 2026} % git_evidence.md: llm.py, rules.py, base.py, taxonomy.py, resolve.py, ingest.py mtimes
144 −\providecommand{\SPIDdiffStoreLines}{$+3/-1$} % git_diff_df7905d_2324b58.patch (store.py)
145 −\providecommand{\SPIDdiffParserLines}{$+13/-7$} % git_diff_0304133_2324b58.patch (filing_parser.py)
146 −\providecommand{\SPIDlegacyTenKRows}{27{,}164} % segmenters.json:legacy_rows
147 −\providecommand{\SPIDlegacyTenKFilings}{7{,}368} % segmenters.json:legacy_accessions
148 −\providecommand{\SPIDlegacyShareTenKLedgerPct}{18.9} % 27,164 / 143,704
149 −\providecommand{\SPIDsegPairs}{25{,}673} % segmenters.json:legacy_rows_matched_by_item
150 −\providecommand{\SPIDlegacyMdnaDollar}{141} % segmenter_item_comparison.csv md_and_a legacy_mean_dollar
151 −\providecommand{\SPIDparsedMdnaDollar}{272} % parsed_mean_dollar
152 −\providecommand{\SPIDlegacyMdnaWords}{9{,}921} % legacy_median_words
153 −\providecommand{\SPIDparsedMdnaWords}{11{,}661} % parsed_median_words
154 −\providecommand{\SPIDlegacyFewerMoneyPct}{92.3} % pct_legacy_fewer_money_tokens
155 −\providecommand{\SPIDlegacyMdnaNumeric}{596} % legacy_mean_numeric
156 −\providecommand{\SPIDparsedMdnaNumeric}{1{,}177} % parsed_mean_numeric
157 −\providecommand{\SPIDpropertiesLtHalfPct}{19.4} % properties pct_legacy_lt_half_words
158 −\providecommand{\SPIDfullBodyMedianWords}{44{,}514} % segmenters.json:full_body_rows[2]
159 −\providecommand{\SPIDfullBodyYield}{0.67} % full_body_ledger_yield[3]
160 −\providecommand{\SPIDfullBodyProductivePct}{25.7} % full_body_ledger_yield[4]
161 −\providecommand{\SPIDfullBodyWithParsedItems}{1{,}117} % implemented_changes.md N4 (segmenters.json)
162 −\providecommand{\SPIDfullBodyUnsubmittedSections}{5{,}385} % implemented_changes.md N4 (segmenters.json)
163 −\providecommand{\SPIDfullDocumentTenK}{86} % segmenters.json / funnel_10k.json
164 −\providecommand{\SPIDfullDocumentTenKLegacy}{51} % parsed_section_names_same_accessions full_document
165 −\providecommand{\SPIDfullDocumentTenKInvisible}{35} % 86 - 51
166 −\providecommand{\SPIDfullDocumentTenQ}{243} % funnel_10k.json:parsed_10q_items full_document
167 −\providecommand{\SPIDfullDocumentTenQLedgered}{241} % funnel_10k.json:ledger_10q_items full_document
168 −\providecommand{\SPIDtenKparsedRows}{341{,}207} % funnel_10k.json:parsed_10k_rows_total
169 −\providecommand{\SPIDtenKoutOfScopeRows}{188{,}518} % parsed_10k_rows_out_of_scope_item
170 −\providecommand{\SPIDtenKlegacyAccessionRows}{35{,}037} % parsed_10k_in_scope_rows_of_legacy_accessions
171 −\providecommand{\SPIDtenKunderThirtyRows}{1{,}112} % parsed_10k_in_scope_rows_lt30_words_non_legacy
172 −\providecommand{\SPIDtenKparsedLedgered}{116{,}540} % parsed_10k_in_scope_rows_ge30_non_legacy
173 −\providecommand{\SPIDwithinProductiveJune}{12.4} % within_sp500_by_run_form.csv backfilled_june 10-Q productive_pct
174 −\providecommand{\SPIDwithinProductiveOctober}{12.7} % october 10-Q
175 −\providecommand{\SPIDwithinMentionsPerRowJune}{0.244} % mentions_per_row
176 −\providecommand{\SPIDwithinMentionsPerRowOctober}{0.250}
177 −\providecommand{\SPIDwithinConfJune}{0.889} % within_sp500_10q_mentions_by_run.csv mean_conf
178 −\providecommand{\SPIDwithinConfOctober}{0.893}
179 −\providecommand{\SPIDwithinMaShareJune}{49.9} % within_sp500_10q_type_mix_by_run.csv ma_integration
180 −\providecommand{\SPIDwithinMaShareOctober}{45.7}
181 −\providecommand{\SPIDpairedIssuers}{81} % within_issuer_paired_10q.json:issuers_paired
182 −\providecommand{\SPIDpairedDeltaPp}{0.6} % mean_diff_productive_share_oct_minus_june (pp)
183 −\providecommand{\SPIDpairedSePp}{1.3} % se (pp)
184 −\providecommand{\SPIDcohortIssuersBoth}{491} % table6_cohort.csv both.issuers
185 −\providecommand{\SPIDcohortIssuersRussellOnly}{1{,}992} % russell_only.issuers
186 −\providecommand{\SPIDcohortIssuersSpOnly}{9} % sp500_only.issuers
187 −\providecommand{\SPIDcohortBothPerIssuerAll}{55.8} % both.per_issuer_all
188 −\providecommand{\SPIDcohortRussellOnlyPerIssuer}{46.9} % russell_only.per_issuer_all
189 −\providecommand{\SPIDcohortBothPerIssuerOctober}{25.1} % both.per_issuer_october_only
190 −\providecommand{\SPIDcohortOlsAll}{8.84} % table6_cohort_regression.json:projects_all_on_sp500.in_sp500.coef
191 −\providecommand{\SPIDcohortOlsAllSe}{1.62} % hc1_se
192 −\providecommand{\SPIDcohortOlsOctober}{-22.98} % projects_october_only_on_sp500.in_sp500.coef
193 −\providecommand{\SPIDcohortOlsOctoberSe}{1.20}
194 −\providecommand{\SPIDcohortOlsControlled}{-0.28} % projects_all_on_sp500_log_rows.in_sp500.coef
195 −\providecommand{\SPIDcohortOlsControlledSe}{1.52}
196 −\providecommand{\SPIDcohortOlsN}{2{,}499} % n
197 −\providecommand{\SPIDfiscalYearNullMentions}{68{,}827} % fiscal_year_audit.json
198 −\providecommand{\SPIDfiscalYearNullOctTenK}{823}
199 −\providecommand{\SPIDfiscalYearNullOctTenQ}{28{,}074}
200 −\providecommand{\SPIDfiscalYearNullFilings}{134{,}124} % src_filings_fiscal_year_null_by_form (sum)
201 −\providecommand{\SPIDfiscalYearFillAccessions}{31{,}976} % fiscal_year_fill_by_accession.csv rows
202 −
203 −% ---- focus windows (results/focus/stats_keys.json, focus_coverage_by_form_item.csv, shown_fraction_bins.csv, mdna_10k_short_by_year.csv; results/rules/focus_recall_loss*.csv) ----
204 −\providecommand{\SPIDfocusOverBudgetSections}{326{,}095} % stats_keys.json:ledger_sections_over_9000_chars
205 −\providecommand{\SPIDfocusOverBudgetSectionsPct}{29} % 326,095 / 1,123,098
206 −\providecommand{\SPIDfocusOverBudgetCalls}{324{,}386} % stats_keys.json:calls_over_9000_chars
207 −\providecommand{\SPIDfocusOverBudgetCallsPct}{46} % 324,386 / 703,725
208 −\providecommand{\SPIDfocusMeanShownOverBudgetPct}{15.9} % stats_keys.json:mean_shown_frac_over_budget
209 −\providecommand{\SPIDmdnaN}{28{,}919} % stats_keys.json:ledger_10k_mdna_n
210 −\providecommand{\SPIDmdnaMedianWords}{9{,}905} % stats_keys.json:ledger_10k_mdna_median_words
211 −\providecommand{\SPIDmdnaMedianChars}{64{,}194} % ledger_10k_mdna_median_chars
212 −\providecommand{\SPIDmdnaShownMedianPct}{9.3} % ledger_10k_mdna_shown_p50
213 −\providecommand{\SPIDmdnaShownPTenPct}{4.3} % focus_coverage_by_form_item.csv 10-K md_and_a shown_p10
214 −\providecommand{\SPIDmdnaShownPNinetyPct}{24} % shown_p90
215 −\providecommand{\SPIDmdnaLastShownMedianPct}{16} % ledger_10k_mdna_last_p50
216 −\providecommand{\SPIDmdnaShownLtTwentyFivePct}{90.5} % ledger_10k_mdna_pct_shown_lt_25
217 −\providecommand{\SPIDmdnaHitsShownMedianPct}{15.6} % hits_shown_p50
218 −\providecommand{\SPIDbusinessShownMedianPct}{15.7} % 10-K business shown_p50
219 −\providecommand{\SPIDriskShownMedianPct}{10.1} % 10-K risk_factors shown_p50
220 −\providecommand{\SPIDtenQmdnaShownMedianPct}{13.2} % 10-Q md_and_a shown_p50
221 −\providecommand{\SPIDtenQfinShownMedianPct}{10.6} % 10-Q financial_statements shown_p50
222 −\providecommand{\SPIDeightKWholePct}{91} % 100 - 8-K pct_over_9000 (8.82)
223 −\providecommand{\SPIDmsgTruncatedN}{0} % stats_keys.json:msg_truncated_14k
224 −\providecommand{\SPIDmentionsFromLtTwentyFive}{193{,}416} % stats_keys.json:mentions_from_sections_shown_lt_25
225 −\providecommand{\SPIDmentionsFromLtTwentyFivePct}{62.7} % / 308,477
226 −\providecommand{\SPIDmentionsFromLtTwentyFiveTenK}{84} % focus_coverage_by_form.csv 10-K pct_mentions_from_lt25
227 −\providecommand{\SPIDmentionsFromLtTwentyFiveTenQ}{79} % 10-Q
228 −\providecommand{\SPIDmentionsFromLtTwentyFiveEightK}{6} % 8-K (5.74)
229 −\providecommand{\SPIDplateauLow}{0.4} % mentions_vs_length_by_item.csv 10-K md_and_a
230 −\providecommand{\SPIDplateauHigh}{1.5}
231 −\providecommand{\SPIDplateauRange}{1.2--1.6}
232 −\providecommand{\SPIDplateauKchars}{20{,}000}
233 −\providecommand{\SPIDmentionsPerTenKShownChars}{2.5}
234 −\providecommand{\SPIDcapexVocabShownMdnaPct}{5.8} % focus_coverage_by_form_item.csv pct_capex_vocab_shown_over_budget 10-K md_and_a
235 −\providecommand{\SPIDcapexVocabShownBusinessPct}{10.0}
236 −\providecommand{\SPIDcapexVocabShownTenQmdnaPct}{8.3}
237 −\providecommand{\SPIDshortMdnaN}{169} % mdna_10k_short_by_year.csv sum(lt30_words)
238 −\providecommand{\SPIDshortMdnaDenom}{29{,}088} % sum(mdna_sections)
239 −\providecommand{\SPIDshortMdnaPct}{0.6}
240 −\providecommand{\SPIDshortMdnaIncorporatedN}{470} % sum(lt300_incorporated_by_ref)
241 −\providecommand{\SPIDrulesFocusRecovered}{84{,}841} % focus_recall_loss_overall.csv rules_focused
242 −\providecommand{\SPIDrulesFocusTotal}{324{,}237} % rules_full
243 −\providecommand{\SPIDrulesFocusRecoveredPct}{26.2} % 100 - pct_lost
244 −\providecommand{\SPIDrulesFocusMdnaPct}{20.8} % focus_recall_loss.csv 10-K md_and_a (100 - 79.18)
245 −\providecommand{\SPIDrulesFocusBusinessPct}{36.9} % 10-K business
246 −\providecommand{\SPIDrulesFocusTenQmdnaPct}{25.1} % 10-Q md_and_a
247 −\providecommand{\SPIDrulesFocusEightKPct}{84.2} % 8-K full_body
248 −
249 −% ---- rules baseline (results/rules/agreement_overall.csv, agreement_by_form.csv, agreement_by_run.csv, type_agreement.csv) ----
250 −\providecommand{\SPIDrulesSampleProductive}{30{,}000} % manifest.json notes.sample
251 −\providecommand{\SPIDrulesSampleZero}{30{,}000}
252 −\providecommand{\SPIDrulesGivenLlmPct}{85.7} % p_rules_given_llm
253 −\providecommand{\SPIDrulesGivenLlmTenK}{97.4}
254 −\providecommand{\SPIDrulesGivenLlmTenQ}{94.4}
255 −\providecommand{\SPIDrulesGivenLlmEightK}{69.2}
256 −\providecommand{\SPIDrulesGivenLlmJune}{79.8}
257 −\providecommand{\SPIDrulesGivenLlmOctober}{86.7}
258 −\providecommand{\SPIDllmGivenRulesPct}{32.5} % p_llm_given_rules_weighted
259 −\providecommand{\SPIDrulesFlagPct}{39.5} % rules_pos_pct_weighted
260 −\providecommand{\SPIDrulesAgreementPct}{71.2} % agreement_pct_w
261 −\providecommand{\SPIDrulesLlmOnlyPct}{2.1}
262 −\providecommand{\SPIDrulesOnlyPct}{26.6}
263 −\providecommand{\SPIDrulesTypeOverlapPct}{84.6} % type_overlap_pct_codetected
264 −\providecommand{\SPIDrulesTypeMa}{96.8} % type_agreement.csv
265 −\providecommand{\SPIDrulesTypeDrug}{92.5}
266 −\providecommand{\SPIDrulesTypeCost}{76.9}
267 −\providecommand{\SPIDrulesTypeCapex}{55.2}
268 −\providecommand{\SPIDrulesTypePlant}{40.7}
269 −\providecommand{\SPIDrulesTypeGeo}{36.5}
270 −
271 −% ---- financing / buy-back false-positive classes (results/fp_classes/summary.json, financing_regex_by_type.csv, _by_item.csv, _terms.csv, table5_restated_excl_financing.csv) ----
272 −\providecommand{\SPIDfinMentions}{22{,}412} % summary.json:mentions_matched[0]
273 −\providecommand{\SPIDfinMentionsPct}{7.3} % 7.28
274 −\providecommand{\SPIDfinAmountB}{17.8} % matched_amount_gusd[0] / 1000
275 −\providecommand{\SPIDfinAmountDenomB}{104.2} % matched_amount_gusd[1] / 1000
276 −\providecommand{\SPIDfinUnregN}{5{,}179} % unregistered_sales_matched[0]
277 −\providecommand{\SPIDfinUnregDenom}{9{,}506}
278 −\providecommand{\SPIDfinUnregPct}{54.5}
279 −\providecommand{\SPIDfinEightKPct}{19.2} % financing_regex_by_item.csv 8-K full_body
280 −\providecommand{\SPIDfinFinStatementsPct}{2.4} % 10-Q financial_statements
281 −\providecommand{\SPIDfinControlsPct}{0.2} % 10-Q controls_and_procedures
282 −\providecommand{\SPIDfinCapexPct}{52.6} % financing_regex_by_type.csv capex_program
283 −\providecommand{\SPIDfinCostPct}{16.4} % cost_reduction
284 −\providecommand{\SPIDfinMaPct}{7.0} % ma_integration
285 −\providecommand{\SPIDcapexProjectsExcl}{4{,}725} % table5_restated_excl_financing.csv capex_program
286 −\providecommand{\SPIDcapexShareExcl}{4.3}
287 −\providecommand{\SPIDcostProjectsExcl}{5{,}403}
288 −\providecommand{\SPIDmaProjectsExcl}{37{,}527}
289 −\providecommand{\SPIDfinProjectsRep}{12{,}027} % summary.json:projects_matched_rep[0]
290 −\providecommand{\SPIDfinProjectsRepPct}{9.9}
291 −\providecommand{\SPIDfinProjectsAny}{13{,}139} % projects_matched_rep[1]
292 −\providecommand{\SPIDitemTwoPairs}{77{,}869} % summary.json:item2_collision pairs
293 −\providecommand{\SPIDunregMedianWords}{602}
294 −\providecommand{\SPIDtenQmdnaMedianWords}{7{,}573}
295 −\providecommand{\SPIDunregGtThreeK}{1{,}001}
296 −\providecommand{\SPIDunregGtThreeKPct}{1.3}
297 −\providecommand{\SPIDswapCandidates}{296}
298 −\providecommand{\SPIDunregGtThreeKMentions}{425}
299 −\providecommand{\SPIDfinTermRepurchase}{10{,}886} % financing_regex_terms.csv
300 −\providecommand{\SPIDfinTermSeniorNotes}{3{,}375}
301 −\providecommand{\SPIDfinTermTermLoan}{2{,}263}
302 −
303 −% ---- 8-K item-code consistency (results/benchmark_8k/summary.json, item_vs_type.csv scope=all_8k_sections) ----
304 −\providecommand{\SPIDeightKItemCodePct}{99.7} % summary.json:coverage_pct 99.74
305 −\providecommand{\SPIDbenchMaGivenTwoOhOne}{0.911} % p_type_given_item ma_integration | Item 2.01
306 −\providecommand{\SPIDbenchMaGivenTwoOhOneCiLow}{0.903}
307 −\providecommand{\SPIDbenchMaGivenTwoOhOneCiHigh}{0.918}
308 −\providecommand{\SPIDbenchTwoOhOneN}{5{,}456} % n_item
309 −\providecommand{\SPIDbenchMaGivenEightOhOne}{0.199} % Item 8.01 (control)
310 −\providecommand{\SPIDbenchMaGivenFiveOhTwo}{0.031} % Item 5.02 (control)
311 −\providecommand{\SPIDbenchMaBase}{0.095} % base_rate_type
312 −\providecommand{\SPIDbenchItemsGivenMa}{0.467} % p_item_given_type, Item 2.01 or 1.01
313 −\providecommand{\SPIDbenchCostGivenTwoOhFive}{0.709} % cost_reduction | Item 2.05
314 −\providecommand{\SPIDbenchCostGivenTwoOhFiveCiLow}{0.687}
315 −\providecommand{\SPIDbenchCostGivenTwoOhFiveCiHigh}{0.730}
316 −\providecommand{\SPIDbenchTwoOhFiveN}{1{,}700}
317 −\providecommand{\SPIDbenchCostLift}{92} % lift_type_given_item 92.05
318 −\providecommand{\SPIDbenchTwoOhFiveGivenCost}{0.392}
319 −\providecommand{\SPIDbenchPartnershipGivenOneOhOne}{0.040}
320 −\providecommand{\SPIDbenchPartnershipBase}{0.011}
321 −
322 −% ---- annotation frame (results/annotation_frame/design.json) ----
323 −\providecommand{\SPIDannSeed}{20261105}
324 −\providecommand{\SPIDannStrata}{192}
325 −\providecommand{\SPIDannNProductive}{1{,}677}
326 −\providecommand{\SPIDannNZero}{385}
327 −\providecommand{\SPIDannZeroGatePass}{285}
328 −\providecommand{\SPIDannZeroGateReject}{100}
329 −\providecommand{\SPIDannCore}{510}
330 −\providecommand{\SPIDannDev}{1{,}058}
331 −\providecommand{\SPIDannHoldout}{1{,}004}
332 −\providecommand{\SPIDannDeffProductive}{3.4}
333 −\providecommand{\SPIDannDeffZero}{1.2}
334 −\providecommand{\SPIDannHalfWidthPrecision}{4.4} % half_width_95_precision_p0.5 (pp)
335 −\providecommand{\SPIDannHalfWidthFn}{2.4} % half_width_95_zero_fn_rate 0.05 (pp)
336 −\providecommand{\SPIDannMde}{7.8} % mde_gate_recall_diff_at_p0.05 (pp)
337 −\providecommand{\SPIDannFloor}{10}
338 −\providecommand{\SPIDannOversample}{2}
339 −\providecommand{\SPIDannPopProductive}{168{,}230}
340 −\providecommand{\SPIDannPopZero}{954{,}868}
341 −
342 −% ---- time series (results/timeseries/summary.json, first_seen_fixed_cohort.csv) ----
343 −\providecommand{\SPIDfirstSeenLastYear}{6{,}694} % all_issuers 2026 first_seen_current_key
344 −\providecommand{\SPIDfixedCohortIssuers}{1{,}389} % summary.json:cohort_issuers
345 −\providecommand{\SPIDfixedCohortMentionsPerIssuerFirst}{9.6} % 2011
346 −\providecommand{\SPIDfixedCohortMentionsPerIssuerLast}{8.8} % 2025 (8.75)
347 −\providecommand{\SPIDfixedCohortNewPerIssuerFirst}{4.7} % 2011
348 −\providecommand{\SPIDfixedCohortNewPerIssuerLast}{2.8} % 2025 (2.83)
349 −\providecommand{\SPIDfixedCohortFirstSeenFirst}{6{,}533} % 2011
350 −\providecommand{\SPIDfixedCohortFirstSeenLast}{3{,}926} % 2025
351 −\providecommand{\SPIDepisodesKthree}{131{,}823} % summary.json:episodes_k3_total
352 −\providecommand{\SPIDepisodesKfive}{126{,}318}
353 −
354 −% ---- universe and corpus artefacts (results/universe/universe_artefacts.json, results/russell_coverage.json, data/stats.json) ----
355 −\providecommand{\SPIDdualClassCiks}{18} % 2,573 - 2,555
356 −\providecommand{\SPIDuniverseBoth}{491} % implemented_changes.md N10 (universe.json)
357 −\providecommand{\SPIDuniverseSpOnly}{9}
358 −\providecommand{\SPIDuniverseRuOnly}{2{,}064}
359 −\providecommand{\SPIDparseErrors}{14} % filings_status_missing.csv parse_status = error
360 −\providecommand{\SPIDannualPanelFirms}{2{,}499} % stats.json:annual_panel_firms
361 −\providecommand{\SPIDrussellGapMax}{441} % 2,996 - 2,555
362 −\providecommand{\SPIDrussellGapMaxPct}{14.7}
363 −\providecommand{\SPIDfactsheetDate}{September~30, 2026} % russell_coverage.json:index_as_of
364 −\providecommand{\SPIDiwvHoldingsDate}{October~23, 2026} % stats.json:universe.russell_holdings_as_of
365 −\providecommand{\SPIDiwvFetchDate}{October~27, 2026} % universe_artefacts.json:russell_scalars.fetched_at
366 −\providecommand{\SPIDiwvPageDate}{November~4, 2026} % russell_coverage.json:fund_holdings_as_of
367 −\providecommand{\SPIDiwvProspectusDate}{July~31, 2026} % russell_coverage.json:replication_source_title
368 −\providecommand{\SPIDuniverseJsonSha}{3967b29b} % universe_artefacts.json sha256 prefix
369 −\providecommand{\SPIDrussellJsonSha}{758cbebf}
370 −\providecommand{\SPIDspJsonSha}{50840752}
371 −\providecommand{\SPIDfactsheetSha}{281e9264} % russell_coverage.json:source_sha256 prefix
372 −\providecommand{\SPIDmethodologySha}{26d2d051} % methodology_document.sha256 prefix
373 −\providecommand{\SPIDissuersWithoutFilings}{65} % stats.json / Table 1
374 −\providecommand{\SPIDissuersFilingsNoProject}{7} % 2,499 - 2,492
375 −\providecommand{\SPIDspWikipediaRows}{503} % universe_artefacts.json:sp500_scalars.count
376 −\providecommand{\SPIDspWikipediaDate}{May~25, 2026} % sp500_scalars.fetched_at
377 −\providecommand{\SPIDtickerMapSize}{10{,}430} % cik_mapping_scalars.count
378 −
379 −% ---- run facts quoted in the text (docs/research_log.md, environment.md, reproducibility) ----
380 −\providecommand{\SPIDtotalCostUsd}{775} % research_log.md 2026-10-27/28 (author-reported total)
381 −\providecommand{\SPIDworkers}{48} % log_summary.json:october.workers_values
382 −\providecommand{\SPIDrequirementsLockPackages}{88} % requirements.lock (N12)
383 −\providecommand{\SPIDpythonVersion}{3.12.15} % .python-version (N12)
384 −\providecommand{\SPIDduckdbVersion}{2.0.0} % environment.md (N12)
385 −\providecommand{\SPIDreferencesN}{42} % references.bib entries (L4)
386 −\providecommand{\SPIDdoiVerifiedN}{36} % L4: DOIs re-resolved 2026-11-05
387 −\providecommand{\SPIDtestsN}{22} % tests/test_tables.py (L6)
388 −\providecommand{\SPIDsnapshotFilesN}{nine} % code/audit/spid_snapshot/SHA256SUMS
389 −\providecommand{\SPIDjuneRunDate}{June~18, 2026} % log_summary.json:june.first/last
390 −\providecommand{\SPIDbackfillTimestamp}{October~27, 2026, 13:12} % backfill_block.json:min_extracted_at
391 −
392 −% ---- added for Sections 3-4 (data.tex, methodology.tex) ----
393 −\providecommand{\SPIDissuersFilingFirstYear}{1{,}392} % results/timeseries/first_seen_fixed_cohort.csv all_issuers 2010 issuers_filing
394 −\providecommand{\SPIDissuersFilingLastYear}{2{,}498} % all_issuers 2026 issuers_filing
395 −\providecommand{\SPIDfilingsNotParsedPct}{0.003} % 16 / 527,548
396 −\providecommand{\SPIDcorpusDbGb}{68} % results/*/manifest.json edgar_research.duckdb 73,500,995,584 B (= 68.5 GiB)
397 −\providecommand{\SPIDspidDbGb}{3.2} % spid.duckdb 3,155,701,760 B
398 −\providecommand{\SPIDcorpusParquetGb}{29.1} % results/n0_probe (N0): parquet 1,342,283 sections / 29.1 GB
399 −\providecommand{\SPIDacqNewDocs}{about 400{,}000} % author-reported run fact (docs/research_log.md 2026-10-27); orchestrator log not archived with the paper
400 −\providecommand{\SPIDacqHours}{seven} % author-reported run fact; not archived
401 −\providecommand{\SPIDacqReqPerSec}{17} % author-reported run fact; not archived
402 −\providecommand{\SPIDacqNodes}{ten} % docs/research_log.md 2026-10-27 (10 cluster nodes + 1 external gateway)
403 −\providecommand{\SPIDacqNodeRate}{0.9} % author-reported (requests per second per node)
404 −\providecommand{\SPIDacqGatewayRate}{one} % author-reported (requests per second per shard on the gateway)
405 −\providecommand{\SPIDacqGatewayDivisor}{nine} % author-reported (requests per second shared behind one IP)
406 −\providecommand{\SPIDparseFilingsPerSec}{100} % author-reported run fact; not archived
407 −\providecommand{\SPIDparseMinutesRange}{five to thirteen} % author-reported run fact; not archived
408 −\providecommand{\SPIDembedMinutesRange}{15--40} % author-reported run fact; not archived
409 −\providecommand{\SPIDmergeMinutes}{seven} % author-reported run fact; not archived
410 −\providecommand{\SPIDworkersJune}{16} % results/ledger/log_summary.json:june.ciks_total_lines (workers=16)
411 −\providecommand{\SPIDjuneBatchSize}{15} % log_summary.json:june (batch=15)
412 −\providecommand{\SPIDoctoberBatchSize}{20} % log_summary.json:october.batch_values
413 −\providecommand{\SPIDfocusWindowBefore}{220} % code/audit/spid_snapshot/llm.py _focus (characters before a gate hit)
414 −\providecommand{\SPIDfocusWindowAfter}{380} % llm.py _focus (characters after a gate hit)
415 −\providecommand{\SPIDfocusCollectBudget}{12{,}600} % llm.py _focus (collection stop)
416 −\providecommand{\SPIDfocusEmitBudget}{9{,}000} % llm.py _focus (emitted budget)
417 −\providecommand{\SPIDuserMessageCap}{14{,}000} % llm.py:126 user message cut
418 −\providecommand{\SPIDminWords}{30} % config.py / pipeline.py minimum section length
419 −\providecommand{\SPIDconfThreshold}{0.45} % llm.py confidence threshold
420 −\providecommand{\SPIDconfDefault}{0.6} % llm.py:142-146 default when confidence is missing or non-numeric
421 −\providecommand{\SPIDcompletionTokens}{2{,}000} % llm.py completion limit
422 −\providecommand{\SPIDlistItemsMax}{eight} % llm.py list truncation
423 −\providecommand{\SPIDlistItemChars}{120} % llm.py list item truncation
424 −\providecommand{\SPIDidNameChars}{40} % llm.py:141 anchor = type + name[:40]
425 −\providecommand{\SPIDretries}{three} % llm.py:119-120 retries before returning an empty list
426 −\providecommand{\SPIDtimeoutSeconds}{120} % llm.py call timeout
427 −\providecommand{\SPIDtenKsectionsMax}{fourteen} % src/parsing/section_extractor.py (Items 1 to 9B)
428 −\providecommand{\SPIDtenQsectionsN}{seven} % src/parsing/section_extractor.py
429 −\providecommand{\SPIDchunkWords}{512} % src/parsing/chunker.py
430 −\providecommand{\SPIDchunkOverlap}{64} % src/parsing/chunker.py
431 −\providecommand{\SPIDmaxFileMb}{50} % src/parsing/html_parser.py
432 −\providecommand{\SPIDembeddingDim}{384} % MiniLM embedding dimension (scripts/build_embeddings.py)
433 −\providecommand{\SPIDsecRateLimit}{ten} % secfairaccess (requests per second)
434 −\providecommand{\SPIDcooldownSeconds}{65} % src/acquisition/bulk_downloader.py
435 −\providecommand{\SPIDfactorAnchors}{8} % scripts/build_factors.py (thematic anchors)
436 −\providecommand{\SPIDembeddingsRows}{10{,}720{,}890} % stats.json chunks
437 −\providecommand{\SPIDannualPanelRows}{32{,}852} % data/factor_tables.csv annual_panel rows
438 −\providecommand{\SPIDquarterlyPanelRows}{128{,}043} % data/factor_tables.csv quarterly_panel rows
439 −
440 −% ---- added for Sections 5-7 (construct.tex, resolution.tex, results.tex) ----
441 −\providecommand{\SPIDgateRejectedPct}{37.3} % 419,361 / 1,123,098 (results/ledger/gate_pass_totals.json)
442 −\providecommand{\SPIDusdPerOctoberRow}{0.0008} % gate_pass_totals.json:usd_per_october_row_paper_total_775
443 −\providecommand{\SPIDjsonFailBeforeOutage}{nine} % log_summary.json:october.outside_window_list (json_decode_error before 01:10)
444 −\providecommand{\SPIDjsonFailAfterOutage}{five} % after 06:22
445 −\providecommand{\SPIDmentionsKeyedLocationPct}{38.6} % 118,783 / 308,065
446 −\providecommand{\SPIDmentionsPerProject}{2.54} % 308,065 / 121,099 (data/projects_by_type.csv mean)
447 −\providecommand{\SPIDmentionsPerProjectDrug}{4.99} % data/projects_by_type.csv drug_pipeline mean_mentions
448 −\providecommand{\SPIDmentionsPerProjectTechDeploy}{1.63} % technology_deployment mean_mentions
449 −\providecommand{\SPIDtwoMentionShare}{17.0} % data/mentions_per_project.csv bucket 2 (20,544 / 121,099)
450 −\providecommand{\SPIDoverFiveMentionShare}{8.2} % data/mentions_per_project.csv buckets > 5
451 −\providecommand{\SPIDprojectsPerIssuerMax}{240} % data/projects_per_issuer.csv mx
452 −\providecommand{\SPIDamountPTwentyFiveMusd}{23} % data/amount_dist.csv q[1]
453 −\providecommand{\SPIDkgEdgesOwns}{121{,}099} % data/kg.csv
454 −\providecommand{\SPIDkgEdgesLocatedIn}{54{,}583}
455 −\providecommand{\SPIDkgEdgesUses}{28{,}774}
456 −\providecommand{\SPIDspanZeroN}{67{,}170} % data/duration.csv span 0
457 −\providecommand{\SPIDconfShareHalf}{0.5} % data/confidence_dist.csv 1,611 / 308,065
458 −\providecommand{\SPIDfinAmountSharePct}{17.1} % 17.8 / 104.2 (results/fp_classes/summary.json)
459 −\providecommand{\SPIDnCostReduction}{6{,}481} % data/projects_by_type.csv cost_reduction n
460 −\providecommand{\SPIDstabilitySections}{500} % consolidated_review.md §6 item 11 (X1 protocol: 500 sections x 3)
461 −\providecommand{\SPIDstabilityCalls}{about 2{,}500} % consolidated_review.md §6 item 11
462 −\providecommand{\SPIDresubmitSections}{200} % consolidated_review.md §6 item 11 (ADVE-08 ii)
463 −\providecommand{\SPIDannTextChars}{2{,}000} % results/annotation_frame (worktree CSV text truncation)
464 −\providecommand{\SPIDannFrameMb}{77} % implemented_changes.md N11 (frames on the node)
465 −\providecommand{\SPIDunregLongThreshold}{3{,}000} % results/fp_classes/summary.json item2_collision (unreg_gt_3000)
modified paper/tables/gate_regex.tex +3 −2
@@ -1,5 +1,6 @@
1 −\begin{verbatim}
1 +% Generated by code/make_tables.py from code/audit/spid_snapshot/rules.py (_PROJECT_GATE, three source lines concatenated at run time).
2 +{\footnotesize\begin{verbatim}
2 3 \b(project|initiative|program|invest|expan|construct|build|launch|develop|
3 4 deploy|implement|acqui|partner|facilit|capacity|capital|migrat|transform|
4 5 pipeline|plant|data ?cent|automat|sustainab|renewable|restructur)\w*
5 −\end{verbatim}
6 +\end{verbatim}}
modified paper/tables/numbers.tex +636 −13
@@ -1,19 +1,21 @@
1 1 % Generated by code/make_tables.py — inline numbers of the paper. Do not edit; use \SPID<name> in the text.
2 2 % Source and formula of every macro: results/inline_numbers.json
3 3 \newcommand{\SPIDiwvEquityLines}{2{,}587}
4 −\newcommand{\SPIDuniverseN}{2{,}564}
5 −\newcommand{\SPIDrussellDistinctCiks}{2{,}555}
6 −\newcommand{\SPIDrussellMappedLines}{2{,}573}
7 −\newcommand{\SPIDrussellUnmatched}{7}
8 4 \newcommand{\SPIDrussellIndexConstituents}{2{,}996}
9 5 \newcommand{\SPIDrussellProxyCoveragePct}{85.3}
10 6 \newcommand{\SPIDiwvHoldingsCount}{2{,}588}
11 7 \newcommand{\SPIDiwvReplicationMethod}{representative sampling}
8 +\newcommand{\SPIDuniverseN}{2{,}564}
9 +\newcommand{\SPIDrussellDistinctCiks}{2{,}555}
10 +\newcommand{\SPIDrussellMappedLines}{2{,}573}
11 +\newcommand{\SPIDrussellUnmatched}{7}
12 +\newcommand{\SPIDrussellDualClassCiks}{18}
12 13 \newcommand{\SPIDfilingDateFirst}{2010-01-04}
13 14 \newcommand{\SPIDfilingDateLast}{2026-10-27}
14 15 \newcommand{\SPIDfilingsTotal}{527{,}548}
15 16 \newcommand{\SPIDfilingsNotParsed}{16}
16 17 \newcommand{\SPIDfilingsMissingOnDisk}{2}
18 +\newcommand{\SPIDfilingsParserError}{14}
17 19 \newcommand{\SPIDrawGb}{254.5}
18 20 \newcommand{\SPIDfirstSeenYearMin}{2011}
19 21 \newcommand{\SPIDfirstSeenYearMax}{2025}
@@ -27,6 +29,8 @@
27 29 \newcommand{\SPIDmentionsPerIssuerFirstYear}{9.7}
28 30 \newcommand{\SPIDmentionsPerIssuerLastFullYear}{10.2}
29 31 \newcommand{\SPIDlastYear}{2026}
32 +\newcommand{\SPIDissuersFilingFirstYear}{1{,}392}
33 +\newcommand{\SPIDissuersFilingLastYear}{2{,}498}
30 34 \newcommand{\SPIDcallsOneZeroK}{135{,}310}
31 35 \newcommand{\SPIDcallsOneZeroQ}{363{,}973}
32 36 \newcommand{\SPIDcallsEightK}{204{,}442}
@@ -50,6 +54,13 @@
50 54 \newcommand{\SPIDgatePassTotal}{703{,}725}
51 55 \newcommand{\SPIDproductiveShareCalls}{23.9}
52 56 \newcommand{\SPIDmentionsPerCall}{0.44}
57 +\newcommand{\SPIDgatePassRowsAll}{703{,}737}
58 +\newcommand{\SPIDresumeBatchCalls}{2{,}686}
59 +\newcommand{\SPIDresumeBatchProductive}{23}
60 +\newcommand{\SPIDresumeBatchExpected}{536}
61 +\newcommand{\SPIDresumeBatchSections}{5{,}198}
62 +\newcommand{\SPIDresumeBatchCiks}{19}
63 +\newcommand{\SPIDoutageZeroBatches}{14}
53 64 \newcommand{\SPIDtenKmdnaMentions}{39{,}099}
54 65 \newcommand{\SPIDtenQmdnaMentions}{99{,}305}
55 66 \newcommand{\SPIDtenKbusinessMentions}{30{,}492}
@@ -59,42 +70,60 @@
59 70 \newcommand{\SPIDamountMedianMusd}{128.5}
60 71 \newcommand{\SPIDsmallNThreshold}{50}
61 72 \newcommand{\SPIDsmallNCategories}{ai_initiative, automation, cloud_migration}
73 +\newcommand{\SPIDprojectsExclFinancing}{107{,}960}
74 +\newcommand{\SPIDprojectsWithFinancingMention}{13{,}139}
75 +\newcommand{\SPIDprojectsWithFinancingMentionPct}{10.8}
76 +\newcommand{\SPIDnExclFinancingCapexProgram}{4{,}519}
77 +\newcommand{\SPIDshareExclFinancingCapexProgram}{4.2}
78 +\newcommand{\SPIDnExclFinancingCostReduction}{5{,}397}
79 +\newcommand{\SPIDshareExclFinancingCostReduction}{5.0}
80 +\newcommand{\SPIDnExclFinancingMaIntegration}{36{,}687}
81 +\newcommand{\SPIDshareExclFinancingMaIntegration}{34.0}
62 82 \newcommand{\SPIDshareDataCenter}{0.4}
63 83 \newcommand{\SPIDnDataCenter}{449}
64 84 \newcommand{\SPIDwithAmountDataCenter}{129}
65 85 \newcommand{\SPIDmedianAmountDataCenter}{166.0}
86 +\newcommand{\SPIDmedianAmountCIDataCenter}{93.0--375.0}
66 87 \newcommand{\SPIDshareAiInitiative}{0.3}
67 88 \newcommand{\SPIDnAiInitiative}{376}
68 89 \newcommand{\SPIDwithAmountAiInitiative}{20}
69 90 \newcommand{\SPIDmedianAmountAiInitiative}{127.5}
91 +\newcommand{\SPIDmedianAmountCIAiInitiative}{35.0--612.5}
70 92 \newcommand{\SPIDshareCloudMigration}{0.2}
71 93 \newcommand{\SPIDnCloudMigration}{264}
72 94 \newcommand{\SPIDwithAmountCloudMigration}{35}
73 95 \newcommand{\SPIDmedianAmountCloudMigration}{50.0}
96 +\newcommand{\SPIDmedianAmountCICloudMigration}{9.4--250.0}
74 97 \newcommand{\SPIDshareAutomation}{0.3}
75 98 \newcommand{\SPIDnAutomation}{374}
76 99 \newcommand{\SPIDwithAmountAutomation}{25}
77 100 \newcommand{\SPIDmedianAmountAutomation}{13.7}
101 +\newcommand{\SPIDmedianAmountCIAutomation}{3.4--38.4}
78 102 \newcommand{\SPIDshareMaIntegration}{34.5}
79 103 \newcommand{\SPIDnMaIntegration}{41{,}742}
80 104 \newcommand{\SPIDwithAmountMaIntegration}{28{,}044}
81 105 \newcommand{\SPIDmedianAmountMaIntegration}{155.0}
106 +\newcommand{\SPIDmedianAmountCIMaIntegration}{150.0--161.5}
82 107 \newcommand{\SPIDshareCapexProgram}{8.9}
83 108 \newcommand{\SPIDnCapexProgram}{10{,}720}
84 109 \newcommand{\SPIDwithAmountCapexProgram}{9{,}452}
85 110 \newcommand{\SPIDmedianAmountCapexProgram}{300.0}
111 +\newcommand{\SPIDmedianAmountCICapexProgram}{300.0--323.2}
86 112 \newcommand{\SPIDsharePartnership}{8.2}
87 113 \newcommand{\SPIDnPartnership}{9{,}909}
88 114 \newcommand{\SPIDwithAmountPartnership}{2{,}943}
89 115 \newcommand{\SPIDmedianAmountPartnership}{75.0}
116 +\newcommand{\SPIDmedianAmountCIPartnership}{60.0--81.9}
90 117 \newcommand{\SPIDshareGeographicExpansion}{6.5}
91 118 \newcommand{\SPIDnGeographicExpansion}{7{,}868}
92 119 \newcommand{\SPIDwithAmountGeographicExpansion}{1{,}431}
93 120 \newcommand{\SPIDmedianAmountGeographicExpansion}{36.7}
121 +\newcommand{\SPIDmedianAmountCIGeographicExpansion}{30.1--44.6}
94 122 \newcommand{\SPIDsharePlantConstruction}{6.3}
95 123 \newcommand{\SPIDnPlantConstruction}{7{,}590}
96 124 \newcommand{\SPIDwithAmountPlantConstruction}{2{,}511}
97 125 \newcommand{\SPIDmedianAmountPlantConstruction}{56.0}
126 +\newcommand{\SPIDmedianAmountCIPlantConstruction}{50.0--64.9}
98 127 \newcommand{\SPIDtechCategoriesCountRange}{264--449}
99 128 \newcommand{\SPIDsectorTopFourPerIssuerRange}{62--75}
100 129 \newcommand{\SPIDsectorTopFourNames}{utilities, materials, energy, real estate}
@@ -103,6 +132,18 @@
103 132 \newcommand{\SPIDsectorIssuersHealthCare}{429}
104 133 \newcommand{\SPIDsectorProjectsIndustrials}{17{,}890}
105 134 \newcommand{\SPIDsectorIssuersIndustrials}{386}
135 +\newcommand{\SPIDcohortEffectAll}{8.8}
136 +\newcommand{\SPIDcohortEffectAllSE}{1.62}
137 +\newcommand{\SPIDcohortEffectOctober}{-23.0}
138 +\newcommand{\SPIDcohortEffectOctoberSE}{1.20}
139 +\newcommand{\SPIDcohortEffectVolumeControl}{-0.28}
140 +\newcommand{\SPIDcohortEffectVolumeControlSE}{1.52}
141 +\newcommand{\SPIDperIssuerAllBoth}{55.8}
142 +\newcommand{\SPIDperIssuerOctoberBoth}{25.1}
143 +\newcommand{\SPIDperIssuerAllRussellOnly}{46.9}
144 +\newcommand{\SPIDperIssuerOctoberRussellOnly}{46.9}
145 +\newcommand{\SPIDperIssuerAllSpFiveZeroZeroOnly}{42.7}
146 +\newcommand{\SPIDperIssuerOctoberSpFiveZeroZeroOnly}{13.1}
106 147 \newcommand{\SPIDspanKnownN}{103{,}500}
107 148 \newcommand{\SPIDspanUnknownN}{17{,}599}
108 149 \newcommand{\SPIDspanUnknownShareAll}{14.5}
@@ -115,10 +156,24 @@
115 156 \newcommand{\SPIDstatusSharePlanned}{15.1}
116 157 \newcommand{\SPIDstatusShareMentioned}{2.3}
117 158 \newcommand{\SPIDsingleMentionShare}{60.2}
159 +\newcommand{\SPIDtwoMentionShare}{17.0}
160 +\newcommand{\SPIDoverFiveMentionShare}{8.2}
118 161 \newcommand{\SPIDoverTenMentionShare}{3.1}
119 162 \newcommand{\SPIDconfShareOne}{35.2}
120 163 \newcommand{\SPIDconfShareNine}{32.7}
121 164 \newcommand{\SPIDconfShareLeSix}{1.6}
165 +\newcommand{\SPIDconfExactDefaultCount}{3{,}278}
166 +\newcommand{\SPIDamountMaxBusd}{1{,}000.0}
167 +\newcommand{\SPIDamountGeFiftyB}{104}
168 +\newcommand{\SPIDamountLeZero}{259}
169 +\newcommand{\SPIDamountRawDeviations}{584}
170 +\newcommand{\SPIDamountMentionsGeFiftyB}{161}
171 +\newcommand{\SPIDamountMentionsZero}{584}
172 +\newcommand{\SPIDamountMentionsNegative}{24}
173 +\newcommand{\SPIDamountProjectsGeFiftyB}{104}
174 +\newcommand{\SPIDamountTopTwoHundredNumberFound}{191}
175 +\newcommand{\SPIDamountTopTwoHundredCurrency}{178}
176 +\newcommand{\SPIDamountNonUsdTokenShare}{1.6}
122 177 \newcommand{\SPIDamountMentions}{120{,}240}
123 178 \newcommand{\SPIDamountMentionsShare}{39.0}
124 179 \newcommand{\SPIDamountProjects}{56{,}500}
@@ -140,10 +195,159 @@
140 195 \newcommand{\SPIDprovenanceLast}{2022-03-07}
141 196 \newcommand{\SPIDprovenanceMaxAmountBusd}{11.5}
142 197 \newcommand{\SPIDprovenanceNameYear}{2022}
198 +\newcommand{\SPIDprovenanceProjectId}{3e2705ba}
143 199 \newcommand{\SPIDgateRegexFlags}{re.IGNORECASE}
144 200 \newcommand{\SPIDgateRegexLength}{215}
145 201 \newcommand{\SPIDgateRegexAlternatives}{25}
146 202 \newcommand{\SPIDtaxonomyN}{21}
203 +\newcommand{\SPIDyearsRegexEqualPct}{39}
204 +\newcommand{\SPIDtechsRegexEqualPct}{46}
205 +\newcommand{\SPIDyearsNotInText}{604}
206 +\newcommand{\SPIDtechDeployMentionedNoSignal}{90}
207 +\newcommand{\SPIDtechDeployMentionedTotal}{124}
208 +\newcommand{\SPIDgroundedYearsPct}{99.8}
209 +\newcommand{\SPIDgroundedYearsCI}{[99.7, 99.8]}
210 +\newcommand{\SPIDgroundedYearsOneZeroKPct}{99.6}
211 +\newcommand{\SPIDgroundedYearsOneZeroQPct}{99.8}
212 +\newcommand{\SPIDgroundedYearsEightKPct}{99.8}
213 +\newcommand{\SPIDgroundedPartnersPct}{99.4}
214 +\newcommand{\SPIDgroundedPartnersCI}{[99.3, 99.5]}
215 +\newcommand{\SPIDgroundedPartnersOneZeroKPct}{99.3}
216 +\newcommand{\SPIDgroundedPartnersOneZeroQPct}{99.1}
217 +\newcommand{\SPIDgroundedPartnersEightKPct}{99.6}
218 +\newcommand{\SPIDgroundedAmountNumberPct}{93.7}
219 +\newcommand{\SPIDgroundedAmountNumberCI}{[93.6, 93.9]}
220 +\newcommand{\SPIDgroundedAmountNumberOneZeroKPct}{97.4}
221 +\newcommand{\SPIDgroundedAmountNumberOneZeroQPct}{97.5}
222 +\newcommand{\SPIDgroundedAmountNumberEightKPct}{86.9}
223 +\newcommand{\SPIDgroundedAmountWithCurrencyPct}{80.5}
224 +\newcommand{\SPIDgroundedAmountWithCurrencyCI}{[80.2, 80.7]}
225 +\newcommand{\SPIDgroundedAmountWithCurrencyOneZeroKPct}{86.8}
226 +\newcommand{\SPIDgroundedAmountWithCurrencyOneZeroQPct}{82.3}
227 +\newcommand{\SPIDgroundedAmountWithCurrencyEightKPct}{74.9}
228 +\newcommand{\SPIDgroundedLocationsPct}{78.3}
229 +\newcommand{\SPIDgroundedLocationsCI}{[78.0, 78.6]}
230 +\newcommand{\SPIDgroundedLocationsOneZeroKPct}{85.7}
231 +\newcommand{\SPIDgroundedLocationsOneZeroQPct}{82.1}
232 +\newcommand{\SPIDgroundedLocationsEightKPct}{67.8}
233 +\newcommand{\SPIDgroundedTechnologiesPct}{63.6}
234 +\newcommand{\SPIDgroundedTechnologiesCI}{[63.0, 64.2]}
235 +\newcommand{\SPIDgroundedTechnologiesOneZeroKPct}{63.8}
236 +\newcommand{\SPIDgroundedTechnologiesOneZeroQPct}{64.8}
237 +\newcommand{\SPIDgroundedTechnologiesEightKPct}{58.2}
238 +\newcommand{\SPIDgroundedAllFieldsPct}{88.2}
239 +\newcommand{\SPIDgroundedAllFieldsTenKPct}{92.2}
240 +\newcommand{\SPIDgroundedAllFieldsTenQPct}{92.4}
241 +\newcommand{\SPIDgroundedAllFieldsEightKPct}{76.6}
242 +\newcommand{\SPIDgroundedAllFieldsJunePct}{84.5}
243 +\newcommand{\SPIDgroundedAllFieldsOctoberPct}{88.7}
244 +\newcommand{\SPIDgroundedAllFieldsN}{276{,}168}
245 +\newcommand{\SPIDprojectCountRangeKeys}{21{,}027--308{,}065}
246 +\newcommand{\SPIDprojectCountRangeKeysN}{9}
247 +\newcommand{\SPIDprojectCountRangeResolvedKeys}{21{,}027--198{,}488}
248 +\newcommand{\SPIDprojectCountRangeAll}{16{,}562--308{,}065}
249 +\newcommand{\SPIDprojectCountCurrentKey}{121{,}099}
250 +\newcommand{\SPIDprojectCountStrict}{198{,}488}
251 +\newcommand{\SPIDprojectCountCikType}{21{,}027}
252 +\newcommand{\SPIDprojectCountTypeDropped}{96{,}749}
253 +\newcommand{\SPIDprojectCountNameOnly}{114{,}244}
254 +\newcommand{\SPIDprojectCountCurrentKeyHighThreshold}{83{,}483}
255 +\newcommand{\SPIDspecCurveThresholdMax}{0.9}
256 +\newcommand{\SPIDtopNameTokens}{\texttt{acquisition} (3.4\%), \texttt{share} (3.1\%), \texttt{expansion} (1.8\%), \texttt{stock} (1.7\%), \texttt{investment} (1.6\%), \texttt{merger} (1.3\%), \texttt{sale} (1.3\%), \texttt{development} (1.2\%), \texttt{strategic} (0.9\%), \texttt{capital} (0.8\%)}
257 +\newcommand{\SPIDtopNameTokensProjectsPct}{17.2}
258 +\newcommand{\SPIDtopNameToken}{acquisition}
259 +\newcommand{\SPIDtopNameTokenMentions}{40{,}407}
260 +\newcommand{\SPIDtopNameTokenProjects}{2{,}256}
261 +\newcommand{\SPIDmaProjectsAmountOtherCounterparty}{1{,}630}
262 +\newcommand{\SPIDmaProjectsBothNamed}{12{,}372}
263 +\newcommand{\SPIDmaGeThreeNamesPct}{14.6}
264 +\newcommand{\SPIDtenKmdnaShownMedianPct}{9.3}
265 +\newcommand{\SPIDtenKmdnaLastOffsetMedianPct}{16}
266 +\newcommand{\SPIDtenKmdnaShownLtQuarterPct}{90.5}
267 +\newcommand{\SPIDledgerSectionsOverBudget}{326{,}095}
268 +\newcommand{\SPIDcallsOverBudget}{324{,}386}
269 +\newcommand{\SPIDmentionsFromShownLtQuarter}{193{,}416}
270 +\newcommand{\SPIDmeanShownOverBudgetPct}{15.9}
271 +\newcommand{\SPIDtenKmdnaMedianChars}{64{,}194}
272 +\newcommand{\SPIDmessagesTruncated}{0}
273 +\newcommand{\SPIDmentionsFromShownLtQuarterPct}{62.7}
274 +\newcommand{\SPIDledgerSectionsOverBudgetPct}{29}
275 +\newcommand{\SPIDmentionsFromShownLtQuarterOneZeroKPct}{84}
276 +\newcommand{\SPIDmentionsFromShownLtQuarterOneZeroQPct}{79}
277 +\newcommand{\SPIDmentionsFromShownLtQuarterEightKPct}{6}
278 +\newcommand{\SPIDtenKmdnaShortSections}{169}
279 +\newcommand{\SPIDtenKmdnaParsedSections}{29{,}088}
280 +\newcommand{\SPIDtenKmdnaShortPct}{0.6}
281 +\newcommand{\SPIDfinancingMentions}{22{,}412}
282 +\newcommand{\SPIDfinancingMentionsPct}{7.3}
283 +\newcommand{\SPIDfinancingProjectsAnyMention}{13{,}139}
284 +\newcommand{\SPIDfinancingProjectsRep}{12{,}027}
285 +\newcommand{\SPIDfinancingAmountTusd}{17.8}
286 +\newcommand{\SPIDmentionAmountTotalTusd}{104.2}
287 +\newcommand{\SPIDfinancingUnregisteredSalesPct}{54.5}
288 +\newcommand{\SPIDfinancingMaIntegrationPct}{7.0}
289 +\newcommand{\SPIDfinancingCapexProgramPct}{52.6}
290 +\newcommand{\SPIDfinancingCostReductionPct}{16.4}
291 +\newcommand{\SPIDfinancingOneZeroKPct}{0.8}
292 +\newcommand{\SPIDfinancingOneZeroQPct}{4.9}
293 +\newcommand{\SPIDfinancingEightKPct}{19.2}
294 +\newcommand{\SPIDitemTwoCollisionSections}{1{,}001}
295 +\newcommand{\SPIDitemTwoCollisionSwapCandidates}{296}
296 +\newcommand{\SPIDpTypeGivenItemMaIntegrationItemTwoZeroOne}{91.1}
297 +\newcommand{\SPIDpItemGivenTypeMaIntegrationItemTwoZeroOne}{13.1}
298 +\newcommand{\SPIDliftMaIntegrationItemTwoZeroOne}{10}
299 +\newcommand{\SPIDpTypeGivenItemMaIntegrationItemTwoZeroOneorOneZeroOne}{35.6}
300 +\newcommand{\SPIDpItemGivenTypeMaIntegrationItemTwoZeroOneorOneZeroOne}{46.7}
301 +\newcommand{\SPIDliftMaIntegrationItemTwoZeroOneorOneZeroOne}{4}
302 +\newcommand{\SPIDpTypeGivenItemMaIntegrationItemOneZeroOne}{31.8}
303 +\newcommand{\SPIDpItemGivenTypeMaIntegrationItemOneZeroOne}{39.2}
304 +\newcommand{\SPIDliftMaIntegrationItemOneZeroOne}{3}
305 +\newcommand{\SPIDpTypeGivenItemCostReductionItemTwoZeroFive}{70.9}
306 +\newcommand{\SPIDpItemGivenTypeCostReductionItemTwoZeroFive}{39.2}
307 +\newcommand{\SPIDliftCostReductionItemTwoZeroFive}{92}
308 +\newcommand{\SPIDpTypeGivenItemPartnershipItemOneZeroOne}{4.0}
309 +\newcommand{\SPIDpItemGivenTypePartnershipItemOneZeroOne}{42.1}
310 +\newcommand{\SPIDliftPartnershipItemOneZeroOne}{4}
311 +\newcommand{\SPIDpTypeGivenItemCapexTypeItemOneZeroOne}{13.2}
312 +\newcommand{\SPIDpItemGivenTypeCapexTypeItemOneZeroOne}{46.8}
313 +\newcommand{\SPIDliftCapexTypeItemOneZeroOne}{4}
314 +\newcommand{\SPIDpTypeGivenItemMaIntegrationItemEightZeroOnecontrol}{19.9}
315 +\newcommand{\SPIDpItemGivenTypeMaIntegrationItemEightZeroOnecontrol}{48.7}
316 +\newcommand{\SPIDliftMaIntegrationItemEightZeroOnecontrol}{2}
317 +\newcommand{\SPIDpTypeGivenItemMaIntegrationItemFiveZeroTwocontrol}{3.1}
318 +\newcommand{\SPIDpItemGivenTypeMaIntegrationItemFiveZeroTwocontrol}{5.9}
319 +\newcommand{\SPIDliftMaIntegrationItemFiveZeroTwocontrol}{0}
320 +\newcommand{\SPIDpTypeGivenItemCostReductionItemEightZeroOnecontrol}{1.5}
321 +\newcommand{\SPIDpItemGivenTypeCostReductionItemEightZeroOnecontrol}{45.1}
322 +\newcommand{\SPIDliftCostReductionItemEightZeroOnecontrol}{2}
323 +\newcommand{\SPIDpTypeGivenItemMaIntegrationItemTwoZeroThreecontrol}{21.0}
324 +\newcommand{\SPIDpItemGivenTypeMaIntegrationItemTwoZeroThreecontrol}{12.4}
325 +\newcommand{\SPIDliftMaIntegrationItemTwoZeroThreecontrol}{2}
326 +\newcommand{\SPIDpTypeGivenItemPartnershipItemEightZeroOnecontrol}{1.7}
327 +\newcommand{\SPIDpItemGivenTypePartnershipItemEightZeroOnecontrol}{34.9}
328 +\newcommand{\SPIDliftPartnershipItemEightZeroOnecontrol}{2}
329 +\newcommand{\SPIDcohortIssuers}{1{,}389}
330 +\newcommand{\SPIDcohortMentionsPerIssuerFirst}{9.6}
331 +\newcommand{\SPIDcohortMentionsPerIssuerLast}{8.8}
332 +\newcommand{\SPIDcohortFirstSeenPerIssuerFirst}{4.7}
333 +\newcommand{\SPIDcohortFirstSeenPerIssuerLast}{2.8}
334 +\newcommand{\SPIDcohortFirstSeenFirst}{6{,}533}
335 +\newcommand{\SPIDcohortFirstSeenLast}{3{,}926}
336 +\newcommand{\SPIDepisodesKThree}{131{,}823}
337 +\newcommand{\SPIDepisodesKFive}{126{,}318}
338 +\newcommand{\SPIDnewProjectsPerIssuerFilingFirstYear}{5.6}
339 +\newcommand{\SPIDnewProjectsPerIssuerFilingLastFullYear}{3.3}
340 +\newcommand{\SPIDnewProjectsPerIssuerFirstYear}{6.4}
341 +\newcommand{\SPIDnewProjectsPerIssuerLastFullYear}{3.5}
342 +\newcommand{\SPIDfocusRecallRecoveredPct}{26.2}
343 +\newcommand{\SPIDfocusRecallRecoveredOneZeroKPct}{25.0}
344 +\newcommand{\SPIDfocusRecallRecoveredOneZeroQPct}{24.9}
345 +\newcommand{\SPIDfocusRecallRecoveredEightKPct}{84.2}
346 +\newcommand{\SPIDrulesGivenLlmPct}{85.7}
347 +\newcommand{\SPIDllmGivenRulesPct}{32.5}
348 +\newcommand{\SPIDrulesLlmAgreementPct}{71.2}
349 +\newcommand{\SPIDrulesLlmTypeOverlapPct}{84.6}
350 +\newcommand{\SPIDrulesSampleN}{60{,}000}
147 351 \newcommand{\SPIDcallsTotal}{703{,}725}
148 352 \newcommand{\SPIDgatePassSections}{703{,}737}
149 353 \newcommand{\SPIDgateRejectedSections}{419{,}361}
@@ -155,9 +359,11 @@
155 359 \newcommand{\SPIDoutageHours}{5.3}
156 360 \newcommand{\SPIDoctoberEffectiveHours}{8.4}
157 361 \newcommand{\SPIDoctoberRowsPerSecondEffective}{31.9}
362 +\newcommand{\SPIDoctoberRowsPerSecondWallClock}{19.7}
158 363 \newcommand{\SPIDoctoberCallsPerSecondEffective}{20.1}
159 364 \newcommand{\SPIDoctoberFirstFlush}{2026-10-27 21:35}
160 365 \newcommand{\SPIDoctoberLastFlush}{2026-10-28 11:15}
366 +\newcommand{\SPIDpaperRateImpliedByTwelveHours}{22.4}
161 367 \newcommand{\SPIDbackfilledRows}{154{,}964}
162 368 \newcommand{\SPIDjuneLogSections}{153{,}894}
163 369 \newcommand{\SPIDbackfilledUnderThirtyWords}{1{,}070}
@@ -168,10 +374,14 @@
168 374 \newcommand{\SPIDoutageWindowEnd}{2026-10-28 06:22}
169 375 \newcommand{\SPIDllmCallFailedTotal}{94{,}609}
170 376 \newcommand{\SPIDllmCallFailedInsideOutage}{94{,}467}
171 −\newcommand{\SPIDllmCallFailedOutsideOutage}{142}
377 +\newcommand{\SPIDllmCallFailedOutsideOutage}{14}
378 +\newcommand{\SPIDllmRetryableTailLines}{128}
172 379 \newcommand{\SPIDllmFailedJsonDecodeError}{14}
173 380 \newcommand{\SPIDllmFailedRetryableHttpFourTwoNineFivexx}{94{,}593}
174 381 \newcommand{\SPIDllmFailedConnectionError}{2}
382 +\newcommand{\SPIDoutageLogWindowStart}{2026-10-28 01:10}
383 +\newcommand{\SPIDoutageLogWindowEnd}{2026-10-28 06:22}
384 +\newcommand{\SPIDoutageRowsRemoved}{149{,}352}
175 385 \newcommand{\SPIDjuneLlmCallFailed}{3}
176 386 \newcommand{\SPIDcollisionSections}{304}
177 387 \newcommand{\SPIDcollisionMentions}{412}
@@ -186,24 +396,437 @@
186 396 \newcommand{\SPIDprojectsTieDistinctNames}{20{,}118}
187 397 \newcommand{\SPIDprojectsStatusTie}{972}
188 398 \newcommand{\SPIDmentionsAtConfidenceOne}{108{,}023}
189 −\newcommand{\SPIDprojectCountRangeKeys}{21{,}027--308{,}065}
190 −\newcommand{\SPIDprojectCountRangeKeysN}{9}
191 −\newcommand{\SPIDprojectCountRangeAll}{16{,}562--308{,}065}
192 −\newcommand{\SPIDprojectCountCurrentKey}{121{,}099}
193 −\newcommand{\SPIDtopNameTokens}{\texttt{acquisition} (3.4\%), \texttt{share} (3.1\%), \texttt{expansion} (1.8\%), \texttt{stock} (1.7\%), \texttt{investment} (1.6\%), \texttt{merger} (1.3\%), \texttt{sale} (1.3\%), \texttt{development} (1.2\%), \texttt{strategic} (0.9\%), \texttt{capital} (0.8\%)}
194 −\newcommand{\SPIDtopNameTokensProjectsPct}{17.2}
399 +\newcommand{\SPIDrebuiltNamesDiffer}{394}
400 +\newcommand{\SPIDrebuiltDescriptionsDiffer}{600}
401 +\newcommand{\SPIDannotationFrameProductive}{1{,}677}
402 +\newcommand{\SPIDannotationFrameZero}{385}
403 +\newcommand{\SPIDannotationStrata}{192}
404 +\newcommand{\SPIDannotationHalfWidthPrecision}{4.4}
405 +\newcommand{\SPIDannotationMdeGateRecall}{7.8}
406 +\newcommand{\SPIDannotationCoreProductive}{510}
407 +\newcommand{\SPIDannotationDev}{1{,}058}
408 +\newcommand{\SPIDannotationHoldout}{1{,}004}
409 +\newcommand{\SPIDfullBodyFilings}{1{,}230}
410 +\newcommand{\SPIDlegacyRows}{27{,}164}
411 +\newcommand{\SPIDlegacyAccessions}{7{,}368}
412 +\newcommand{\SPIDfiscalYearNullMentions}{68{,}827}
413 +\newcommand{\SPIDoutageLargestGapStart}{01:25}
414 +\newcommand{\SPIDoutageLargestGapEnd}{06:40}
415 +\newcommand{\SPIDoutageZeroBatchRange}{47--60}
416 +\newcommand{\SPIDoutageZeroBatchWindow}{01:44--06:05}
417 +\newcommand{\SPIDresumeBatchMentions}{34}
418 +\newcommand{\SPIDresumeBatchWindow}{06:38--06:40}
419 +\newcommand{\SPIDlogExtractionCompleteSum}{1{,}117{,}479}
420 +\newcommand{\SPIDlogPendingSecondStart}{968{,}127}
421 +\newcommand{\SPIDjsonFailBeforeOutage}{nine}
422 +\newcommand{\SPIDjsonFailAfterOutage}{five}
423 +\newcommand{\SPIDworkers}{48}
424 +\newcommand{\SPIDoutageSurvivingRows}{504}
425 +\newcommand{\SPIDoutageSurvivingMentions}{1{,}011}
426 +\newcommand{\SPIDbackfillTimestamp}{October~27, 2026, 13:12}
427 +\newcommand{\SPIDresumeBatchExpectedProductive}{536}
428 +\newcommand{\SPIDresumeBatchZeroSharePct}{99.2}
429 +\newcommand{\SPIDjuneCalls}{95{,}286}
430 +\newcommand{\SPIDjuneProductiveShareCalls}{25.6}
431 +\newcommand{\SPIDoctoberProductiveShareCalls}{23.6}
432 +\newcommand{\SPIDgateRejectedPct}{37.3}
433 +\newcommand{\SPIDusdPerOctoberRow}{0.0008}
434 +\newcommand{\SPIDconfExactDefault}{3{,}278}
435 +\newcommand{\SPIDconfExactDefaultOctober}{2{,}974}
436 +\newcommand{\SPIDconfExactDefaultJune}{304}
437 +\newcommand{\SPIDledgerBackendValue}{llm}
438 +\newcommand{\SPIDamountNegative}{24}
439 +\newcommand{\SPIDamountZero}{584}
440 +\newcommand{\SPIDamountMaxSci}{1.0 \times 10^{12}}
441 +\newcommand{\SPIDamountGeFiftyBMentions}{161}
442 +\newcommand{\SPIDamountGeFiftyBProjects}{104}
443 +\newcommand{\SPIDamountTopNumberFound}{191}
444 +\newcommand{\SPIDamountTopCurrencyFound}{178}
445 +\newcommand{\SPIDamountTopN}{200}
446 +\newcommand{\SPIDamountNonUsdTokenN}{1{,}837}
447 +\newcommand{\SPIDamountLocatedN}{112{,}692}
448 +\newcommand{\SPIDamountNonUsdTokenPct}{1.6}
449 +\newcommand{\SPIDgroundBootstrapReps}{1{,}000}
450 +\newcommand{\SPIDgroundYearsPct}{99.8}
451 +\newcommand{\SPIDgroundPartnersPct}{99.4}
452 +\newcommand{\SPIDgroundAmountNumberPct}{93.7}
453 +\newcommand{\SPIDgroundAmountCurrencyPct}{80.5}
454 +\newcommand{\SPIDgroundLocationsPct}{78.3}
455 +\newcommand{\SPIDgroundTechPct}{63.6}
456 +\newcommand{\SPIDgroundYearsCiLow}{99.7}
457 +\newcommand{\SPIDgroundYearsCiHigh}{99.8}
458 +\newcommand{\SPIDgroundLocationsTenK}{85.7}
459 +\newcommand{\SPIDgroundLocationsTenQ}{82.1}
460 +\newcommand{\SPIDgroundLocationsEightK}{67.8}
461 +\newcommand{\SPIDgroundElemPartners}{99.6}
462 +\newcommand{\SPIDgroundElemLocations}{84.2}
463 +\newcommand{\SPIDgroundElemTech}{70.6}
464 +\newcommand{\SPIDgroundElemYears}{99.7}
465 +\newcommand{\SPIDgroundAllPct}{88.2}
466 +\newcommand{\SPIDgroundAllN}{276{,}168}
467 +\newcommand{\SPIDgroundAllTenK}{92.2}
468 +\newcommand{\SPIDgroundAllTenQ}{92.4}
469 +\newcommand{\SPIDgroundAllEightK}{76.6}
470 +\newcommand{\SPIDgroundAllJune}{84.5}
471 +\newcommand{\SPIDgroundAllOctober}{88.7}
472 +\newcommand{\SPIDgroundAllTopBin}{86.4}
473 +\newcommand{\SPIDgroundAllLowerBinsRange}{90.7--94.2}
474 +\newcommand{\SPIDyearsAbsentFromText}{604}
475 +\newcommand{\SPIDtypeSignalMaPct}{79.8}
476 +\newcommand{\SPIDtypeSignalTechDeployPct}{5.4}
477 +\newcommand{\SPIDtechRegexEqualPct}{46}
478 +\newcommand{\SPIDtechDeployMentionedN}{124}
479 +\newcommand{\SPIDmentionsKeyedLocation}{118{,}783}
480 +\newcommand{\SPIDmentionsKeyedNameToken}{187{,}212}
481 +\newcommand{\SPIDmentionsKeyedNameTokenPct}{60.8}
482 +\newcommand{\SPIDmentionsKeyedLocationPct}{38.6}
483 +\newcommand{\SPIDlocationKeysCountry}{8{,}126}
484 +\newcommand{\SPIDlocationKeysUsState}{6{,}110}
485 +\newcommand{\SPIDlocationKeysCountryStatePct}{26}
486 +\newcommand{\SPIDmaAmountOtherCounterpartyN}{1{,}630}
487 +\newcommand{\SPIDmaAmountOtherCounterpartyDenom}{12{,}372}
488 +\newcommand{\SPIDamountOtherCounterpartyN}{2{,}347}
489 +\newcommand{\SPIDamountOtherCounterpartyDenom}{21{,}908}
490 +\newcommand{\SPIDtopTokenMentions}{40{,}407}
491 +\newcommand{\SPIDtopTokenProjects}{2{,}256}
492 +\newcommand{\SPIDtopTokenSharePct}{21.4}
493 +\newcommand{\SPIDlocationKeyUnitedStatesProjects}{2{,}551}
494 +\newcommand{\SPIDprojectsKeyCikType}{21{,}027}
495 +\newcommand{\SPIDprojectsKeyTypeDropped}{96{,}749}
496 +\newcommand{\SPIDprojectsKeyNameOnly}{114{,}244}
497 +\newcommand{\SPIDprojectsKeyCityNorm}{123{,}246}
498 +\newcommand{\SPIDprojectsKeyStopwords}{130{,}101}
499 +\newcommand{\SPIDprojectsKeyTwoTokens}{145{,}697}
500 +\newcommand{\SPIDprojectsKeyStrict}{198{,}488}
501 +\newcommand{\SPIDprojectsKeyMentionLevel}{308{,}065}
502 +\newcommand{\SPIDprojectsCurrentKeyAtNine}{83{,}483}
503 +\newcommand{\SPIDsingleMentionShareStrict}{75.8}
504 +\newcommand{\SPIDsingleMentionShareCikType}{20.7}
505 +\newcommand{\SPIDchenierClusterCurrent}{8}
506 +\newcommand{\SPIDchenierClusterStrict}{1}
507 +\newcommand{\SPIDchenierClusterNameOnly}{40}
508 +\newcommand{\SPIDchenierClusterCikType}{176}
509 +\newcommand{\SPIDmaGeThreeNamesOverTenPct}{91.7}
510 +\newcommand{\SPIDmaGeThreePartnersPct}{10.9}
511 +\newcommand{\SPIDprojectsTieDistinctDescriptions}{29{,}954}
512 +\newcommand{\SPIDrebuiltNameDiff}{394}
513 +\newcommand{\SPIDrebuiltDescDiff}{600}
514 +\newcommand{\SPIDtiebreakNameDiff}{11{,}484}
515 +\newcommand{\SPIDtiebreakStatusDiff}{503}
516 +\newcommand{\SPIDtiebreakDescDiff}{18{,}256}
517 +\newcommand{\SPIDjuneProjects}{19{,}227}
518 +\newcommand{\SPIDspMentions}{70{,}367}
519 +\newcommand{\SPIDspProjects}{27{,}766}
520 +\newcommand{\SPIDspProjectsJuneOnly}{15{,}910}
521 +\newcommand{\SPIDspProjectsBothRuns}{3{,}317}
522 +\newcommand{\SPIDspProjectsOctoberOnly}{8{,}539}
523 +\newcommand{\SPIDoctoberSpTenQSections}{116{,}231}
524 +\newcommand{\SPIDoctoberSpTenQFilings}{19{,}399}
525 +\newcommand{\SPIDoctoberSpTenQMentions}{28{,}963}
526 +\newcommand{\SPIDoctoberSpTenKMentions}{910}
527 +\newcommand{\SPIDoctoberSpEightKMentions}{564}
528 +\newcommand{\SPIDjuneTenQMentions}{5{,}817}
529 +\newcommand{\SPIDjuneTenQFilings}{3{,}710}
530 +\newcommand{\SPIDjuneTenQSections}{23{,}873}
531 +\newcommand{\SPIDrepoCommits}{six}
532 +\newcommand{\SPIDextractorMtimeDate}{June~17, 2026}
533 +\newcommand{\SPIDdiffStoreLines}{$+3/-1$}
534 +\newcommand{\SPIDdiffParserLines}{$+13/-7$}
535 +\newcommand{\SPIDlegacyTenKRows}{27{,}164}
536 +\newcommand{\SPIDlegacyTenKFilings}{7{,}368}
537 +\newcommand{\SPIDsegPairs}{25{,}673}
538 +\newcommand{\SPIDfullBodyMedianWords}{44{,}514}
539 +\newcommand{\SPIDfullBodyWithParsedItems}{1{,}117}
540 +\newcommand{\SPIDfullBodyUnsubmittedSections}{5{,}385}
541 +\newcommand{\SPIDfullDocumentTenK}{86}
542 +\newcommand{\SPIDfullDocumentTenKLegacy}{51}
543 +\newcommand{\SPIDfullDocumentTenKInvisible}{35}
544 +\newcommand{\SPIDfullDocumentTenQ}{243}
545 +\newcommand{\SPIDfullDocumentTenQLedgered}{241}
546 +\newcommand{\SPIDfullBodyYield}{0.67}
547 +\newcommand{\SPIDfullBodyProductivePct}{25.7}
548 +\newcommand{\SPIDtenKparsedRows}{341{,}207}
549 +\newcommand{\SPIDtenKoutOfScopeRows}{188{,}518}
550 +\newcommand{\SPIDtenKlegacyAccessionRows}{35{,}037}
551 +\newcommand{\SPIDtenKunderThirtyRows}{1{,}112}
552 +\newcommand{\SPIDtenKparsedLedgered}{116{,}540}
553 +\newcommand{\SPIDlegacyShareTenKLedgerPct}{19}
554 +\newcommand{\SPIDlegacyMdnaDollar}{141}
555 +\newcommand{\SPIDparsedMdnaDollar}{272}
556 +\newcommand{\SPIDlegacyMdnaWords}{9{,}921}
557 +\newcommand{\SPIDparsedMdnaWords}{11{,}661}
558 +\newcommand{\SPIDlegacyFewerMoneyPct}{92.3}
559 +\newcommand{\SPIDlegacyMdnaNumeric}{596}
560 +\newcommand{\SPIDparsedMdnaNumeric}{1{,}177}
561 +\newcommand{\SPIDpropertiesLtHalfPct}{19.4}
562 +\newcommand{\SPIDwithinProductiveJune}{12.4}
563 +\newcommand{\SPIDwithinMentionsPerRowJune}{0.244}
564 +\newcommand{\SPIDwithinProductiveOctober}{12.7}
565 +\newcommand{\SPIDwithinMentionsPerRowOctober}{0.250}
566 +\newcommand{\SPIDwithinConfJune}{0.889}
567 +\newcommand{\SPIDwithinConfOctober}{0.893}
568 +\newcommand{\SPIDwithinMaShareJune}{49.9}
569 +\newcommand{\SPIDwithinMaShareOctober}{45.7}
570 +\newcommand{\SPIDpairedIssuers}{81}
571 +\newcommand{\SPIDpairedDeltaPp}{0.6}
572 +\newcommand{\SPIDpairedSePp}{1.3}
573 +\newcommand{\SPIDcohortBothPerIssuerAll}{55.8}
574 +\newcommand{\SPIDcohortRussellOnlyPerIssuer}{46.9}
575 +\newcommand{\SPIDcohortBothPerIssuerOctober}{25.1}
576 +\newcommand{\SPIDcohortOlsAll}{8.84}
577 +\newcommand{\SPIDcohortOlsAllSe}{1.62}
578 +\newcommand{\SPIDcohortOlsOctober}{-22.98}
579 +\newcommand{\SPIDcohortOlsOctoberSe}{1.20}
580 +\newcommand{\SPIDcohortOlsControlled}{-0.28}
581 +\newcommand{\SPIDcohortOlsControlledSe}{1.52}
582 +\newcommand{\SPIDcohortOlsN}{2{,}499}
583 +\newcommand{\SPIDfiscalYearNullOctTenK}{823}
584 +\newcommand{\SPIDfiscalYearNullOctTenQ}{28{,}074}
585 +\newcommand{\SPIDfiscalYearNullFilings}{134{,}124}
586 +\newcommand{\SPIDfiscalYearFillAccessions}{31{,}976}
587 +\newcommand{\SPIDfocusOverBudgetSections}{326{,}095}
588 +\newcommand{\SPIDfocusOverBudgetSectionsPct}{29}
589 +\newcommand{\SPIDfocusOverBudgetCalls}{324{,}386}
590 +\newcommand{\SPIDfocusOverBudgetCallsPct}{46}
591 +\newcommand{\SPIDfocusMeanShownOverBudgetPct}{15.9}
592 +\newcommand{\SPIDmdnaN}{28{,}919}
593 +\newcommand{\SPIDmdnaMedianWords}{9{,}905}
594 +\newcommand{\SPIDmdnaMedianChars}{64{,}194}
595 +\newcommand{\SPIDmdnaShownMedianPct}{9.3}
596 +\newcommand{\SPIDmdnaLastShownMedianPct}{16}
597 +\newcommand{\SPIDmdnaShownLtTwentyFivePct}{90.5}
598 +\newcommand{\SPIDmsgTruncatedN}{0}
599 +\newcommand{\SPIDmentionsFromLtTwentyFive}{193{,}416}
600 +\newcommand{\SPIDmentionsFromLtTwentyFivePct}{62.7}
601 +\newcommand{\SPIDmdnaShownPTenPct}{4.3}
602 +\newcommand{\SPIDmdnaShownPNinetyPct}{24}
603 +\newcommand{\SPIDmdnaHitsShownMedianPct}{15.6}
604 +\newcommand{\SPIDbusinessShownMedianPct}{15.7}
605 +\newcommand{\SPIDriskShownMedianPct}{10.1}
606 +\newcommand{\SPIDtenQmdnaShownMedianPct}{13.2}
607 +\newcommand{\SPIDtenQfinShownMedianPct}{10.6}
608 +\newcommand{\SPIDcapexVocabShownMdnaPct}{5.8}
609 +\newcommand{\SPIDcapexVocabShownBusinessPct}{10.0}
610 +\newcommand{\SPIDcapexVocabShownTenQmdnaPct}{8.3}
611 +\newcommand{\SPIDeightKWholePct}{91}
612 +\newcommand{\SPIDmentionsFromLtTwentyFiveTenK}{84}
613 +\newcommand{\SPIDmentionsFromLtTwentyFiveTenQ}{79}
614 +\newcommand{\SPIDmentionsFromLtTwentyFiveEightK}{6}
615 +\newcommand{\SPIDplateauLow}{0.4}
616 +\newcommand{\SPIDplateauHigh}{1.5}
617 +\newcommand{\SPIDplateauRange}{1.2--1.6}
618 +\newcommand{\SPIDplateauKchars}{20{,}000}
619 +\newcommand{\SPIDmentionsPerTenKShownChars}{2.5}
620 +\newcommand{\SPIDshortMdnaN}{169}
621 +\newcommand{\SPIDshortMdnaDenom}{29{,}088}
622 +\newcommand{\SPIDshortMdnaPct}{0.6}
623 +\newcommand{\SPIDshortMdnaIncorporatedN}{430}
624 +\newcommand{\SPIDrulesFocusRecovered}{84{,}841}
625 +\newcommand{\SPIDrulesFocusTotal}{324{,}237}
626 +\newcommand{\SPIDrulesFocusRecoveredPct}{26.2}
627 +\newcommand{\SPIDrulesFocusBusinessPct}{36.9}
628 +\newcommand{\SPIDrulesFocusMdnaPct}{20.8}
629 +\newcommand{\SPIDrulesFocusTenQmdnaPct}{25.1}
630 +\newcommand{\SPIDrulesFocusEightKPct}{84.2}
631 +\newcommand{\SPIDrulesSampleProductive}{30{,}000}
632 +\newcommand{\SPIDrulesSampleZero}{30{,}000}
633 +\newcommand{\SPIDrulesFlagPct}{39.5}
634 +\newcommand{\SPIDrulesAgreementPct}{71.2}
635 +\newcommand{\SPIDrulesLlmOnlyPct}{2.1}
636 +\newcommand{\SPIDrulesOnlyPct}{26.6}
637 +\newcommand{\SPIDrulesTypeOverlapPct}{84.6}
638 +\newcommand{\SPIDrulesGivenLlmTenK}{97.4}
639 +\newcommand{\SPIDrulesGivenLlmTenQ}{94.4}
640 +\newcommand{\SPIDrulesGivenLlmEightK}{69.2}
641 +\newcommand{\SPIDrulesGivenLlmJune}{79.8}
642 +\newcommand{\SPIDrulesGivenLlmOctober}{86.7}
643 +\newcommand{\SPIDrulesTypeMa}{96.8}
644 +\newcommand{\SPIDrulesTypeGeo}{36.5}
645 +\newcommand{\SPIDrulesTypeCapex}{55.2}
646 +\newcommand{\SPIDrulesTypePlant}{40.7}
647 +\newcommand{\SPIDrulesTypeDrug}{92.5}
648 +\newcommand{\SPIDrulesTypeCost}{76.9}
649 +\newcommand{\SPIDfinMentions}{22{,}412}
650 +\newcommand{\SPIDfinMentionsPct}{7.3}
651 +\newcommand{\SPIDfinAmountB}{17.8}
652 +\newcommand{\SPIDfinAmountDenomB}{104.2}
653 +\newcommand{\SPIDfinAmountSharePct}{17.1}
654 +\newcommand{\SPIDfinUnregPct}{54.5}
655 +\newcommand{\SPIDfinUnregN}{5{,}179}
656 +\newcommand{\SPIDfinUnregDenom}{9{,}506}
657 +\newcommand{\SPIDfinFinStatementsPct}{2.4}
658 +\newcommand{\SPIDfinControlsPct}{0.2}
659 +\newcommand{\SPIDfinProjectsRep}{12{,}027}
660 +\newcommand{\SPIDfinProjectsRepPct}{9.9}
661 +\newcommand{\SPIDfinProjectsAny}{13{,}139}
662 +\newcommand{\SPIDitemTwoPairs}{77{,}869}
663 +\newcommand{\SPIDunregMedianWords}{602}
664 +\newcommand{\SPIDtenQmdnaMedianWords}{7{,}573}
665 +\newcommand{\SPIDunregGtThreeK}{1{,}001}
666 +\newcommand{\SPIDunregGtThreeKPct}{1.3}
667 +\newcommand{\SPIDswapCandidates}{296}
668 +\newcommand{\SPIDunregLongThreshold}{3{,}000}
669 +\newcommand{\SPIDunregGtThreeKMentions}{425}
670 +\newcommand{\SPIDfinEightKPct}{19.2}
671 +\newcommand{\SPIDfinMaPct}{7.0}
672 +\newcommand{\SPIDfinCapexPct}{52.6}
673 +\newcommand{\SPIDfinCostPct}{16.4}
674 +\newcommand{\SPIDfinTermRepurchase}{10{,}886}
675 +\newcommand{\SPIDfinTermSeniorNotes}{3{,}375}
676 +\newcommand{\SPIDfinTermTermLoan}{2{,}263}
677 +\newcommand{\SPIDcapexProjectsExcl}{4{,}725}
678 +\newcommand{\SPIDcostProjectsExcl}{5{,}403}
679 +\newcommand{\SPIDmaProjectsExcl}{37{,}527}
680 +\newcommand{\SPIDcapexShareExcl}{4.3}
681 +\newcommand{\SPIDeightKItemCodePct}{99.7}
682 +\newcommand{\SPIDbenchMaGivenTwoOhOne}{0.911}
683 +\newcommand{\SPIDbenchMaGivenTwoOhOneCiLow}{0.903}
684 +\newcommand{\SPIDbenchMaGivenTwoOhOneCiHigh}{0.918}
685 +\newcommand{\SPIDbenchTwoOhOneN}{5{,}456}
686 +\newcommand{\SPIDbenchMaBase}{0.095}
687 +\newcommand{\SPIDbenchMaGivenEightOhOne}{0.199}
688 +\newcommand{\SPIDbenchMaGivenFiveOhTwo}{0.031}
689 +\newcommand{\SPIDbenchItemsGivenMa}{0.467}
690 +\newcommand{\SPIDbenchCostGivenTwoOhFive}{0.709}
691 +\newcommand{\SPIDbenchCostGivenTwoOhFiveCiLow}{0.687}
692 +\newcommand{\SPIDbenchCostGivenTwoOhFiveCiHigh}{0.730}
693 +\newcommand{\SPIDbenchTwoOhFiveN}{1{,}700}
694 +\newcommand{\SPIDbenchCostLift}{92}
695 +\newcommand{\SPIDbenchTwoOhFiveGivenCost}{0.392}
696 +\newcommand{\SPIDbenchPartnershipGivenOneOhOne}{0.040}
697 +\newcommand{\SPIDbenchPartnershipBase}{0.011}
698 +\newcommand{\SPIDannSeed}{20261105}
699 +\newcommand{\SPIDannStrata}{192}
700 +\newcommand{\SPIDannNProductive}{1{,}677}
701 +\newcommand{\SPIDannNZero}{385}
702 +\newcommand{\SPIDannZeroGatePass}{285}
703 +\newcommand{\SPIDannZeroGateReject}{100}
704 +\newcommand{\SPIDannDeffProductive}{3.4}
705 +\newcommand{\SPIDannDeffZero}{1.2}
706 +\newcommand{\SPIDannHalfWidthPrecision}{4.4}
707 +\newcommand{\SPIDannMde}{7.8}
708 +\newcommand{\SPIDannFloor}{10}
709 +\newcommand{\SPIDannOversample}{2}
710 +\newcommand{\SPIDannPopProductive}{168{,}230}
711 +\newcommand{\SPIDannPopZero}{954{,}868}
712 +\newcommand{\SPIDannHalfWidthFn}{2.4}
713 +\newcommand{\SPIDannCore}{510}
714 +\newcommand{\SPIDannDev}{1{,}058}
715 +\newcommand{\SPIDannHoldout}{1{,}004}
716 +\newcommand{\SPIDannTextChars}{2{,}000}
717 +\newcommand{\SPIDannFrameMb}{77}
718 +\newcommand{\SPIDfirstSeenLastYear}{6{,}694}
719 +\newcommand{\SPIDfixedCohortIssuers}{1{,}389}
720 +\newcommand{\SPIDfixedCohortMentionsPerIssuerFirst}{9.6}
721 +\newcommand{\SPIDfixedCohortMentionsPerIssuerLast}{8.8}
722 +\newcommand{\SPIDfixedCohortNewPerIssuerFirst}{4.7}
723 +\newcommand{\SPIDfixedCohortNewPerIssuerLast}{2.8}
724 +\newcommand{\SPIDfixedCohortFirstSeenFirst}{6{,}533}
725 +\newcommand{\SPIDfixedCohortFirstSeenLast}{3{,}926}
726 +\newcommand{\SPIDepisodesKthree}{131{,}823}
727 +\newcommand{\SPIDepisodesKfive}{126{,}318}
728 +\newcommand{\SPIDdualClassCiks}{18}
729 +\newcommand{\SPIDuniverseBoth}{491}
730 +\newcommand{\SPIDuniverseSpOnly}{9}
731 +\newcommand{\SPIDuniverseRuOnly}{2{,}064}
732 +\newcommand{\SPIDrussellGapMax}{441}
733 +\newcommand{\SPIDrussellGapMaxPct}{14.7}
734 +\newcommand{\SPIDfactsheetDate}{September~30, 2026}
735 +\newcommand{\SPIDiwvHoldingsDate}{October~23, 2026}
736 +\newcommand{\SPIDiwvFetchDate}{October~27, 2026}
737 +\newcommand{\SPIDspWikipediaRows}{503}
738 +\newcommand{\SPIDspWikipediaDate}{May~25, 2026}
739 +\newcommand{\SPIDtickerMapSize}{10{,}430}
740 +\newcommand{\SPIDissuersFilingsNoProject}{7}
741 +\newcommand{\SPIDparseErrors}{14}
742 +\newcommand{\SPIDfilingsNotParsedPct}{0.003}
743 +\newcommand{\SPIDspidDbGb}{3.2}
744 +\newcommand{\SPIDcorpusDbGb}{68}
745 +\newcommand{\SPIDcorpusParquetGb}{29.1}
746 +\newcommand{\SPIDrequirementsLockPackages}{88}
747 +\newcommand{\SPIDpythonVersion}{3.12.15}
748 +\newcommand{\SPIDduckdbVersion}{2.0.0}
749 +\newcommand{\SPIDtestsN}{22}
750 +\newcommand{\SPIDsnapshotFilesN}{nine}
751 +\newcommand{\SPIDannualPanelRows}{32{,}852}
752 +\newcommand{\SPIDquarterlyPanelRows}{128{,}043}
753 +\newcommand{\SPIDmentionsPerProjectDrug}{4.99}
754 +\newcommand{\SPIDmentionsPerProjectTechDeploy}{1.63}
755 +\newcommand{\SPIDnCostReduction}{6{,}481}
756 +\newcommand{\SPIDamountPTwentyFiveMusd}{23}
757 +\newcommand{\SPIDspanZeroN}{67{,}170}
758 +\newcommand{\SPIDconfShareHalf}{0.5}
759 +\newcommand{\SPIDkgEdgesOwns}{121{,}099}
760 +\newcommand{\SPIDkgEdgesLocatedIn}{54{,}583}
761 +\newcommand{\SPIDkgEdgesUses}{28{,}774}
762 +\newcommand{\SPIDprojectsPerIssuerMax}{240}
763 +\newcommand{\SPIDfocusWindowBefore}{220}
764 +\newcommand{\SPIDfocusWindowAfter}{380}
765 +\newcommand{\SPIDfocusEmitBudget}{9{,}000}
766 +\newcommand{\SPIDfocusCollectBudget}{12{,}600}
767 +\newcommand{\SPIDuserMessageCap}{14{,}000}
768 +\newcommand{\SPIDconfDefault}{0.6}
769 +\newcommand{\SPIDconfThreshold}{0.45}
770 +\newcommand{\SPIDcompletionTokens}{2{,}000}
771 +\newcommand{\SPIDlistItemsMax}{eight}
772 +\newcommand{\SPIDlistItemChars}{120}
773 +\newcommand{\SPIDidNameChars}{40}
774 +\newcommand{\SPIDretries}{three}
775 +\newcommand{\SPIDtimeoutSeconds}{120}
776 +\newcommand{\SPIDminWords}{30}
777 +\newcommand{\SPIDchunkWords}{512}
778 +\newcommand{\SPIDchunkOverlap}{64}
779 +\newcommand{\SPIDmaxFileMb}{50}
780 +\newcommand{\SPIDcooldownSeconds}{65}
781 +\newcommand{\SPIDsecRateLimit}{ten}
782 +\newcommand{\SPIDacqGatewayDivisor}{nine}
783 +\newcommand{\SPIDacqNewDocs}{about 400{,}000}
784 +\newcommand{\SPIDacqHours}{seven}
785 +\newcommand{\SPIDacqReqPerSec}{17}
786 +\newcommand{\SPIDacqNodes}{ten}
787 +\newcommand{\SPIDacqNodeRate}{0.9}
788 +\newcommand{\SPIDacqGatewayRate}{one}
789 +\newcommand{\SPIDparseFilingsPerSec}{100}
790 +\newcommand{\SPIDparseMinutesRange}{five to thirteen}
791 +\newcommand{\SPIDembedMinutesRange}{15--40}
792 +\newcommand{\SPIDmergeMinutes}{seven}
793 +\newcommand{\SPIDtotalCostUsd}{775}
794 +\newcommand{\SPIDstabilitySections}{500}
795 +\newcommand{\SPIDstabilityCalls}{about 2{,}500}
796 +\newcommand{\SPIDembeddingDim}{384}
797 +\newcommand{\SPIDfactorAnchors}{8}
798 +\newcommand{\SPIDtenKsectionsMax}{fourteen}
799 +\newcommand{\SPIDtenQsectionsN}{seven}
195 800 \newcommand{\SPIDprojects}{121{,}099}
196 801 \newcommand{\SPIDmentions}{308{,}065}
197 802 \newcommand{\SPIDissuersWithProjects}{2{,}492}
198 803 \newcommand{\SPIDissuersWithFilings}{2{,}499}
804 +\newcommand{\SPIDissuersWithoutFilings}{65}
199 805 \newcommand{\SPIDsectionsTotal}{1{,}342{,}283}
200 806 \newcommand{\SPIDchunks}{10{,}720{,}890}
201 807 \newcommand{\SPIDprojectsWithLocation}{54{,}583}
202 808 \newcommand{\SPIDprojectsTokenKeyedShare}{54.9}
203 809 \newcommand{\SPIDprojectsPerIssuerMean}{48.6}
204 810 \newcommand{\SPIDprojectsPerIssuerMedian}{42}
811 +\newcommand{\SPIDmentionsPerProject}{2.54}
205 812 \newcommand{\SPIDextractedAtFirst}{2026-10-27 13:12:32}
206 813 \newcommand{\SPIDextractedAtLast}{2026-10-28 11:15:49}
814 +\newcommand{\SPIDtenKmdnaMedianWords}{9{,}905}
815 +\newcommand{\SPIDannualPanelFirms}{2{,}499}
816 +\newcommand{\SPIDspFiveHundredCiks}{500}
817 +\newcommand{\SPIDrunSpFiveZeroZeroRunLog}{project-db/logs/extract.log}
818 +\newcommand{\SPIDrunSpFiveZeroZeroRunWorkers}{16}
819 +\newcommand{\SPIDrunSpFiveZeroZeroRunBatch}{15}
820 +\newcommand{\SPIDrunSpFiveZeroZeroRunCiks}{500}
821 +\newcommand{\SPIDrunSpFiveZeroZeroRunSectionsLogged}{153894}
822 +\newcommand{\SPIDrunSpFiveZeroZeroRunLedgerRowsBackfilled}{154964}
823 +\newcommand{\SPIDrunSpFiveZeroZeroRunMentionsBackfilled}{39930}
824 +\newcommand{\SPIDrunSpFiveZeroZeroRunLlmCallFailed}{3}
825 +\newcommand{\SPIDrunRussellRunLog}{data/logs/spid\_extract.log}
826 +\newcommand{\SPIDrunRussellRunWorkers}{24}
827 +\newcommand{\SPIDrunRussellRunLedgerRows}{968134}
828 +\newcommand{\SPIDrunRussellRunExtractedAtFirst}{2026-10-27 13:12:32.140400}
829 +\newcommand{\SPIDrunRussellRunExtractedAtLast}{2026-10-28 11:15:49.150818}
830 +\newcommand{\SPIDrunRussellRunLlmCallFailed}{94609}
831 +\newcommand{\SPIDrunRussellRunSectionFailed}{0}
207 832 \newcommand{\SPIDbrief}{the research-design brief, i.e. the specification of required tables, keys and validation gates against which \texttt{docs/implementation\_audit.md} audits the build}
208 −\newcommand{\SPIDnewProjectsPerIssuerFirstYear}{6.4}
209 −\newcommand{\SPIDnewProjectsPerIssuerLastFullYear}{3.5}
modified paper/tables/prompt_verbatim.tex +3 −2
@@ -1,4 +1,5 @@
1 −\begin{verbatim}
1 +% Generated by code/make_tables.py from code/audit/spid_snapshot/llm.py (_SYSTEM) and taxonomy.py (PROJECT_TYPES), substituted as llm.py does.
2 +{\footnotesize\begin{verbatim}
2 3 You are a financial analyst extracting CORPORATE PROJECTS from SEC filing text.
3 4 A "project" is any concrete initiative, investment, program, expansion, construction,
4 5 product/R&D effort, acquisition/integration, technology deployment, partnership, or
@@ -47,4 +48,4 @@ Rules:
47 48 - If the text describes no concrete project, return {"projects": []}.
48 49 - Do not invent facts. Numbers/locations must appear in the text.
49 50 - Prefer fewer high-quality projects over many vague ones.
50 −\end{verbatim}
51 +\end{verbatim}}
modified paper/tables/tab_amounts.tex +10 −0
@@ -1,3 +1,8 @@
1 +% Generated by code/make_tables.py from data/amount\_dist.csv, projects\_per\_issuer.csv, data/stats.json, results/grounding/amount\_tail.json. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\small
4 +\caption{Distribution of the largest disclosed amount per project and of projects per issuer}\label{tab:amounts}
5 +\begin{threeparttable}
1 6 \begin{tabular}{lrrrrrr}
2 7 \toprule
3 8 & P10 & P25 & Median & P75 & P90 & P99 \\
@@ -6,3 +11,8 @@ Largest amount cited per project{,} M USD ($N$ = 56{{,}}500) & 3.2 & 23 & 128.5
6 11 Projects per issuer ($N$ = 2{{,}}492) & 12 & 24 & 42 & 67 & 94 & 140 \\
7 12 \bottomrule
8 13 \end{tabular}
14 +\begin{tablenotes}\footnotesize
15 +\item Amounts are the largest USD figure cited across the mentions of a project; they mix transaction values, budgets, contract values, financing facilities and estimates, and are never summed in the text. The maximum is 1{,}000~B USD (one mention, number found in the section text, no currency token nearby); 161 mentions in 104 projects cite 50~B USD or more, of which 155 have the number in the text and 144 a currency token within 40 characters; 584 mentions carry an amount of exactly zero (with \texttt{amount\_raw} NULL) and 24 a negative amount. 259 projects have a non-positive maximum amount; none of these values has been corrected (author decision pending). Projects per issuer are counted under the current resolution key, whose choice moves the total by a factor of ten (Table~\ref{tab:spec_curve}). Quantiles are exact order statistics of the stored tables; no sampling uncertainty applies.
16 +\end{tablenotes}
17 +\end{threeparttable}
18 +\end{table}
added paper/tables/tab_benchmark_8k.tex +30 −0
@@ -0,0 +1,30 @@
1 +% Generated by code/make_tables.py from results/benchmark\_8k/item\_vs\_type.csv, summary.json. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\scriptsize
4 +\setlength{\tabcolsep}{3pt}
5 +\caption{External consistency of 8-K mentions with the 8-K item codes declared in the filing body}\label{tab:benchmark_8k}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
8 +\begin{tabular}{llrrrrr}
9 +\toprule
10 +Category & 8-K item code & \multicolumn{1}{c}{\makecell{Sections with\\the item}} & \multicolumn{1}{c}{\makecell{P(category $\mid$ item)\\\%, 95\% CI}} & \multicolumn{1}{c}{\makecell{P(item $\mid$ category)\\\%, 95\% CI}} & \multicolumn{1}{c}{\makecell{Base rate of\\the category (\%)}} & Lift \\
11 +\midrule
12 +M\&A / integration & Item 2.01 & 5{,}456 & 91.1 [90.3, 91.8] & 13.1 [12.7, 13.4] & 9.5 & 9.6 \\
13 +M\&A / integration & Item 2.01 or 1.01 & 49{,}868 & 35.6 [35.2, 36.0] & 46.7 [46.2, 47.2] & 9.5 & 3.8 \\
14 +M\&A / integration & Item 1.01 & 46{,}888 & 31.8 [31.4, 32.2] & 39.2 [38.7, 39.7] & 9.5 & 3.3 \\
15 +Cost reduction / restructuring & Item 2.05 & 1{,}700 & 70.9 [68.7, 73.0] & 39.2 [37.5, 41.0] & 0.8 & 92.1 \\
16 +Strategic partnership & Item 1.01 & 46{,}888 & 4.0 [3.8, 4.2] & 42.1 [40.7, 43.6] & 1.1 & 3.6 \\
17 +capex type & Item 1.01 & 46{,}888 & 13.2 [12.9, 13.6] & 46.8 [45.9, 47.6] & 3.3 & 4.0 \\
18 +M\&A / integration & Item 8.01 (control) & 92{,}840 & 19.9 [19.7, 20.2] & 48.7 [48.2, 49.2] & 9.5 & 2.1 \\
19 +M\&A / integration & Item 5.02 (control) & 71{,}781 & 3.1 [3.0, 3.2] & 5.9 [5.7, 6.1] & 9.5 & 0.3 \\
20 +Cost reduction / restructuring & Item 8.01 (control) & 92{,}840 & 1.5 [1.4, 1.6] & 45.1 [43.3, 46.8] & 0.8 & 1.9 \\
21 +M\&A / integration & Item 2.03 (control) & 22{,}460 & 21.0 [20.5, 21.6] & 12.4 [12.1, 12.8] & 9.5 & 2.2 \\
22 +Strategic partnership & Item 8.01 (control) & 92{,}840 & 1.7 [1.6, 1.8] & 34.9 [33.6, 36.4] & 1.1 & 1.5 \\
23 +\bottomrule
24 +\end{tabular}
25 +\end{adjustbox}
26 +\begin{tablenotes}\footnotesize
27 +\item Item codes are read from the 8-K body with the pattern \texttt{Item\textbackslash{}s+([1-9]\textbackslash{}.[0-9]{2})} (99.7\% of the 400{,}601 8-K sections carry at least one code). ``P(category $\mid$ item)'' is the share of sections declaring the item in which the model returned at least one mention of the category; ``P(item $\mid$ category)'' is the share of sections with such a mention that declare the item; lift is the first probability divided by the category's base rate over all 8-K sections. Item~2.01 (completion of an acquisition or disposition) and Item~2.05 (exit or disposal costs) are the natural counterparts of \texttt{ma\_integration} and \texttt{cost\_reduction}; Items~5.02 and 8.01 are controls. Confidence intervals are Wilson intervals. These are consistency proxies: an item code says that an event of the kind was reported, not that the model's mention is correct, so neither probability is a precision or a recall.
28 +\end{tablenotes}
29 +\end{threeparttable}
30 +\end{table}
added paper/tables/tab_cohort.tex +31 −0
@@ -0,0 +1,31 @@
1 +% Generated by code/make_tables.py from results/runs/table6\_cohort.csv, table6\_cohort\_regression.json. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\scriptsize
4 +\setlength{\tabcolsep}{3pt}
5 +\caption{Projects per issuer by index-membership cohort: the apparent S\&P~500 effect is a run and volume effect}\label{tab:cohort}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
8 +\begin{tabular}{lrrrrrrr}
9 +\toprule
10 +\multicolumn{8}{l}{\itshape Panel A: projects per issuer by cohort and by run of the mentions counted} \\
11 +Cohort & Issuers & \multicolumn{1}{c}{\makecell{Projects\\(all mentions)}} & \multicolumn{1}{c}{\makecell{Per\\issuer}} & \multicolumn{1}{c}{\makecell{Projects\\(October mentions)}} & \multicolumn{1}{c}{\makecell{Per\\issuer}} & \multicolumn{1}{c}{\makecell{Ledger rows\\per issuer}} & \multicolumn{1}{c}{\makecell{October rows\\per issuer}} \\
12 +\midrule
13 +S\&P~500 $\cap$ Russell proxy & 491 & 27{,}382 & 55.8 & 11{,}738 & 25.1 & 552.4 & 242.7 \\
14 +Russell proxy only & 1{,}992 & 93{,}333 & 46.9 & 93{,}333 & 46.9 & 423.8 & 423.8 \\
15 +S\&P~500 only & 9 & 384 & 42.7 & 118 & 13.1 & 521.0 & 201.4 \\
16 +\midrule
17 +\multicolumn{8}{l}{\itshape Panel B: issuer-level OLS of projects on the S\&P~500 cohort dummy (HC1 standard errors in parentheses)} \\
18 +Dependent variable & \multicolumn{2}{c}{S\&P~500 dummy} & \multicolumn{2}{c}{log(1 + ledger rows)} & $N$ & $R^2$ & \\
19 +\midrule
20 +Projects, all mentions & 8.84 & (1.62) & -- & & 2{,}499 & 0.012 & \\
21 +Projects, October mentions only & -22.98 & (1.20) & -- & & 2{,}499 & 0.083 & \\
22 +Projects, all mentions, volume control & -0.28 & (1.52) & 22.09 & (0.73) & 2{,}499 & 0.274 & \\
23 +Projects, October mentions, volume control & -10.59 & (1.09) & 17.54 & (0.51) & 2{,}499 & 0.323 & \\
24 +\bottomrule
25 +\end{tabular}
26 +\end{adjustbox}
27 +\begin{tablenotes}\footnotesize
28 +\item Panel A counts projects per issuer with all mentions and with only the mentions produced by the October run (a project is ``October'' when at least one of its mentions carries an October timestamp); S\&P~500 issuers were additionally extracted in the June run, whose 10-K items came from a different segmenter (Section~\ref{sec:architecture}). Panel B reports the coefficient on the S\&P~500 dummy from issuer-level OLS with heteroskedasticity-robust (HC1) standard errors; the sign flips from $+8.8$ to $-23.0$ projects per issuer when the run is held fixed and vanishes once the number of ledgered rows is controlled for. Economic magnitude: one log point of ledgered rows is associated with 22.1 additional projects. No causal reading is intended: the regressions describe the composition of the database, not disclosure behaviour.
29 +\end{tablenotes}
30 +\end{threeparttable}
31 +\end{table}
modified paper/tables/tab_confidence.tex +20 −8
@@ -1,12 +1,24 @@
1 −\begin{tabular}{lr}
1 +% Generated by code/make_tables.py from data/confidence\_dist.csv, results/ledger/code\_vs\_data\_checks.json. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\small
4 +\caption{Self-reported extraction confidence of stored mentions, by run}\label{tab:confidence}
5 +\begin{threeparttable}
6 +\begin{tabular}{lrrrr}
2 7 \toprule
3 −Self-reported confidence (rounded) & Mentions \\
8 +\multicolumn{1}{c}{\makecell{Self-reported\\confidence (rounded)}} & Mentions & \multicolumn{1}{c}{\makecell{Share\\(\%)}} & \multicolumn{1}{c}{\makecell{June run\\(backfilled)}} & \multicolumn{1}{c}{\makecell{October\\run}} \\
4 9 \midrule
5 −0.5 & 1{,}611 \\
6 −0.6 & 3{,}278 \\
7 −0.7 & 21{,}647 \\
8 −0.8 & 72{,}280 \\
9 −0.9 & 100{,}831 \\
10 −1.0 & 108{,}418 \\
10 +0.5 & 1{,}611 & 0.5 & 106 & 1{,}505 \\
11 +0.6 & 3{,}278 & 1.1 & 304 & 2{,}974 \\
12 +0.7 & 21{,}647 & 7.0 & 2{,}239 & 19{,}408 \\
13 +0.8 & 72{,}280 & 23.5 & 8{,}594 & 63{,}686 \\
14 +0.9 & 100{,}831 & 32.7 & 14{,}459 & 86{,}372 \\
15 +1.0 & 108{,}418 & 35.2 & 14{,}228 & 94{,}190 \\
16 +\midrule
17 +Total & 308{,}065 & 100.0 & 39{,}930 & 268{,}135 \\
11 18 \bottomrule
12 19 \end{tabular}
20 +\begin{tablenotes}\footnotesize
21 +\item Confidence is the value returned by the model in its JSON answer, rounded to one decimal; mentions below 0.45 are discarded before storage. A missing confidence is set to 0.6 by the post-processing code and passes the threshold: 3{,}278 mentions carry exactly 0.600 and cannot be separated from genuine 0.6 answers because the raw response is not stored. The distribution describes the model's reporting habit, not accuracy; calibration requires the human labels of gate (d) (Table~\ref{tab:gates}).
22 +\end{tablenotes}
23 +\end{threeparttable}
24 +\end{table}
modified paper/tables/tab_coverage_year.tex +14 −1
@@ -1,6 +1,13 @@
1 +% Generated by code/make_tables.py from data/issuers\_by\_year.csv, filings\_by\_year\_form.csv, mentions\_by\_year.csv, projects\_by\_first\_seen\_year.csv. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\footnotesize
4 +\setlength{\tabcolsep}{3pt}
5 +\caption{Issuers, filings, stored mentions and projects first seen, by filing year}\label{tab:coverage_year}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
1 8 \begin{tabular}{lrrrrrrrr}
2 9 \toprule
3 −Year & Issuers & 10-K & 10-Q & 8-K & Mentions & Issuers w/ mentions & Mentions per issuer & Projects first seen \\
10 +Year & Issuers filing & 10-K & 10-Q & 8-K & Mentions stored & \multicolumn{1}{c}{\makecell{Issuers with\\$\geq 1$ mention}} & \multicolumn{1}{c}{\makecell{Mentions per\\issuer with mention}} & \multicolumn{1}{c}{\makecell{Projects\\first seen}} \\
4 11 \midrule
5 12 2010 & 1{,}392 & 1{,}357 & 4{,}152 & 17{,}672 & 11{,}908 & 1{,}224 & 9.7 & 7{,}835 \\
6 13 2011 & 1{,}424 & 1{,}409 & 4{,}260 & 18{,}533 & 13{,}551 & 1{,}287 & 10.5 & 6{,}679 \\
@@ -21,3 +28,9 @@ Year & Issuers & 10-K & 10-Q & 8-K & Mentions & Issuers w/ mentions & Mentions p
21 28 2026 & 2{,}498 & 2{,}338 & 5{,}322 & 23{,}972 & 19{,}086 & 2{,}260 & 8.4 & 6{,}694 \\
22 29 \bottomrule
23 30 \end{tabular}
31 +\end{adjustbox}
32 +\begin{tablenotes}\footnotesize
33 +\item Filing year of the document. 2010 is left-censored (a project already under way before the corpus start is ``first seen'' at its first in-window filing) and 2026 is partial (filings to 2026-10-27); the range quoted in the text, 6{,}240--8{,}216 projects first seen per year, covers 2011--2025 only. ``Projects first seen'' counts projects under the current resolution key whose earliest mention falls in the year (Table~\ref{tab:timeseries_cohort} holds the issuer-cohort and windowed-key series). Issuers filing rise mechanically under the snapshot design (Section~\ref{sec:sample}).
34 +\end{tablenotes}
35 +\end{threeparttable}
36 +\end{table}
modified paper/tables/tab_datamodel.tex +18 −10
@@ -1,24 +1,32 @@
1 −\begin{longtable}{p{3.1cm}p{8.6cm}p{4.3cm}}
1 +% Generated by code/make_tables.py from data/datamodel_audit.csv. Longtable: input outside a float.
2 +{\footnotesize
3 +\begin{longtable}{p{2.6cm}p{6.9cm}p{3.4cm}}
2 4 \caption{Tables required by the research design, current implementation and status}\label{tab:datamodel}\\
3 5 \toprule
4 6 Required table & Current implementation (database, table, key fields) & Status \\
5 7 \midrule
6 8 \endfirsthead
9 +\multicolumn{3}{l}{\itshape Table \thetable{} (continued)}\\
7 10 \toprule
8 11 Required table & Current implementation (database, table, key fields) & Status \\
9 12 \midrule
10 13 \endhead
11 −\bottomrule
14 +\midrule
15 +\multicolumn{3}{r}{\itshape continued on the next page}\\
12 16 \endfoot
13 −\texttt{universe\_snapshots} & \texttt{data/metadata/universe.json} + \texttt{companies} (CIK, ticker(s), name, sector, flags \texttt{in\_sp500}/\texttt{in\_russell3000}, fund weight, SIC, state, exchange, FYE, shard); snapshot date and source URL recorded & Partial: no file hash, no membership dates, no match confidence \\
14 −\texttt{issuers} & \texttt{companies} (one row per CIK; former names from SEC header stored in metadata JSON only) & Partial: no name history, no parent/subsidiary links \\
17 +\bottomrule
18 +\multicolumn{3}{p{12.8cm}}{\scriptsize Status at revision \texttt{2324b58}; ``partial'' and ``proposed'' rows are schema changes to be added by migration. The \texttt{amount\_raw} field is a formatted copy of the coerced float, not the filing's string; the ledger stores no model, prompt or call status.}\\
19 +\endlastfoot
20 +\texttt{universe\_\allowbreak{}snapshots} & \texttt{data/metadata/universe.json} + \texttt{companies} (CIK, ticker(s), name, sector, flags \texttt{in\_sp500}/\texttt{in\_russell3000}, fund weight, SIC, state, exchange, FYE, shard); snapshot date and source URL recorded & Partial: no file hash, no membership dates, no match confidence \\
21 +\texttt{issuers} & \texttt{companies} (one row per CIK; former names from SEC header stored in metadata JSON only) & Partial: no name history, no parent/\allowbreak{}subsidiary links \\
15 22 \texttt{filings} & \texttt{filings} (accession PK, CIK FK, form, filing/report dates, SEC URL, local path, size, download and parse status) & Implemented; no acceptance timestamp, no checksum \\
16 23 \texttt{sections} & \texttt{filing\_sections} (UUID PK, accession FK, name, item, order, text, counts) & Implemented; no character offsets into raw HTML \\
17 −\texttt{project\_mentions} & \texttt{project\_mentions} (SHA-1 id, accession, CIK, section id, name, type, description, objective, amount, raw amount, lists, years, status, confidence, backend, issuer context) & Implemented; no evidence span, no prompt hash, no five-way label \\
24 +\texttt{project\_\allowbreak{}mentions} & \texttt{project\_mentions} (SHA-1 id, accession, CIK, section id, name, type, description, objective, amount, formatted amount string (\texttt{amount\_raw}, not the filing's string), lists, years, status, confidence, backend, issuer context) & Implemented; no evidence span, no prompt hash, no five-way label \\
18 25 \texttt{projects} & \texttt{projects} (MD5 of CIK$|$type$|$location-or-name, representative fields, max amount, counts, first/last seen and cited years) & Implemented (deterministic key) \\
19 −\texttt{project\_mention\_links} & implicit in the key (every mention maps to exactly one project) & Proposed: explicit table with score, resolver version, adjudication \\
20 −\texttt{project\_events} & \texttt{project\_timeline} (one row per mention: date, form, status, amount, confidence, snippet) & Partial: mention rows, not typed events \\
21 −\texttt{project\_amounts} & \texttt{amount\_usd}/\texttt{amount\_raw} on mentions; max on projects & Proposed: type, currency, scale, basis, realization flag \\
22 −\texttt{extraction\_runs} & \texttt{extracted\_sections} ledger (section, accession, backend, n\_mentions, timestamp) + run logs & Partial: no prompt/schema/taxonomy hashes, no call status \\
23 −\texttt{human\_labels} & --- & Proposed \\
26 +\texttt{project\_\allowbreak{}mention\_\allowbreak{}links} & implicit in the key (every mention maps to exactly one project) & Proposed: explicit table with score, resolver version, adjudication \\
27 +\texttt{project\_\allowbreak{}events} & \texttt{project\_timeline} (one row per mention: date, form, status, amount, confidence, snippet) & Partial: mention rows, not typed events \\
28 +\texttt{project\_\allowbreak{}amounts} & \texttt{amount\_usd}/\texttt{amount\_raw} on mentions; max on projects & Proposed: type, currency, scale, basis, realization flag \\
29 +\texttt{extraction\_\allowbreak{}runs} & \texttt{extracted\_sections} ledger (section, accession, backend, n\_mentions, timestamp) + run logs & Partial: no prompt/\allowbreak{}schema/\allowbreak{}taxonomy hashes, no call status \\
30 +\texttt{human\_\allowbreak{}labels} & --- & Proposed \\
24 31 \end{longtable}
32 +}
modified paper/tables/tab_filings.tex +16 −6
@@ -1,11 +1,21 @@
1 −\begin{tabular}{lrrrrr}
1 +% Generated by code/make_tables.py from data/filings\_by\_form.csv, data/parse\_status.csv, data/stats.json, results/universe/filings\_status\_missing.csv. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\small
4 +\caption{Filings in the corpus by form, 2010-01-04 to 2026-10-27}\label{tab:filings}
5 +\begin{threeparttable}
6 +\begin{tabular}{lrrrrrr}
2 7 \toprule
3 −Form & Filings & First filing & Last filing & Raw HTML (GB) & Not parsed \\
8 +Form & Filings & First filing & Last filing & Raw HTML (GB) & Parser error & Missing on disk \\
4 9 \midrule
5 −10-K & 31{,}775 & 2010-01-08 & 2026-10-27 & 88.6 & 3 \\
6 −10-Q & 95{,}167 & 2010-01-05 & 2026-10-27 & 155.9 & 12 \\
7 −8-K & 400{,}606 & 2010-01-04 & 2026-10-27 & 10.0 & 1 \\
10 +10-K & 31{,}775 & 2010-01-08 & 2026-10-27 & 88.6 & 2 & 1 \\
11 +10-Q & 95{,}167 & 2010-01-05 & 2026-10-27 & 155.9 & 11 & 1 \\
12 +8-K & 400{,}606 & 2010-01-04 & 2026-10-27 & 10.0 & 1 & 0 \\
8 13 \midrule
9 −Total & 527{,}548 & 2010-01-04 & 2026-10-27 & 254.5 & 16 \\
14 +Total & 527{,}548 & 2010-01-04 & 2026-10-27 & 254.5 & 14 & 2 \\
10 15 \bottomrule
11 16 \end{tabular}
17 +\begin{tablenotes}\footnotesize
18 +\item Primary documents of Forms 10-K, 10-Q and 8-K retained from the SEC submissions index of every issuer of Table~\ref{tab:reconciliation}. ``Parser error'' counts documents whose primary document could not be cleaned; ``missing on disk'' counts documents logged as downloaded but not found at parse time. Raw HTML size is the sum of primary-document sizes recorded at download time. The 14 parser errors and 2 documents logged as downloaded but absent on disk are listed by accession number in \texttt{results/universe/filings\_status\_missing.csv} (parser errors: BJRI, NEWT, NNN, UNP; missing: XEL 10-K 2014, LNT 10-Q 2012).
19 +\end{tablenotes}
20 +\end{threeparttable}
21 +\end{table}
added paper/tables/tab_focus.tex +40 −0
@@ -0,0 +1,40 @@
1 +% Generated by code/make_tables.py from results/focus/focus\_coverage\_by\_form\_item.csv, focus\_coverage\_by\_form.csv, stats\_keys.json. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\scriptsize
4 +\setlength{\tabcolsep}{2.5pt}
5 +\caption{Focus-window coverage: share of each ledgered section's text actually shown to the model, by form and item}\label{tab:focus}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
8 +\begin{tabular}{llrrrrrrrr}
9 +\toprule
10 +Form & Item & \multicolumn{1}{c}{\makecell{Ledgered\\rows}} & \multicolumn{1}{c}{\makecell{Over 9{,}000\\chars (\%)}} & \multicolumn{1}{c}{\makecell{Median\\chars}} & \multicolumn{1}{c}{\makecell{Share shown\\P10}} & \multicolumn{1}{c}{\makecell{Share shown\\median}} & \multicolumn{1}{c}{\makecell{Share shown\\P90}} & \multicolumn{1}{c}{\makecell{Rows shown\\$< 25$\% (\%)}} & \multicolumn{1}{c}{\makecell{Mentions from rows\\shown $< 25$\% (\%)}} \\
11 +\midrule
12 +10-K & \texttt{business} & 29{,}285 & 81.1 & 37{,}168 & 5 & 16 & 100 & 66.6 & 86.1 \\
13 +10-K & \texttt{full\_body} & 1{,}230 & 99.9 & 304{,}265 & 1 & 2 & 4 & 99.8 & 100.0 \\
14 +10-K & \texttt{md\_and\_a} & 28{,}919 & 94.0 & 64{,}194 & 4 & 9 & 24 & 90.5 & 96.7 \\
15 +10-K & \texttt{properties} & 28{,}236 & 5.6 & 1{,}255 & 100 & 100 & 100 & 3.2 & 11.3 \\
16 +10-K & \texttt{quantitative\_disclosures} & 26{,}876 & 11.9 & 3{,}354 & 45 & 100 & 100 & 5.4 & 33.2 \\
17 +10-K & \texttt{risk\_factors} & 29{,}158 & 96.8 & 62{,}542 & 4 & 10 & 28 & 87.9 & 93.0 \\
18 +\midrule
19 +10-Q & \texttt{controls\_and\_procedures} & 92{,}393 & 1.9 & 1{,}710 & 100 & 100 & 100 & 1.1 & 3.2 \\
20 +10-Q & \texttt{financial\_statements} & 91{,}882 & 96.8 & 64{,}457 & 5 & 11 & 22 & 92.4 & 94.2 \\
21 +10-Q & \texttt{full\_document} & 241 & 100.0 & 348{,}536 & 1 & 2 & 7 & 100.0 & 100.0 \\
22 +10-Q & \texttt{legal\_proceedings} & 66{,}998 & 3.3 & 522 & 100 & 100 & 100 & 1.7 & 10.9 \\
23 +10-Q & \texttt{md\_and\_a} & 91{,}371 & 94.4 & 47{,}488 & 6 & 13 & 31 & 84.7 & 89.8 \\
24 +10-Q & \texttt{quantitative\_disclosures} & 83{,}138 & 4.9 & 1{,}510 & 100 & 100 & 100 & 1.0 & 7.7 \\
25 +10-Q & \texttt{risk\_factors} & 72{,}560 & 22.9 & 969 & 7 & 100 & 100 & 17.7 & 42.9 \\
26 +10-Q & \texttt{unregistered\_sales} & 80{,}210 & 6.9 & 3{,}886 & 100 & 100 & 100 & 4.3 & 5.7 \\
27 +\midrule
28 +8-K & \texttt{full\_body} & 400{,}601 & 8.8 & 3{,}816 & 100 & 100 & 100 & 3.3 & 5.7 \\
29 +\midrule
30 +10-K & all items & 143{,}704 & 59.3 & 28{,}255 & 5 & 22 & 100 & 52.1 & 84.0 \\
31 +10-Q & all items & 578{,}793 & 35.5 & 3{,}503 & 8 & 100 & 100 & 31.4 & 79.2 \\
32 +8-K & all items & 400{,}601 & 8.8 & 3{,}816 & 100 & 100 & 100 & 3.3 & 5.7 \\
33 +\bottomrule
34 +\end{tabular}
35 +\end{adjustbox}
36 +\begin{tablenotes}\footnotesize
37 +\item The snapshot's \texttt{\_focus} function was replayed on all 1{,}123{,}098 ledgered sections (the replicated spans equal the real output). Sections up to 9{,}000 characters are shown whole; longer sections are reduced to windows around candidate-gate hits up to the budget, so the ``share shown'' is the fraction of the section's characters contained in the text sent to the model. The last column is the share of the item's ledger mentions that come from sections of which less than a quarter was shown (193{,}416 of 308{,}477 ledger mentions overall). No user message reached the 14{,}000-character cut. Shares are over all ledgered rows, including gate-rejected ones (calls-only shares in \texttt{results/focus/focus\_coverage\_calls\_only\_by\_form\_item.csv}). Coverage of the text is not recall: what the model missed inside the shown windows is unmeasured.
38 +\end{tablenotes}
39 +\end{threeparttable}
40 +\end{table}
modified paper/tables/tab_fp_classes.tex +33 −63
@@ -1,67 +1,37 @@
1 −\begin{tabular}{lrrrrrrr}
1 +% Generated by code/make_tables.py from results/fp\_classes/financing\_regex\_by\_item.csv, financing\_regex\_by\_type.csv, financing\_regex\_terms.csv, summary.json. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\scriptsize
4 +\setlength{\tabcolsep}{3pt}
5 +\caption{Financing-instrument, buyback and dividend mentions: a construct-violation class detectable by pattern}\label{tab:fp_classes}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
8 +\begin{tabular}{llrrr@{\hspace{1.5em}}lrrr}
2 9 \toprule
3 −form\_type & item & project\_type & mentions & matched & pct & matched\_amount\_gusd & total\_amount\_gusd \\
10 +\multicolumn{5}{l}{\itshape Panel A: by form and item} & \multicolumn{4}{l}{\itshape Panel B: by category} \\
11 +Form & Item & Mentions & Matched & \% & Category & Mentions & Matched & \% \\
4 12 \midrule
5 −8-K & full\_body & ma\_integration & 41{,}635 & 6{,}055 & 14.54 & 4{,}431.64 & 21{,}674.49 \\
6 −10-Q & md\_and\_a & ma\_integration & 32{,}011 & 319 & 1.0 & 297.7 & 15{,}025.4 \\
7 −10-Q & financial\_statements & ma\_integration & 19{,}165 & 260 & 1.36 & 158.12 & 7{,}994.15 \\
8 −10-K & md\_and\_a & ma\_integration & 14{,}027 & 60 & 0.43 & 159.74 & 6{,}818.94 \\
9 −10-Q & md\_and\_a & drug\_pipeline & 12{,}341 & 1 & 0.01 & & 161.52 \\
10 −10-K & business & ma\_integration & 10{,}554 & 21 & 0.2 & 3.23 & 7{,}258.55 \\
11 −8-K & full\_body & capex\_program & 10{,}415 & 7{,}135 & 68.51 & 5{,}436.73 & 7{,}873.23 \\
12 −10-Q & md\_and\_a & geographic\_expansion & 7{,}602 & 2 & 0.03 & & 461.42 \\
13 −10-Q & md\_and\_a & plant\_construction & 6{,}624 & 1 & 0.02 & 3.0 & 882.35 \\
14 −10-Q & md\_and\_a & product\_launch & 5{,}935 & 1 & 0.02 & & 119.1 \\
15 −10-Q & md\_and\_a & partnership & 5{,}563 & 38 & 0.68 & 16.44 & 2{,}199.1 \\
16 −10-Q & md\_and\_a & rd\_program & 5{,}221 & 0 & 0.0 & & 169.15 \\
17 −8-K & full\_body & partnership & 4{,}919 & 170 & 3.46 & 127.29 & 1{,}238.44 \\
18 −10-Q & unregistered\_sales & ma\_integration & 4{,}565 & 2{,}334 & 51.13 & 1{,}995.02 & 2{,}281.79 \\
19 −10-Q & md\_and\_a & cost\_reduction & 4{,}437 & 111 & 2.5 & 79.52 & 571.57 \\
20 −8-K & full\_body & drug\_pipeline & 4{,}308 & 4 & 0.09 & 0.25 & 118.97 \\
21 −10-Q & md\_and\_a & capex\_program & 4{,}088 & 856 & 20.94 & 796.27 & 2{,}998.47 \\
22 −10-K & md\_and\_a & drug\_pipeline & 3{,}992 & 0 & 0.0 & & 28.52 \\
23 −10-Q & md\_and\_a & manufacturing\_expansion & 3{,}870 & 3 & 0.08 & & 182.76 \\
24 −10-Q & controls\_and\_procedures & ma\_integration & 3{,}536 & 5 & 0.14 & 0.43 & 248.21 \\
25 −8-K & full\_body & cost\_reduction & 3{,}361 & 643 & 19.13 & 266.15 & 807.44 \\
26 −10-K & properties & plant\_construction & 3{,}266 & 0 & 0.0 & & 132.04 \\
27 −10-K & md\_and\_a & geographic\_expansion & 3{,}156 & 2 & 0.06 & & 363.7 \\
28 −10-K & business & drug\_pipeline & 3{,}141 & 0 & 0.0 & & 25.43 \\
29 −10-Q & md\_and\_a & infrastructure & 3{,}047 & 4 & 0.13 & 1.85 & 3{,}464.59 \\
30 −10-K & business & geographic\_expansion & 2{,}833 & 0 & 0.0 & & 658.32 \\
31 −10-Q & controls\_and\_procedures & erp\_implementation & 2{,}703 & 0 & 0.0 & & 61.61 \\
32 −10-Q & md\_and\_a & digital\_transformation & 2{,}484 & 0 & 0.0 & & 67.68 \\
33 −10-K & business & product\_launch & 2{,}462 & 0 & 0.0 & & 51.71 \\
34 −10-Q & md\_and\_a & technology\_deployment & 2{,}410 & 35 & 1.45 & 16.79 & 179.42 \\
35 −10-K & md\_and\_a & plant\_construction & 2{,}310 & 3 & 0.13 & 0.34 & 286.23 \\
36 −10-K & md\_and\_a & product\_launch & 2{,}285 & 0 & 0.0 & & 80.96 \\
37 −10-K & md\_and\_a & partnership & 2{,}246 & 16 & 0.71 & 7.36 & 223.79 \\
38 −10-Q & risk\_factors & ma\_integration & 2{,}133 & 20 & 0.94 & 10.78 & 962.24 \\
39 −10-K & md\_and\_a & rd\_program & 2{,}001 & 0 & 0.0 & & 125.19 \\
40 −8-K & full\_body & plant\_construction & 1{,}983 & 23 & 1.16 & 4.29 & 685.84 \\
41 −10-K & business & rd\_program & 1{,}898 & 0 & 0.0 & & 186.29 \\
42 −10-K & business & partnership & 1{,}880 & 1 & 0.05 & 0.3 & 132.91 \\
43 −10-Q & unregistered\_sales & capex\_program & 1{,}740 & 1{,}419 & 81.55 & 1{,}841.69 & 1{,}972.31 \\
44 −10-Q & financial\_statements & drug\_pipeline & 1{,}735 & 0 & 0.0 & & 9.85 \\
45 −10-K & business & plant\_construction & 1{,}671 & 1 & 0.06 & 0.51 & 104.63 \\
46 −10-Q & financial\_statements & partnership & 1{,}664 & 56 & 3.37 & 35.31 & 185.07 \\
47 −8-K & full\_body & infrastructure & 1{,}651 & 24 & 1.45 & 15.03 & 540.82 \\
48 −10-K & md\_and\_a & cost\_reduction & 1{,}564 & 23 & 1.47 & 15.4 & 216.18 \\
49 −10-K & md\_and\_a & capex\_program & 1{,}507 & 372 & 24.68 & 392.53 & 1{,}848.99 \\
50 −10-Q & financial\_statements & cost\_reduction & 1{,}448 & 159 & 10.98 & 112.79 & 201.78 \\
51 −10-K & md\_and\_a & manufacturing\_expansion & 1{,}392 & 3 & 0.22 & 0.02 & 107.1 \\
52 −10-Q & financial\_statements & plant\_construction & 1{,}385 & 6 & 0.43 & 2.18 & 168.42 \\
53 −10-Q & unregistered\_sales & cost\_reduction & 1{,}381 & 1{,}212 & 87.76 & 1{,}020.25 & 1{,}033.64 \\
54 −8-K & full\_body & geographic\_expansion & 1{,}286 & 12 & 0.93 & 1.71 & 122.93 \\
55 −10-K & business & technology\_deployment & 1{,}265 & 8 & 0.63 & 10.52 & 86.41 \\
56 −10-K & properties & geographic\_expansion & 1{,}219 & 2 & 0.16 & 0.49 & 59.64 \\
57 −8-K & full\_body & technology\_deployment & 1{,}177 & 202 & 17.16 & 126.57 & 317.1 \\
58 −10-K & md\_and\_a & digital\_transformation & 1{,}090 & 0 & 0.0 & & 12.71 \\
59 −10-K & md\_and\_a & infrastructure & 1{,}067 & 3 & 0.28 & 2.16 & 1{,}525.2 \\
60 −10-K & business & digital\_transformation & 1{,}050 & 0 & 0.0 & & 84.4 \\
61 −10-K & business & manufacturing\_expansion & 1{,}025 & 0 & 0.0 & & 62.95 \\
62 −10-K & md\_and\_a & technology\_deployment & 978 & 27 & 2.76 & 13.61 & 52.45 \\
63 −8-K & full\_body & rd\_program & 968 & 4 & 0.41 & 0.75 & 217.38 \\
64 −10-K & properties & manufacturing\_expansion & 913 & 0 & 0.0 & & 11.22 \\
65 −\multicolumn{8}{l}{\ldots 232 more rows in \texttt{results/fp\_classes/financing\_regex\_by\_item\_type.csv}} \\
13 +10-K & \texttt{md\_and\_a} & 39{,}021 & 509 & 1.3 & Capital expenditure program & 19{,}211 & 10{,}096 & 52.6 \\
14 +10-K & \texttt{business} & 30{,}455 & 116 & 0.4 & M\&A / integration & 130{,}259 & 9{,}145 & 7.0 \\
15 +10-K & \texttt{properties} & 7{,}869 & 4 & 0.1 & Cost reduction / restructuring & 13{,}157 & 2{,}160 & 16.4 \\
16 +10-K & \texttt{risk\_factors} & 2{,}796 & 14 & 0.5 & Strategic partnership & 17{,}501 & 475 & 2.7 \\
17 +10-K & \texttt{full\_body} & 824 & 2 & 0.2 & Technology deployment & 6{,}725 & 360 & 5.4 \\
18 +10-K & \texttt{quantitative\_disclosures} & 530 & 37 & 7.0 & Plant / site construction & 18{,}388 & 40 & 0.2 \\
19 +10-Q & \texttt{md\_and\_a} & 99{,}167 & 1{,}372 & 1.4 & Infrastructure investment & 8{,}510 & 37 & 0.4 \\
20 +10-Q & \texttt{financial\_statements} & 30{,}080 & 721 & 2.4 & Sustainability / ESG & 2{,}607 & 36 & 1.4 \\
21 +10-Q & \texttt{unregistered\_sales} & 9{,}506 & 5{,}179 & 54.5 & Geographic expansion & 17{,}713 & 27 & 0.2 \\
22 +10-Q & \texttt{controls\_and\_procedures} & 7{,}079 & 11 & 0.2 & Manufacturing / capacity expansion & 8{,}825 & 13 & 0.2 \\
23 +10-Q & \texttt{risk\_factors} & 4{,}420 & 43 & 1.0 & R\&D program & 11{,}758 & 7 & 0.1 \\
24 +10-Q & \texttt{legal\_proceedings} & 845 & 8 & 1.0 & Data center & 889 & 6 & 0.7 \\
25 +10-Q & \texttt{quantitative\_disclosures} & 800 & 76 & 9.5 & Drug / clinical pipeline & 26{,}755 & 5 & 0.0 \\
26 +10-Q & \texttt{full\_document} & 107 & 0 & 0.0 & New product / launch & 12{,}456 & 3 & 0.0 \\
27 +8-K & \texttt{full\_body} & 74{,}566 & 14{,}320 & 19.2 & Energy transition / renewables & 866 & 2 & 0.2 \\
28 +\midrule
29 +All & & 308{,}065 & 22{,}412 & 7.3 & All & 308{,}065 & 22{,}412 & 7.3 \\
66 30 \bottomrule
67 31 \end{tabular}
32 +\end{adjustbox}
33 +\begin{tablenotes}\footnotesize
34 +\item A mention is matched when its lower-cased name or description contains \texttt{repurchase|buy-?back|dividend|credit facility|revolving|term loan|notes? (due|offering)|at-the-market|senior notes|commercial paper} (most frequent terms: repurchase 10{,}886, senior notes 3{,}375, term loan 2{,}263, revolving 1{,}839, credit facility 1{,}184, notes due 1{,}177). These instruments are not strategic projects under the construct of Section~\ref{sec:construct}, yet the gate word ``program'' and the prompt admit them; 13{,}139 projects (10.8\%) have at least one matched mention and 12{,}027 a matched representative name or description. Matched mentions carry 17.8 of the 104.2~T USD of mention amounts. The pattern is a lower bound on the class (no human label has confirmed any match or non-match) and is applied to the stored paraphrase, not to the filing text. Part~I/Part~II ``Item~2'' collisions of the 10-Q segmenter affect 1{,}001 \texttt{unregistered\_sales} sections above 3{,}000 words (1.3\% of 77{,}869 pairs), 296 of them with an MD\&A sibling under 500 words.
35 +\end{tablenotes}
36 +\end{threeparttable}
37 +\end{table}
modified paper/tables/tab_graph.tex +13 −0
@@ -1,3 +1,8 @@
1 +% Generated by code/make_tables.py from data/kg.csv. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\small
4 +\caption{Knowledge-graph composition: node and edge types}\label{tab:graph}
5 +\begin{threeparttable}
1 6 \begin{tabular}{llr}
2 7 \toprule
3 8 & Type & Count \\
@@ -10,5 +15,13 @@ Nodes & \texttt{Partner} & 36{,}822 \\
10 15 Nodes & \texttt{Location} & 14{,}508 \\
11 16 Nodes & \texttt{Technology} & 8{,}551 \\
12 17 Nodes & \texttt{Company} & 2{,}492 \\
18 +\midrule
19 +Nodes & total & 183{,}472 \\
20 +Edges & total & 204{,}456 \\
13 21 \bottomrule
14 22 \end{tabular}
23 +\begin{tablenotes}\footnotesize
24 +\item Nodes are projected from the resolved projects (one node per company, project, distinct location string, technology tag and partner string); edges are \texttt{owns} (company--project), \texttt{located\_in} and \texttt{uses}. Partner nodes are created without edges in the current build. Technology tags are free text and are grounded in the section text for only part of the mentions (Table~\ref{tab:grounding}).
25 +\end{tablenotes}
26 +\end{threeparttable}
27 +\end{table}
modified paper/tables/tab_grounding.tex +40 −63
@@ -1,67 +1,44 @@
1 −\begin{tabular}{lrrrrrrrr}
1 +% Generated by code/make_tables.py from results/grounding/grounding\_by\_group.csv, grounding\_element\_level.csv, grounding\_all\_structured.csv, fallback\_bounds.json. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\footnotesize
4 +\setlength{\tabcolsep}{4pt}
5 +\caption{Mechanical grounding of the structured fields of all stored mentions in the stored section text}\label{tab:grounding}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
8 +\begin{tabular}{lrrrrr}
2 9 \toprule
3 −form & item & field & n\_mentions & n\_sections & n\_grounded & grounded\_share & ci\_low & ci\_high \\
10 +\multicolumn{6}{l}{\itshape Panel A: share of mentions whose field is found literally in the stored section text (\%, 95\% CI)} \\
11 +Field & Mentions with the field & All forms & 10-K & 10-Q & 8-K \\
4 12 \midrule
5 −10-Q & financial\_statements & years & 27{,}098 & 18{,}213 & 27{,}085 & 1 & 0.999 & 1 \\
6 −10-K & md\_and\_a & years & 30{,}493 & 13{,}345 & 30{,}433 & 0.998 & 0.997 & 0.999 \\
7 −10-Q & md\_and\_a & years & 76{,}041 & 36{,}503 & 75{,}894 & 0.998 & 0.998 & 0.998 \\
8 −8-K & full\_body & years & 69{,}075 & 59{,}295 & 68{,}920 & 0.998 & 0.997 & 0.998 \\
9 −10-Q & risk\_factors & years & 2{,}905 & 2{,}288 & 2{,}891 & 0.995 & 0.992 & 0.997 \\
10 −10-Q & unregistered\_sales & years & 9{,}009 & 6{,}923 & 8{,}999 & 0.999 & 0.998 & 1 \\
11 −10-K & properties & years & 6{,}061 & 3{,}401 & 6{,}009 & 0.991 & 0.988 & 0.994 \\
12 −10-K & business & years & 20{,}877 & 9{,}200 & 20{,}776 & 0.995 & 0.994 & 0.996 \\
13 −10-K & quantitative\_disclosures & years & 460 & 330 & 460 & 1.0 & 1.0 & 1.0 \\
14 −10-Q & controls\_and\_procedures & years & 6{,}606 & 5{,}434 & 6{,}571 & 0.995 & 0.993 & 0.996 \\
15 −10-Q & legal\_proceedings & years & 679 & 558 & 677 & 0.997 & 0.993 & 1.0 \\
16 −10-Q & quantitative\_disclosures & years & 697 & 531 & 693 & 0.994 & 0.984 & 1.0 \\
17 −10-K & risk\_factors & years & 1{,}704 & 1{,}034 & 1{,}695 & 0.995 & 0.991 & 0.998 \\
18 −10-Q & full\_document & years & 93 & 34 & 93 & 1.0 & 1.0 & 1.0 \\
19 −10-K & full\_body & years & 671 & 301 & 669 & 0.997 & 0.993 & 1.0 \\
20 −8-K & full\_body & locations & 39{,}399 & 36{,}198 & 26{,}714 & 0.678 & 0.673 & 0.683 \\
21 −10-Q & md\_and\_a & locations & 32{,}007 & 19{,}345 & 27{,}070 & 0.846 & 0.841 & 0.851 \\
22 −10-K & md\_and\_a & locations & 12{,}521 & 7{,}249 & 10{,}572 & 0.844 & 0.836 & 0.852 \\
23 −10-Q & financial\_statements & locations & 11{,}964 & 9{,}096 & 9{,}225 & 0.771 & 0.762 & 0.78 \\
24 −10-Q & controls\_and\_procedures & locations & 691 & 618 & 485 & 0.702 & 0.665 & 0.735 \\
25 −10-K & properties & locations & 6{,}769 & 3{,}524 & 5{,}818 & 0.86 & 0.847 & 0.872 \\
26 −10-K & risk\_factors & locations & 863 & 578 & 744 & 0.862 & 0.832 & 0.892 \\
27 −10-K & business & locations & 11{,}424 & 6{,}107 & 9{,}918 & 0.868 & 0.86 & 0.876 \\
28 −10-Q & risk\_factors & locations & 1{,}063 & 828 & 917 & 0.863 & 0.838 & 0.886 \\
29 −10-Q & quantitative\_disclosures & locations & 166 & 136 & 133 & 0.801 & 0.732 & 0.861 \\
30 −10-Q & unregistered\_sales & locations & 723 & 595 & 533 & 0.737 & 0.701 & 0.774 \\
31 −10-K & quantitative\_disclosures & locations & 165 & 124 & 138 & 0.836 & 0.764 & 0.899 \\
32 −10-Q & legal\_proceedings & locations & 595 & 463 & 375 & 0.63 & 0.584 & 0.674 \\
33 −10-Q & full\_document & locations & 86 & 31 & 76 & 0.884 & 0.811 & 0.951 \\
34 −10-K & full\_body & locations & 347 & 184 & 314 & 0.905 & 0.864 & 0.939 \\
35 −10-K & md\_and\_a & partners & 6{,}268 & 4{,}289 & 6{,}223 & 0.993 & 0.99 & 0.995 \\
36 −10-Q & financial\_statements & partners & 5{,}933 & 4{,}753 & 5{,}902 & 0.995 & 0.993 & 0.997 \\
37 −8-K & full\_body & partners & 42{,}167 & 37{,}852 & 41{,}998 & 0.996 & 0.995 & 0.997 \\
38 −10-Q & md\_and\_a & partners & 16{,}157 & 11{,}346 & 15{,}993 & 0.99 & 0.988 & 0.992 \\
39 −10-Q & risk\_factors & partners & 1{,}359 & 1{,}189 & 1{,}352 & 0.995 & 0.991 & 0.998 \\
40 −10-Q & controls\_and\_procedures & partners & 488 & 453 & 487 & 0.998 & 0.994 & 1.0 \\
41 −10-Q & unregistered\_sales & partners & 1{,}964 & 1{,}599 & 1{,}939 & 0.987 & 0.981 & 0.993 \\
42 −10-K & business & partners & 5{,}164 & 3{,}484 & 5{,}132 & 0.994 & 0.991 & 0.996 \\
43 −10-K & properties & partners & 799 & 531 & 792 & 0.991 & 0.985 & 0.997 \\
44 −10-Q & legal\_proceedings & partners & 313 & 282 & 308 & 0.984 & 0.968 & 0.997 \\
45 −10-K & risk\_factors & partners & 403 & 326 & 399 & 0.99 & 0.979 & 0.998 \\
46 −10-Q & quantitative\_disclosures & partners & 98 & 91 & 97 & 0.99 & 0.965 & 1.0 \\
47 −10-K & quantitative\_disclosures & partners & 64 & 54 & 64 & 1.0 & 1.0 & 1.0 \\
48 −10-K & full\_body & partners & 127 & 89 & 127 & 1.0 & 1.0 & 1.0 \\
49 −10-Q & full\_document & partners & 16 & 10 & 16 & 1.0 & 1.0 & 1.0 \\
50 −10-K & md\_and\_a & technologies & 5{,}311 & 3{,}624 & 3{,}252 & 0.612 & 0.596 & 0.627 \\
51 −10-Q & controls\_and\_procedures & technologies & 2{,}014 & 1{,}957 & 1{,}820 & 0.904 & 0.89 & 0.917 \\
52 −10-Q & financial\_statements & technologies & 3{,}218 & 2{,}625 & 1{,}968 & 0.612 & 0.591 & 0.632 \\
53 −10-Q & unregistered\_sales & technologies & 232 & 188 & 116 & 0.5 & 0.429 & 0.574 \\
54 −10-K & business & technologies & 5{,}448 & 3{,}379 & 3{,}654 & 0.671 & 0.655 & 0.686 \\
55 −8-K & full\_body & technologies & 5{,}116 & 4{,}613 & 2{,}977 & 0.582 & 0.567 & 0.596 \\
56 −10-Q & md\_and\_a & technologies & 13{,}596 & 9{,}327 & 8{,}492 & 0.625 & 0.615 & 0.635 \\
57 −10-Q & risk\_factors & technologies & 549 & 483 & 328 & 0.597 & 0.552 & 0.645 \\
58 −10-K & properties & technologies & 616 & 416 & 367 & 0.596 & 0.545 & 0.647 \\
59 −10-Q & quantitative\_disclosures & technologies & 51 & 46 & 23 & 0.451 & 0.302 & 0.591 \\
60 −10-K & risk\_factors & technologies & 367 & 297 & 223 & 0.608 & 0.549 & 0.665 \\
61 −10-Q & legal\_proceedings & technologies & 63 & 60 & 47 & 0.746 & 0.63 & 0.854 \\
62 −10-K & quantitative\_disclosures & technologies & 47 & 39 & 32 & 0.681 & 0.535 & 0.814 \\
63 −10-Q & full\_document & technologies & 6 & 6 & 1 & 0.167 & 0.0 & 0.5 \\
64 −10-K & full\_body & technologies & 106 & 71 & 61 & 0.576 & 0.462 & 0.68 \\
65 −\multicolumn{9}{l}{\ldots 30 more rows in \texttt{results/grounding/grounding\_by\_field\_form\_item.csv}} \\
13 +Cited years & 252{,}469 & 99.8 [99.7, 99.8] & 99.6 & 99.8 & 99.8 \\
14 +Partners & 81{,}320 & 99.4 [99.3, 99.5] & 99.3 & 99.1 & 99.6 \\
15 +Amount (number) & 120{,}240 & 93.7 [93.6, 93.9] & 97.4 & 97.5 & 86.9 \\
16 +Amount (number + currency token within 40 chars) & 120{,}240 & 80.5 [80.2, 80.7] & 86.8 & 82.3 & 74.9 \\
17 +Locations & 118{,}783 & 78.3 [78.0, 78.6] & 85.7 & 82.1 & 67.8 \\
18 +Technology tags & 36{,}740 & 63.6 [63.0, 64.2] & 63.8 & 64.8 & 58.2 \\
19 +\midrule
20 +\multicolumn{6}{l}{\itshape Panel B: element level (every listed year, partner, location or tag counted separately)} \\
21 +Partners & 122{,}590 elements & 99.6 & & & \\
22 +Locations & 181{,}898 elements & 84.2 & & & \\
23 +Technology tags & 47{,}361 elements & 70.6 & & & \\
24 +Cited years & 307{,}399 elements & 99.7 & & & \\
25 +\midrule
26 +\multicolumn{6}{l}{\itshape Panel C: mentions with every structured field grounded (\%), by form, run and confidence bin} \\
27 +All mentions with at least one structured field & 276{,}168 & 88.2 & 92.2 & 92.4 & 76.6 \\
28 +By run: June (backfilled) / October & 36{,}806 / 239{,}362 & 84.5 / 88.7 & & & \\
29 +\quad confidence bin 0.45-0.6 & 696 & 90.7 & & & \\
30 +\quad confidence bin 0.6-0.7 & 1{,}726 & 93.5 & & & \\
31 +\quad confidence bin 0.7-0.8 & 13{,}313 & 94.2 & & & \\
32 +\quad confidence bin 0.8-0.9 & 58{,}586 & 92.7 & & & \\
33 +\quad confidence bin 0.9-1.0 & 201{,}847 & 86.4 & & & \\
34 +\quad confidence bin 10-K & 69{,}065 & 92.2 & & & \\
35 +\quad confidence bin 10-Q & 134{,}391 & 92.4 & & & \\
36 +\quad confidence bin 8-K & 72{,}712 & 76.6 & & & \\
66 37 \bottomrule
67 38 \end{tabular}
39 +\end{adjustbox}
40 +\begin{tablenotes}\footnotesize
41 +\item Population: all 308{,}065 stored mentions, joined to the text of their section as stored (legacy June text for the S\&P~500 10-Ks). A field is ``grounded'' when every element of the list (years, partners, locations, technologies, case-folded) or the amount (tested in units, thousands, millions and billions with one to three significant digits) occurs literally in that text; a currency token is \$, USD, dollar, million or billion within 40 characters of the number. Confidence intervals are percentile bootstraps with 1{,}000 replicates clustered by section. Grounding is a necessary condition for correctness, not a measure of it: a grounded year can belong to another initiative, and an ungrounded location can be a correct normalisation (``Texas'' for ``Austin''); precision and recall require the human labels of gate (d). Panel C counts mentions with at least one structured field. Upper bounds on the regex back-fill from the model's own paraphrase (\texttt{llm.py}): the stored years equal the regex output on the description for 98{,}438 of 252{,}469 mentions with years (39\%) and the technology list for 16{,}949 of 36{,}740 (46\%); 604 mentions cite a year absent from the section text.
42 +\end{tablenotes}
43 +\end{threeparttable}
44 +\end{table}
modified paper/tables/tab_items.tex +31 −16
@@ -1,21 +1,36 @@
1 −\begin{tabular}{llrrr}
1 +% Generated by code/make_tables.py from data/ledger\_10k\_items.csv, ledger\_10q\_items.csv, results/ledger/gate\_pass\_by\_form\_item.csv, results/focus/, results/fp\_classes/. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\footnotesize
4 +\setlength{\tabcolsep}{3pt}
5 +\caption{Ledgered rows, mentions, gate-passing calls, text shown to the model and financing-class share, by form and item}\label{tab:items}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
8 +\begin{tabular}{llrrrrr}
2 9 \toprule
3 −Form & Section (item) & Ledgered sections & Mentions & Gate passed (calls) \\
10 +Form & Section (item) & \multicolumn{1}{c}{\makecell{Ledgered\\rows}} & Mentions & \multicolumn{1}{c}{\makecell{Gate-passing\\calls}} & \multicolumn{1}{c}{\makecell{Median share of\\text shown (\%)}} & \multicolumn{1}{c}{\makecell{Financing-class\\mentions (\%)}} \\
4 11 \midrule
5 −10-K & \texttt{business} & 29{,}285 & 30{,}492 & 29{,}118 \\
6 −10-K & \texttt{risk\_factors} & 29{,}158 & 2{,}797 & 28{,}941 \\
7 −10-K & \texttt{md\_and\_a} & 28{,}919 & 39{,}099 & 28{,}050 \\
8 −10-K & \texttt{properties} & 28{,}236 & 7{,}879 & 25{,}940 \\
9 −10-K & \texttt{quantitative\_disclosures} & 26{,}876 & 531 & 22{,}032 \\
10 −10-K & \texttt{full\_body} & 1{,}230 & 824 & 1{,}229 \\
12 +10-K & \texttt{business} & 29{,}285 & 30{,}492 & 29{,}118 & 16 & 0.4 \\
13 +10-K & \texttt{risk\_factors} & 29{,}158 & 2{,}797 & 28{,}941 & 10 & 0.5 \\
14 +10-K & \texttt{md\_and\_a} & 28{,}919 & 39{,}099 & 28{,}050 & 9 & 1.3 \\
15 +10-K & \texttt{properties} & 28{,}236 & 7{,}879 & 25{,}940 & 100 & 0.1 \\
16 +10-K & \texttt{quantitative\_disclosures} & 26{,}876 & 531 & 22{,}032 & 100 & 7.0 \\
17 +10-K & \texttt{full\_body} & 1{,}230 & 824 & 1{,}229 & 2 & 0.2 \\
11 18 \midrule
12 −10-Q & \texttt{controls\_and\_procedures} & 92{,}393 & 7{,}082 & 20{,}913 \\
13 −10-Q & \texttt{financial\_statements} & 91{,}882 & 30{,}159 & 90{,}106 \\
14 −10-Q & \texttt{md\_and\_a} & 91{,}371 & 99{,}305 & 90{,}269 \\
15 −10-Q & \texttt{quantitative\_disclosures} & 83{,}138 & 808 & 46{,}720 \\
16 −10-Q & \texttt{unregistered\_sales} & 80{,}210 & 9{,}535 & 61{,}867 \\
17 −10-Q & \texttt{risk\_factors} & 72{,}560 & 4{,}420 & 33{,}826 \\
18 −10-Q & \texttt{legal\_proceedings} & 66{,}998 & 845 & 20{,}031 \\
19 −10-Q & \texttt{full\_document} & 241 & 107 & 241 \\
19 +10-Q & \texttt{controls\_and\_procedures} & 92{,}393 & 7{,}082 & 20{,}913 & 100 & 0.2 \\
20 +10-Q & \texttt{financial\_statements} & 91{,}882 & 30{,}159 & 90{,}106 & 11 & 2.4 \\
21 +10-Q & \texttt{md\_and\_a} & 91{,}371 & 99{,}305 & 90{,}269 & 13 & 1.4 \\
22 +10-Q & \texttt{quantitative\_disclosures} & 83{,}138 & 808 & 46{,}720 & 100 & 9.5 \\
23 +10-Q & \texttt{unregistered\_sales} & 80{,}210 & 9{,}535 & 61{,}867 & 100 & 54.5 \\
24 +10-Q & \texttt{risk\_factors} & 72{,}560 & 4{,}420 & 33{,}826 & 100 & 1.0 \\
25 +10-Q & \texttt{legal\_proceedings} & 66{,}998 & 845 & 20{,}031 & 100 & 1.0 \\
26 +10-Q & \texttt{full\_document} & 241 & 107 & 241 & 2 & 0.0 \\
27 +\midrule
28 +8-K & \texttt{full\_body} & 400{,}601 & 74{,}594 & 204{,}442 & 100 & 19.2 \\
20 29 \bottomrule
21 30 \end{tabular}
31 +\end{adjustbox}
32 +\begin{tablenotes}\footnotesize
33 +\item Mentions are ledger counts (before identifier de-duplication, Table~\ref{tab:sections}). The 10-K \texttt{full\_body} rows are filings of the June (S\&P~500) ingest in which its segmenter found no Item heading; the October parser's \texttt{full\_document} fallback produced 10-K rows that are excluded from extraction by scope (Section~\ref{sec:architecture}), while its 10-Q \texttt{full\_document} rows are ledgered. ``Median share of text shown'' is the median, over the item's ledgered rows, of the fraction of the section's characters contained in the focus windows actually sent to the model (Table~\ref{tab:focus}). ``Financing-class mentions'' is the share of the item's stored mentions whose name or description matches the repurchase / dividend / credit-facility / notes-offering pattern of Table~\ref{tab:fp_classes}; rows above 10\% are the 10-Q \texttt{unregistered\_sales} item (Part~II Item~2, where issuer repurchases are tabled) and the 8-K body.
34 +\end{tablenotes}
35 +\end{threeparttable}
36 +\end{table}
modified paper/tables/tab_june_october.tex +21 −11
@@ -1,15 +1,25 @@
1 −\begin{tabular}{lrrrrrr}
1 +% Generated by code/make_tables.py from results/resolver/june\_october\_reconciliation.csv. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\small
4 +\caption{Mentions by cohort, run and form: reconciliation of the June (S\&P~500) and October (Russell proxy) runs}\label{tab:june_october}
5 +\begin{threeparttable}
6 +\begin{tabular}{llrrrrr}
2 7 \toprule
3 −in\_sp500 & run & form\_type & mentions & projects\_touched & filings & issuers \\
8 +Cohort & Run & Form & Mentions & \multicolumn{1}{c}{\makecell{Projects\\touched}} & Filings & Issuers \\
4 9 \midrule
5 −False & october & 10-K & 64{,}798 & 34{,}658 & 15{,}784 & 1{,}857 \\
6 −False & october & 10-Q & 117{,}224 & 45{,}274 & 40{,}745 & 1{,}954 \\
7 −False & october & 8-K & 55{,}676 & 34{,}420 & 45{,}937 & 1{,}964 \\
8 −True & backfilled\_june & 10-K & 15{,}787 & 8{,}697 & 4{,}193 & 481 \\
9 −True & backfilled\_june & 10-Q & 5{,}817 & 2{,}071 & 2{,}028 & 84 \\
10 −True & backfilled\_june & 8-K & 18{,}326 & 10{,}023 & 15{,}234 & 495 \\
11 −True & october & 10-K & 910 & 649 & 222 & 97 \\
12 −True & october & 10-Q & 28{,}963 & 11{,}030 & 10{,}684 & 455 \\
13 −True & october & 8-K & 564 & 432 & 477 & 203 \\
10 +Russell proxy only & October run & 10-K & 64{,}798 & 34{,}658 & 15{,}784 & 1{,}857 \\
11 +Russell proxy only & October run & 10-Q & 117{,}224 & 45{,}274 & 40{,}745 & 1{,}954 \\
12 +Russell proxy only & October run & 8-K & 55{,}676 & 34{,}420 & 45{,}937 & 1{,}964 \\
13 +S\&P~500 & June run (backfilled) & 10-K & 15{,}787 & 8{,}697 & 4{,}193 & 481 \\
14 +S\&P~500 & June run (backfilled) & 10-Q & 5{,}817 & 2{,}071 & 2{,}028 & 84 \\
15 +S\&P~500 & June run (backfilled) & 8-K & 18{,}326 & 10{,}023 & 15{,}234 & 495 \\
16 +S\&P~500 & October run & 10-K & 910 & 649 & 222 & 97 \\
17 +S\&P~500 & October run & 10-Q & 28{,}963 & 11{,}030 & 10{,}684 & 455 \\
18 +S\&P~500 & October run & 8-K & 564 & 432 & 477 & 203 \\
14 19 \bottomrule
15 20 \end{tabular}
21 +\begin{tablenotes}\footnotesize
22 +\item The June run covered the 10-Ks (legacy segmenter), the 8-Ks and 3{,}710 10-Qs of the S\&P~500; the October run added the remaining S\&P~500 10-Qs and the whole Russell-only cohort. ``Projects touched'' counts distinct current-key projects with at least one mention in the row, so projects spanning rows are counted more than once. The backfilled block alone resolves to the June release's project count, which reconciles the two releases without any resolver change.
23 +\end{tablenotes}
24 +\end{threeparttable}
25 +\end{table}
added paper/tables/tab_ledger_calls.tex +29 −0
@@ -0,0 +1,29 @@
1 +% Generated by code/make_tables.py from results/ledger/gate\_pass\_by\_form\_run.csv, gate\_pass\_by\_run.csv, gate\_pass\_totals.json. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\scriptsize
4 +\setlength{\tabcolsep}{3pt}
5 +\caption{Extraction ledger reconciliation by form and run: ledgered rows, gate-passing calls, productive sections and mentions}\label{tab:ledger_calls}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
8 +\begin{tabular}{llrrrrrrrr}
9 +\toprule
10 +Form & Run & \multicolumn{1}{c}{\makecell{Ledgered\\rows}} & \multicolumn{1}{c}{\makecell{Rows\\$< 30$ words}} & \multicolumn{1}{c}{\makecell{Gate-passing\\calls}} & \multicolumn{1}{c}{\makecell{Productive\\sections}} & \multicolumn{1}{c}{\makecell{Productive\\(\% of calls)}} & \multicolumn{1}{c}{\makecell{Mentions\\(ledger)}} & \multicolumn{1}{c}{\makecell{Mentions\\stored}} & \multicolumn{1}{c}{\makecell{Mentions\\per call}} \\
11 +\midrule
12 +10-K & June run (backfilled) & 27{,}164 & 0 & 26{,}336 & 6{,}204 & 23.6 & 15{,}787 & 15{,}787 & 0.60 \\
13 +10-K & October run & 116{,}540 & 0 & 108{,}974 & 24{,}673 & 22.6 & 65{,}835 & 65{,}708 & 0.60 \\
14 +10-Q & June run (backfilled) & 23{,}873 & 1{,}069 & 14{,}590 & 2{,}969 & 20.4 & 5{,}817 & 5{,}817 & 0.40 \\
15 +10-Q & October run & 554{,}920 & 0 & 349{,}383 & 72{,}736 & 20.8 & 146{,}444 & 146{,}187 & 0.42 \\
16 +8-K & June run (backfilled) & 103{,}927 & 1 & 54{,}360 & 15{,}234 & 28.0 & 18{,}326 & 18{,}326 & 0.34 \\
17 +8-K & October run & 296{,}674 & 0 & 150{,}082 & 46{,}414 & 30.9 & 56{,}268 & 56{,}240 & 0.37 \\
18 +\midrule
19 +All forms & June run (backfilled) & 154{,}964 & 1{,}070 & 95{,}286 & 24{,}407 & 25.6 & 39{,}930 & 39{,}930 & 0.42 \\
20 +All forms & October run & 968{,}134 & 0 & 608{,}439 & 143{,}823 & 23.6 & 268{,}547 & 268{,}135 & 0.44 \\
21 +All forms & Both runs & 1{,}123{,}098 & 1{,}070 & 703{,}725 & 168{,}230 & 23.9 & 308{,}477 & 308{,}065 & 0.44 \\
22 +\bottomrule
23 +\end{tabular}
24 +\end{adjustbox}
25 +\begin{tablenotes}\footnotesize
26 +\item The run is identified by the ledger timestamp: every row of the June (S\&P~500) run was re-inserted at a single instant (\SPIDextractedAtFirst) and the October run occupies all later timestamps; the ledger itself stores no run, model or prompt identifier. ``Gate-passing calls'' are rows whose stored text matches the candidate gate of Appendix~\ref{app:prompt} (recomputed with DuckDB RE2 and with Python \texttt{re}; the two agree on every row and no row with mentions fails the gate); the remaining rows were ledgered as ``no project'' without an API call. Rows under 30 words exist only in the backfilled block, which ignored the word filter. A productive section has at least one stored mention. The ledger cannot distinguish an empty answer from a failed call (Table~\ref{tab:outage}), so productive shares are lower bounds on the share of calls that would return a project under a complete run.
27 +\end{tablenotes}
28 +\end{threeparttable}
29 +\end{table}
added paper/tables/tab_outage.tex +37 −0
@@ -0,0 +1,37 @@
1 +% Generated by code/make_tables.py from results/ledger/log\_summary.json, throughput.json, backfill\_block.json, resume\_batch1\_vs\_expected.csv. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\footnotesize
4 +\caption{Reconciliation of the October 2026 extraction outage: log, ledger and the suspect post-resume batch}\label{tab:outage}
5 +\begin{threeparttable}
6 +\begin{tabular}{p{9.3cm}r}
7 +\toprule
8 +Quantity & Value \\
9 +\midrule
10 +\multicolumn{2}{l}{\itshape Panel A: rows removed from the ledger after the credit-exhaustion outage (research log: 149{,}352)} \\
11 +Sections reported complete by the October log, all batches ($\sum$ ``Extraction complete'') & 1{,}117{,}479 \\
12 +Sections pending at the second start of the run & 968{,}127 \\
13 +Difference = sections ledgered during the outage and re-submitted & 149{,}352 \\
14 +Ledger rows with a timestamp inside the largest gap (01:25--06:40, 5.25~h) & 0 \\
15 +Log batches returning zero mentions inside the outage window (batch ids 47--60) & 14 \\
16 +\midrule
17 +\multicolumn{2}{l}{\itshape Panel B: failed-call lines in the October log (94{,}609 lines; the ledger records none of them)} \\
18 +Retryable HTTP 429/5xx inside the outage window 01:10--06:22 & 94{,}593 \\
19 +Retryable HTTP 429/5xx in the outage tail (first ledger window definition, 20 s after the log window) & 128 \\
20 +Connection resets & 2 \\
21 +JSON-decode failures outside the outage (ledgered as ``no project'': silent empty results) & 14 \\
22 +``Section failed'' lines & 0 \\
23 +JSON-decode failures in the June log (of 153{,}894 sections) & 3 \\
24 +\midrule
25 +\multicolumn{2}{l}{\itshape Panel C: first batch after the resume (06:38--06:40, 19 issuers)} \\
26 +Sections in the batch (log) / ledgered rows & 5{,}198 / 4{,}769 \\
27 +Gate-passing calls & 2{,}686 \\
28 +Productive sections observed & 23 \\
29 +Productive sections expected at the form $\times$ item rates of the rest of the run & 536.2 \\
30 +Failed-call lines logged inside the batch window & 0 \\
31 +\bottomrule
32 +\end{tabular}
33 +\begin{tablenotes}\footnotesize
34 +\item Panel A reconciles the research log's figure with the run log and the ledger timestamps; the ledger stamps every row individually (968{,}134 distinct timestamps), so the per-flush test proposed at review is replaced by per-minute and per-batch productivity tests (\texttt{results/ledger/}). Panel B classifies the ``LLM call failed'' lines of the log by reason; a JSON-decode failure returns an empty list that the ledger records as zero mentions, indistinguishable from ``no project''. Panel C: the first batch after the resume returned 23 productive sections where 536 were expected, with no failure logged, which is consistent with HTTP-200 empty answers while the quota was being restored; only a re-submission of its gate-passing sections (authorisation request AR-LLM-4, not granted in this revision) can separate ``no project'' from ``empty answer''. Expected counts apply the productive share of each form $\times$ item outside the batch to the batch's calls.
35 +\end{tablenotes}
36 +\end{threeparttable}
37 +\end{table}
modified paper/tables/tab_overmerge.tex +36 −23
@@ -1,27 +1,40 @@
1 −\begin{tabular}{lrrrrrrr}
1 +% Generated by code/make_tables.py from results/resolver/overmerge\_by\_type.csv, composition.json. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\scriptsize
4 +\setlength{\tabcolsep}{3pt}
5 +\caption{Over-merge indicators of the resolution key, by category}\label{tab:overmerge}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
8 +\begin{tabular}{lrrrrr}
2 9 \toprule
3 −project\_type & projects & mentions & pct\_ge3\_names & pct\_ge2\_names & pct\_ge3\_partners\_among\_with\_partner & n\_ge3\_partners & pct\_multi\_all\_names\_distinct \\
10 +Category & Projects & \multicolumn{1}{c}{\makecell{$\geq 2$ distinct\\names (\%)}} & \multicolumn{1}{c}{\makecell{$\geq 3$ distinct\\names (\%)}} & \multicolumn{1}{c}{\makecell{$\geq 3$ distinct first partners\\(\% of projects with a partner)}} & \multicolumn{1}{c}{\makecell{All names distinct\\(\% of multi-mention)}} \\
4 11 \midrule
5 −ma\_integration & 41{,}742 & 130{,}259 & 14.63 & 30.93 & 10.92 & 2{,}289 & 30.24 \\
6 −capex\_program & 10{,}720 & 19{,}211 & 6.4 & 19.43 & 4.13 & 189 & 38.86 \\
7 −partnership & 9{,}909 & 17{,}501 & 6.74 & 19.66 & 4.3 & 281 & 38.57 \\
8 −geographic\_expansion & 7{,}868 & 17{,}713 & 10.18 & 25.23 & 1.88 & 14 & 35.76 \\
9 −plant\_construction & 7{,}590 & 18{,}388 & 13.49 & 30.3 & 4.04 & 62 & 34.68 \\
10 −cost\_reduction & 6{,}481 & 13{,}157 & 5.71 & 17.47 & 1.59 & 4 & 26.39 \\
11 −drug\_pipeline & 5{,}360 & 26{,}755 & 27.85 & 46.19 & 11.97 & 238 & 28.07 \\
12 −product\_launch & 5{,}356 & 12{,}456 & 12.23 & 27.97 & 3.38 & 23 & 37.89 \\
13 −rd\_program & 5{,}080 & 11{,}758 & 11.44 & 27.52 & 3.59 & 32 & 30.05 \\
14 −infrastructure & 4{,}481 & 8{,}510 & 7.5 & 20.78 & 2.17 & 21 & 38.05 \\
15 −manufacturing\_expansion & 4{,}140 & 8{,}825 & 11.26 & 27.08 & 2.17 & 11 & 34.79 \\
16 −technology\_deployment & 4{,}128 & 6{,}725 & 4.77 & 15.79 & 1.78 & 17 & 34.48 \\
17 −digital\_transformation & 2{,}642 & 5{,}249 & 6.25 & 19.3 & 0.0 & 0 & 25.92 \\
18 −erp\_implementation & 1{,}735 & 4{,}242 & 3.46 & 17.23 & 1.41 & 1 & 12.86 \\
19 −sustainability & 1{,}305 & 2{,}607 & 6.13 & 15.17 & 1.06 & 2 & 26.77 \\
20 −supply\_chain & 684 & 1{,}171 & 3.51 & 15.06 & 1.0 & 1 & 26.96 \\
21 −data\_center & 449 & 889 & 9.35 & 26.06 & 3.64 & 6 & 46.54 \\
22 −energy\_transition & 415 & 866 & 10.12 & 24.34 & 1.57 & 2 & 38.41 \\
23 −ai\_initiative & 376 & 632 & 4.79 & 16.22 & 0.0 & 0 & 27.83 \\
24 −automation & 374 & 630 & 2.67 & 13.1 & 4.17 & 1 & 28.04 \\
25 −cloud\_migration & 264 & 521 & 5.68 & 17.05 & 0.0 & 0 & 21.88 \\
12 +M\&A / integration & 41{,}742 & 30.9 & 14.6 & 10.9 & 30.2 \\
13 +Capital expenditure program & 10{,}720 & 19.4 & 6.4 & 4.1 & 38.9 \\
14 +Strategic partnership & 9{,}909 & 19.7 & 6.7 & 4.3 & 38.6 \\
15 +Geographic expansion & 7{,}868 & 25.2 & 10.2 & 1.9 & 35.8 \\
16 +Plant / site construction & 7{,}590 & 30.3 & 13.5 & 4.0 & 34.7 \\
17 +Cost reduction / restructuring & 6{,}481 & 17.5 & 5.7 & 1.6 & 26.4 \\
18 +Drug / clinical pipeline & 5{,}360 & 46.2 & 27.9 & 12.0 & 28.1 \\
19 +New product / launch & 5{,}356 & 28.0 & 12.2 & 3.4 & 37.9 \\
20 +R\&D program & 5{,}080 & 27.5 & 11.4 & 3.6 & 30.1 \\
21 +Infrastructure investment & 4{,}481 & 20.8 & 7.5 & 2.2 & 38.1 \\
22 +Manufacturing / capacity expansion & 4{,}140 & 27.1 & 11.3 & 2.2 & 34.8 \\
23 +Technology deployment & 4{,}128 & 15.8 & 4.8 & 1.8 & 34.5 \\
24 +Digital transformation & 2{,}642 & 19.3 & 6.3 & 0.0 & 25.9 \\
25 +ERP / systems implementation & 1{,}735 & 17.2 & 3.5 & 1.4 & 12.9 \\
26 +Sustainability / ESG & 1{,}305 & 15.2 & 6.1 & 1.1 & 26.8 \\
27 +Supply-chain initiative & 684 & 15.1 & 3.5 & 1.0 & 27.0 \\
28 +Data center & 449 & 26.1 & 9.4 & 3.6 & 46.5 \\
29 +Energy transition / renewables & 415 & 24.3 & 10.1 & 1.6 & 38.4 \\
30 +AI / ML initiative & 376 & 16.2 & 4.8 & 0.0 & 27.8 \\
31 +Automation / robotics & 374 & 13.1 & 2.7 & 4.2 & 28.0 \\
32 +Cloud migration & 264 & 17.1 & 5.7 & 0.0 & 21.9 \\
26 33 \bottomrule
27 34 \end{tabular}
35 +\end{adjustbox}
36 +\begin{tablenotes}\footnotesize
37 +\item Distinct names and partners are counted over the mentions of each project (lower-cased); three or more distinct counterparties in one M\&A project is an over-merge by construction. For 1{,}630 of 12{,}372 M\&A projects in which both are named, the project amount comes from a mention naming a different counterparty than the representative mention. These are indicators, not error rates: the linkage audit of gate (d) has not been run.
38 +\end{tablenotes}
39 +\end{threeparttable}
40 +\end{table}
modified paper/tables/tab_provenance.tex +15 −2
@@ -1,6 +1,13 @@
1 −\begin{tabular}{llllp{6.2cm}}
1 +% Generated by code/make_tables.py from data/example\_provenance.csv, documented\_inputs.json:snippet\_chars. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\scriptsize
4 +\setlength{\tabcolsep}{3pt}
5 +\caption{Provenance of one resolved project: Cheniere Energy, Corpus Christi liquefaction (project \texttt{3e2705ba\ldots})}\label{tab:provenance}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
8 +\begin{tabular}{lllp{2.1cm}p{5.4cm}}
2 9 \toprule
3 −Accession & Filed & Form & Status / amount & Evidence snippet (model-generated description grounded in the section) \\
10 +Accession & Filed & Form & Status / amount & Evidence snippet (model-generated description) \\
4 11 \midrule
5 12 \texttt{0000003570-14-000070} & 2014-04-08 & 8-K & planned / -- & The construction of the first liquefaction train at the Corpus Christi Liquefaction facility is contingent upon receiving regulatory approvals and securing financing. \\
6 13 \texttt{0000003570-14-000114} & 2014-05-30 & 8-K & planned / -- & CCLNG will construct a second liquefaction train at its facility to sell LNG to IBERDROLA under a long-term agreement. \\
@@ -12,3 +19,9 @@ Accession & Filed & Form & Status / amount & Evidence snippet (model-generated d
12 19 \texttt{0000003570-22-000029} & 2022-03-07 & 8-K & in\_progress / 5.5 B USD & The project involves the engineering, procurement, construction, pre-commissioning, commissioning, start-up, and testing of a mid-scale natural gas liquefaction facility \\
13 20 \bottomrule
14 21 \end{tabular}
22 +\end{adjustbox}
23 +\begin{tablenotes}\footnotesize
24 +\item Snippets are the first 170 characters of the model-generated description stored in \texttt{project\_timeline.snippet}; the description is a paraphrase, not a quotation, and the character span of the supporting passage is not stored; the full source section is retrievable through \texttt{project\_mentions.section\_id}. All 8 printed mentions are 8-K filings. The representative name is that of the highest-confidence mention (filed 2022) applied retroactively to the whole timeline, and is one admissible choice among mentions tied at the maximum confidence. The key for this issuer and type is the location token ``corpus christi'', so distinct phases share one identifier: the same mentions form 198488 projects under the strict key and 21027 under the issuer $\times$ type key (cluster sizes in Table~\ref{tab:spec_curve}).
25 +\end{tablenotes}
26 +\end{threeparttable}
27 +\end{table}
modified paper/tables/tab_reconciliation.tex +14 −1
@@ -1,4 +1,9 @@
1 −\begin{tabular}{lr}
1 +% Generated by code/make_tables.py from data/stats.json (universe), data/documented\_inputs.json, results/russell\_coverage.json, results/universe/universe\_artefacts.json. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\small
4 +\caption{Universe-to-dataset reconciliation: from the two constituent lists to issuers with resolved projects}\label{tab:reconciliation}
5 +\begin{threeparttable}
6 +\begin{tabular}{p{11.6cm}r}
2 7 \toprule
3 8 Step & Count \\
4 9 \midrule
@@ -12,8 +17,16 @@ Merged issuer universe (distinct CIKs) & 2{,}564 \\
12 17 \quad S\&P~500 only & 9 \\
13 18 \quad Russell proxy only & 2{,}064 \\
14 19 \midrule
20 +Russell~3000 index constituents, FTSE Russell factsheet as of 2026-09-30 & 2{,}996 \\
21 +\quad coverage of the index by the proxy (distinct CIKs / constituents, \%) & 85.3 \\
22 +\midrule
15 23 Issuers with at least one 10-K, 10-Q or 8-K since 2010 & 2{,}499 \\
16 24 Issuers without any such filing (foreign private issuers filing 20-F/40-F, FDIC-only banks) & 65 \\
17 25 Issuers with at least one resolved project & 2{,}492 \\
18 26 \bottomrule
19 27 \end{tabular}
28 +\begin{tablenotes}\footnotesize
29 +\item Sources: \texttt{data/metadata/universe.json}, \texttt{russell3000\_constituents.json}, \texttt{sp500\_constituents.json} (SHA-256 prefixes: \texttt{universe.json} 3967b29b378e\ldots; \texttt{russell3000\_constituents.json} 758cbebf5854\ldots; \texttt{sp500\_constituents.json} 508407526069\ldots; full digests in Table~\ref{tab:universe_artefacts}) and the merged DuckDB database. The first row is the count reported by the build log of \texttt{scripts/build\_universe.py}; the iShares holdings file and the SEC \texttt{company\_tickers.json} used by the build were not archived, so this count and the dropped non-company lines are not reconstructible (Section~\ref{sec:sample}). The mapped lines collapse to fewer CIKs because 18 dual-class registrants appear twice; 7 tickers have no CIK in the SEC map (TOWN, FRBA, NBN, HIFS, ADRO, THRD, HOLX). The index count is the ``Number of Holdings'' of the FTSE Russell factsheet (SHA-256 281e92643781\ldots); the fund tracks the index by representative sampling, so the omitted constituents cannot be identified without the licensed constituent list. The 65 issuers without filings are listed in \texttt{data/issuers\_without\_filings.csv} (foreign private issuers filing Forms 20-F/40-F and banks filing with the FDIC); 7 issuers have filings but no resolved project.
30 +\end{tablenotes}
31 +\end{threeparttable}
32 +\end{table}
added paper/tables/tab_rules_agreement.tex +32 −0
@@ -0,0 +1,32 @@
1 +% Generated by code/make_tables.py from results/rules/agreement\_by\_form.csv, agreement\_overall.csv, focus\_recall\_loss.csv. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\scriptsize
4 +\setlength{\tabcolsep}{3pt}
5 +\caption{Rule-based extractor versus LLM: section-level agreement on a stratified sample, and the recall bound of the focus windows}\label{tab:rules_agreement}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
8 +\begin{tabular}{lrrrrrrr}
9 +\toprule
10 +\multicolumn{8}{l}{\itshape Panel A: section-level agreement between the rule-based extractor and the LLM (weighted to the ledger)} \\
11 +Form & \multicolumn{1}{c}{\makecell{Sections\\sampled}} & \multicolumn{1}{c}{\makecell{P(rules $\geq 1 \mid$\\LLM $\geq 1$) \%}} & \multicolumn{1}{c}{\makecell{P(LLM $\geq 1 \mid$\\rules $\geq 1$) \%}} & \multicolumn{1}{c}{\makecell{Rules\\positive \%}} & \multicolumn{1}{c}{\makecell{LLM\\positive \%}} & \multicolumn{1}{c}{\makecell{Agreement\\\%}} & \multicolumn{1}{c}{\makecell{Same type on\\co-detected \%}} \\
12 +\midrule
13 +10-K & 8{,}890 & 97.4 & 28.2 & 73.9 & 21.4 & 46.4 & 86.2 \\
14 +10-Q & 29{,}399 & 94.4 & 28.7 & 43.5 & 13.3 & 68.2 & 87.8 \\
15 +8-K & 21{,}711 & 69.2 & 48.6 & 21.6 & 15.2 & 84.2 & 77.9 \\
16 +All forms & 60{,}000 & 85.7 & 32.5 & 39.5 & 15.0 & 71.2 & 84.6 \\
17 +\midrule
18 +\multicolumn{8}{l}{\itshape Panel B: rule mentions recovered inside the focus windows, sections over the 9{,}000-character budget} \\
19 +Form & \multicolumn{1}{c}{\makecell{Sections over\\budget (sample)}} & \multicolumn{1}{c}{\makecell{Rule mentions,\\full text}} & \multicolumn{1}{c}{\makecell{Rule mentions,\\focused text}} & \multicolumn{1}{c}{\makecell{Recovered\\\%}} & & & \\
20 +\midrule
21 +10-K & 6{,}482 & 97{,}830 & 24{,}462 & 25.0 & & & \\
22 +10-Q & 15{,}449 & 219{,}560 & 54{,}612 & 24.9 & & & \\
23 +8-K & 2{,}997 & 6{,}847 & 5{,}767 & 84.2 & & & \\
24 +All forms & 24{,}928 & 324{,}237 & 84{,}841 & 26.2 & & & \\
25 +\bottomrule
26 +\end{tabular}
27 +\end{adjustbox}
28 +\begin{tablenotes}\footnotesize
29 +\item Seeded stratified sample of 60{,}000 ledgered sections (30{,}000 with at least one LLM mention and the same number without), weighted back to the 1{,}123{,}098 ledger rows by inverse inclusion probability; the snapshot's \texttt{RuleExtractor} was run on the stored text. The two extractors have different constructs (the rules flag any gate-vocabulary sentence), so agreement is not accuracy and neither extractor is the reference. Panel B runs the rules on the full text and on the focused text of the same over-budget sections: the share recovered is a deterministic upper bound on what any extractor can see through the focus windows, not a recall estimate for the LLM.
30 +\end{tablenotes}
31 +\end{threeparttable}
32 +\end{table}
modified paper/tables/tab_sections.tex +14 −1
@@ -1,6 +1,13 @@
1 +% Generated by code/make_tables.py from data/sections\_by\_form.csv, ledger\_by\_form.csv, mentions\_by\_form.csv, results/ledger/table3\_ledger\_vs\_stored.csv, ledger\_collisions.csv. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\scriptsize
4 +\setlength{\tabcolsep}{3pt}
5 +\caption{Parsed sections, extraction ledger, gate-passing calls and mentions, by form}\label{tab:sections}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
1 8 \begin{tabular}{lrrrrrrrr}
2 9 \toprule
3 −Form & Parsed sections & Median words & Ledgered sections ($\geq$ 30 words) & Gate-passing calls & Sections with $\geq 1$ mention & Mentions returned by the model (ledger) & Mentions stored & Issuers \\
10 +Form & \multicolumn{1}{c}{\makecell{Parsed\\sections}} & \multicolumn{1}{c}{\makecell{Median\\words}} & \multicolumn{1}{c}{\makecell{Ledgered rows\\($\geq 30$ words)}} & \multicolumn{1}{c}{\makecell{Gate-passing\\calls}} & \multicolumn{1}{c}{\makecell{Sections with\\$\geq 1$ mention}} & \multicolumn{1}{c}{\makecell{Mentions returned\\(ledger, before de-dup.)}} & \multicolumn{1}{c}{\makecell{Mentions\\stored}} & \multicolumn{1}{c}{\makecell{Issuers\\ledgered}} \\
4 11 \midrule
5 12 10-K & 341{,}207 & 875 & 143{,}704 & 135{,}310 & 30{,}877 & 81{,}622 & 81{,}495 & 2{,}464 \\
6 13 10-Q & 600{,}471 & 500 & 578{,}793 & 363{,}973 & 75{,}705 & 152{,}261 & 152{,}004 & 2{,}494 \\
@@ -9,3 +16,9 @@ Form & Parsed sections & Median words & Ledgered sections ($\geq$ 30 words) & Ga
9 16 Total & 1{,}342{,}283 & & 1{,}123{,}098 & 703{,}725 & 168{,}230 & 308{,}477 & 308{,}065 & 2{,}499$^{\dagger}$ \\
10 17 \bottomrule
11 18 \end{tabular}
19 +\end{adjustbox}
20 +\begin{tablenotes}\footnotesize
21 +\item ``Ledgered rows'' counts rows of the \texttt{extracted\_sections} ledger (parsed sections with at least 30 words; for 10-Ks restricted to the items of Table~\ref{tab:items}); the ledger records neither whether the candidate gate passed nor whether the API call succeeded, so it is not a count of calls. ``Gate-passing calls'' recomputes the candidate gate of Appendix~\ref{app:prompt} over the ledgered text: 703{,}725 sections reached the model and 419{,}361 were ledgered with zero mentions without a call (Table~\ref{tab:ledger_calls} splits them by run). ``Mentions returned'' is $\sum$\texttt{n\_mentions} over the ledger (308{,}477); ``Mentions stored'' is the row count of \texttt{project\_mentions} (308{,}065). The difference of 412 (10-K 127, 10-Q 257, 8-K 28), spread over 304 sections, is the number of mentions overwritten before storage because the mention identifier hashes the type and the first 40 characters of the project name (Section~\ref{sec:construct}); every count in the text uses the stored basis unless labelled ``ledger''. $^{\dagger}$Issuers with at least one filing of any form, not a column sum.
22 +\end{tablenotes}
23 +\end{threeparttable}
24 +\end{table}
modified paper/tables/tab_sectors.tex +13 −1
@@ -1,6 +1,11 @@
1 +% Generated by code/make_tables.py from data/projects\_by\_sector.csv, companies\_by\_sector.csv. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\small
4 +\caption{Issuers and resolved projects by sector}\label{tab:sectors}
5 +\begin{threeparttable}
1 6 \begin{tabular}{lrrrrr}
2 7 \toprule
3 −GICS sector (iShares) & Issuers in universe & of which S\&P~500 & Issuers with projects & Projects & Projects per issuer \\
8 +GICS sector (iShares) & \multicolumn{1}{c}{\makecell{Issuers in\\universe}} & \multicolumn{1}{c}{\makecell{of which\\S\&P~500}} & \multicolumn{1}{c}{\makecell{Issuers with\\projects}} & Projects & \multicolumn{1}{c}{\makecell{Projects\\per issuer}} \\
4 9 \midrule
5 10 Health Care & 433 & 59 & 429 & 23{,}679 & 55.2 \\
6 11 Industrials & 393 & 79 & 386 & 17{,}890 & 46.3 \\
@@ -13,5 +18,12 @@ Energy & 119 & 21 & 107 & 6{,}710 & 62.7 \\
13 18 Consumer Staples & 103 & 36 & 103 & 5{,}921 & 57.5 \\
14 19 Utilities & 68 & 31 & 66 & 4{,}920 & 74.5 \\
15 20 Communication Services & 105 & 20 & 101 & 4{,}520 & 44.8 \\
21 +\midrule
22 +Total & 2{,}564 & 500 & 2{,}492 & 121{,}099 & 48.6 \\
16 23 \bottomrule
17 24 \end{tabular}
25 +\begin{tablenotes}\footnotesize
26 +\item Sector labels come from the iShares holdings file (Russell proxy) or, for S\&P~500-only issuers, from the Wikipedia GICS table; ``Issuers in universe'' includes issuers without filings. Projects per issuer is projects divided by issuers with at least one project. The S\&P~500 issuers were extracted in two runs and with two 10-K segmenters (Table~\ref{tab:cohort}), so cross-sector differences in projects per issuer mix disclosure behaviour with run and volume effects.
27 +\end{tablenotes}
28 +\end{threeparttable}
29 +\end{table}
modified paper/tables/tab_spec_curve.tex +24 −47
@@ -1,51 +1,28 @@
1 −\begin{tabular}{lrrrrrrrr}
1 +% Generated by code/make_tables.py from results/resolver/spec\_curve.csv, composition.json, ties\_idempotence.json, top\_name\_tokens.csv. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\scriptsize
4 +\setlength{\tabcolsep}{3pt}
5 +\caption{Specification curve of the project count over alternative resolution keys and confidence thresholds}\label{tab:spec_curve}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
8 +\begin{tabular}{lrrrrrr}
2 9 \toprule
3 −key & threshold & projects & mentions & single\_mention\_pct & gt10\_mention\_pct & mean\_mentions & max\_cluster & example\_cluster\_size\_cheniere \\
10 +Resolution key & \multicolumn{1}{c}{\makecell{Projects\\($\geq 0.45$)}} & \multicolumn{1}{c}{\makecell{Single-mention\\projects (\%)}} & \multicolumn{1}{c}{\makecell{Projects with\\$> 10$ mentions (\%)}} & \multicolumn{1}{c}{\makecell{Mentions\\per project}} & \multicolumn{1}{c}{\makecell{Cheniere\\cluster size}} & \multicolumn{1}{c}{\makecell{Projects\\($\geq 0.9$)}} \\
4 11 \midrule
5 −k\_cik\_type & 0.45 & 21{,}027 & 308{,}065 & 20.69 & 29.82 & 14.651 & 399 & 176 \\
6 −k\_cik\_type & 0.6 & 21{,}001 & 306{,}454 & 20.74 & 29.76 & 14.592 & 399 & 176 \\
7 −k\_cik\_type & 0.7 & 20{,}878 & 303{,}175 & 20.76 & 29.48 & 14.521 & 399 & 175 \\
8 −k\_cik\_type & 0.8 & 20{,}053 & 281{,}241 & 21.63 & 28.19 & 14.025 & 375 & 171 \\
9 −k\_cik\_type & 0.9 & 16{,}562 & 207{,}150 & 25.35 & 24.03 & 12.508 & 343 & 106 \\
10 −k\_type\_dropped & 0.45 & 96{,}749 & 308{,}065 & 52.59 & 4.99 & 3.184 & 269 & 11 \\
11 −k\_type\_dropped & 0.6 & 96{,}438 & 306{,}454 & 52.61 & 4.96 & 3.178 & 269 & 11 \\
12 −k\_type\_dropped & 0.7 & 95{,}580 & 303{,}175 & 52.64 & 4.95 & 3.172 & 269 & 11 \\
13 −k\_type\_dropped & 0.8 & 89{,}818 & 281{,}241 & 53.07 & 4.84 & 3.131 & 269 & 11 \\
14 −k\_type\_dropped & 0.9 & 70{,}174 & 207{,}150 & 54.53 & 4.26 & 2.952 & 250 & 10 \\
15 −k\_current & 0.45 & 121{,}099 & 308{,}065 & 60.23 & 3.11 & 2.544 & 269 & 8 \\
16 −k\_current & 0.6 & 120{,}621 & 306{,}454 & 60.24 & 3.1 & 2.541 & 269 & 8 \\
17 −k\_current & 0.7 & 119{,}427 & 303{,}175 & 60.26 & 3.1 & 2.539 & 269 & 8 \\
18 −k\_current & 0.8 & 111{,}079 & 281{,}241 & 60.47 & 3.05 & 2.532 & 269 & 8 \\
19 −k\_current & 0.9 & 83{,}483 & 207{,}150 & 61.35 & 2.91 & 2.481 & 250 & 7 \\
20 −k\_current\_stopwords & 0.45 & 130{,}101 & 308{,}065 & 59.05 & 2.49 & 2.368 & 209 & 8 \\
21 −k\_current\_stopwords & 0.6 & 129{,}601 & 306{,}454 & 59.06 & 2.48 & 2.365 & 209 & 8 \\
22 −k\_current\_stopwords & 0.7 & 128{,}404 & 303{,}175 & 59.09 & 2.47 & 2.361 & 209 & 8 \\
23 −k\_current\_stopwords & 0.8 & 119{,}990 & 281{,}241 & 59.21 & 2.4 & 2.344 & 209 & 8 \\
24 −k\_current\_stopwords & 0.9 & 91{,}918 & 207{,}150 & 59.72 & 2.08 & 2.254 & 206 & 7 \\
25 −k\_city\_normalised & 0.45 & 123{,}246 & 308{,}065 & 56.83 & 2.84 & 2.5 & 212 & 8 \\
26 −k\_city\_normalised & 0.6 & 122{,}760 & 306{,}454 & 56.83 & 2.83 & 2.496 & 212 & 8 \\
27 −k\_city\_normalised & 0.7 & 121{,}588 & 303{,}175 & 56.84 & 2.82 & 2.493 & 212 & 8 \\
28 −k\_city\_normalised & 0.8 & 113{,}404 & 281{,}241 & 56.88 & 2.75 & 2.48 & 212 & 8 \\
29 −k\_city\_normalised & 0.9 & 86{,}347 & 207{,}150 & 57.02 & 2.42 & 2.399 & 209 & 7 \\
30 −k\_name\_only & 0.45 & 114{,}244 & 308{,}065 & 56.41 & 3.74 & 2.697 & 230 & 40 \\
31 −k\_name\_only & 0.6 & 113{,}779 & 306{,}454 & 56.41 & 3.73 & 2.693 & 230 & 40 \\
32 −k\_name\_only & 0.7 & 112{,}652 & 303{,}175 & 56.43 & 3.73 & 2.691 & 230 & 39 \\
33 −k\_name\_only & 0.8 & 104{,}680 & 281{,}241 & 56.44 & 3.72 & 2.687 & 230 & 39 \\
34 −k\_name\_only & 0.9 & 78{,}834 & 207{,}150 & 56.48 & 3.57 & 2.628 & 226 & 25 \\
35 −k\_two\_tokens & 0.45 & 145{,}697 & 308{,}065 & 62.96 & 1.74 & 2.114 & 209 & 8 \\
36 −k\_two\_tokens & 0.6 & 145{,}122 & 306{,}454 & 62.97 & 1.73 & 2.112 & 209 & 8 \\
37 −k\_two\_tokens & 0.7 & 143{,}667 & 303{,}175 & 62.95 & 1.72 & 2.11 & 209 & 8 \\
38 −k\_two\_tokens & 0.8 & 133{,}671 & 281{,}241 & 62.92 & 1.69 & 2.104 & 209 & 8 \\
39 −k\_two\_tokens & 0.9 & 100{,}490 & 207{,}150 & 62.93 & 1.51 & 2.061 & 206 & 7 \\
40 −k\_strict & 0.45 & 198{,}488 & 308{,}065 & 75.78 & 0.52 & 1.552 & 206 & 1 \\
41 −k\_strict & 0.6 & 197{,}673 & 306{,}454 & 75.8 & 0.51 & 1.55 & 206 & 1 \\
42 −k\_strict & 0.7 & 195{,}703 & 303{,}175 & 75.82 & 0.5 & 1.549 & 206 & 1 \\
43 −k\_strict & 0.8 & 182{,}052 & 281{,}241 & 75.92 & 0.49 & 1.545 & 206 & 1 \\
44 −k\_strict & 0.9 & 135{,}411 & 207{,}150 & 76.17 & 0.4 & 1.53 & 203 & 1 \\
45 −k\_mention\_level & 0.45 & 308{,}065 & 308{,}065 & 100.0 & 0.0 & 1.0 & 1 & 1 \\
46 −k\_mention\_level & 0.6 & 306{,}454 & 306{,}454 & 100.0 & 0.0 & 1.0 & 1 & 1 \\
47 −k\_mention\_level & 0.7 & 303{,}175 & 303{,}175 & 100.0 & 0.0 & 1.0 & 1 & 1 \\
48 −k\_mention\_level & 0.8 & 281{,}241 & 281{,}241 & 100.0 & 0.0 & 1.0 & 1 & 1 \\
49 −k\_mention\_level & 0.9 & 207{,}150 & 207{,}150 & 100.0 & 0.0 & 1.0 & 1 & 1 \\
12 +Issuer $\times$ type (no location, no name) & 21{,}027 & 20.7 & 29.8 & 14.65 & 176 & 16{,}562 \\
13 +Current key without the type & 96{,}749 & 52.6 & 5.0 & 3.18 & 11 & 70{,}174 \\
14 +Issuer $\times$ type $\times$ name token (location ignored) & 114{,}244 & 56.4 & 3.7 & 2.70 & 40 & 78{,}834 \\
15 +Current key (location, else name token) $\dagger$ & 121{,}099 & 60.2 & 3.1 & 2.54 & 8 & 83{,}483 \\
16 +Current key, city-normalised locations & 123{,}246 & 56.8 & 2.8 & 2.50 & 8 & 86{,}347 \\
17 +Current key, extended stop-word list & 130{,}101 & 59.1 & 2.5 & 2.37 & 8 & 91{,}918 \\
18 +Issuer $\times$ type $\times$ two name tokens & 145{,}697 & 63.0 & 1.7 & 2.11 & 8 & 100{,}490 \\
19 +Strict: full normalised name + location & 198{,}488 & 75.8 & 0.5 & 1.55 & 1 & 135{,}411 \\
20 +No resolution (one project per mention) & 308{,}065 & 100.0 & 0.0 & 1.00 & 1 & 207{,}150 \\
50 21 \bottomrule
51 22 \end{tabular}
23 +\end{adjustbox}
24 +\begin{tablenotes}\footnotesize
25 +\item Every key is applied to the same 308{,}065 stored mentions, rebuilt from \texttt{resolve.py} in a temporary table on the master node; $\dagger$ marks the key of the released \texttt{projects} table, whose identifier set is reproduced exactly. ``Cheniere cluster size'' is the number of projects formed by the mentions of the Table~\ref{tab:provenance} example. Thresholds drop mentions below the stated confidence before resolution. The project count is therefore a property of the key: 21{,}027--308{,}065 at the release threshold, and the single-mention share and projects-per-issuer statistics move with it. Under the current key 66{,}405 projects (54.8\%) are keyed on a name token because the mention has no location, 54{,}658 on a location and 286 on the fallback ``general''; the single token ``acquisition'' absorbs 40{,}407 mentions into 2{,}256 projects (Table~\ref{tab:top_name_tokens}). The stored table is not exactly reproducible: 33{,}820 projects have several mentions at the maximum confidence (\texttt{arg\_max} ties), and re-running the authors' SQL changes 394 representative names and 600 descriptions while reproducing every project identifier.
26 +\end{tablenotes}
27 +\end{threeparttable}
28 +\end{table}
modified paper/tables/tab_status.tex +13 −1
@@ -1,4 +1,9 @@
1 −\begin{tabular}{lr@{\hspace{2em}}lr@{\hspace{2em}}lr}
1 +% Generated by code/make_tables.py from data/projects\_by\_status.csv, mentions\_per\_project.csv, duration.csv, results/resolver/ties\_idempotence.json. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\small
4 +\caption{Latest status, number of mentions and span of cited years of resolved projects}\label{tab:status}
5 +\begin{threeparttable}
6 +\begin{tabular}{lr@{\hspace{1.6em}}lr@{\hspace{1.6em}}lr}
2 7 \toprule
3 8 Latest status & Projects & Mentions per project & Projects & Span of cited years & Projects \\
4 9 \midrule
@@ -7,5 +12,12 @@ Latest status & Projects & Mentions per project & Projects & Span of cited years
7 12 \texttt{planned} & 18{,}340 & 3-5 & 17{,}681 & 3-5 years & 8{,}697 \\
8 13 \texttt{mentioned} & 2{,}745 & 6-10 & 6{,}173 & $>$5 years & 10{,}326 \\
9 14 & & >10 & 3{,}769 & unknown years & 17{,}599 \\
15 +\midrule
16 +Total & 121{,}099 & & 121{,}099 & & 121{,}099 \\
10 17 \bottomrule
11 18 \end{tabular}
19 +\begin{tablenotes}\footnotesize
20 +\item Status is that of the project's latest mention by filing date, a snapshot of the last statement rather than the terminal fate (for 972 projects several mentions share the last filing date with different statuses, and the stored choice is one admissible value among ties). The span is the difference between the latest and earliest four-digit year cited in the mentions' text; it is unknown for 17{,}599 projects (14.5\%), so the shares quoted in the text, 64.9\% at zero span and 10.0\% above five years, are over the 103{,}500 projects with known years. Single-mention projects (60.2\%) mix false splits, one-off disclosures and false positives; projects above ten mentions are where false merges concentrate (Table~\ref{tab:spec_curve}).
21 +\end{tablenotes}
22 +\end{threeparttable}
23 +\end{table}
modified paper/tables/tab_taxonomy.tex +10 −0
@@ -1,3 +1,8 @@
1 +% Generated by code/make_tables.py from code/audit/spid\_snapshot/taxonomy.py. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\small
4 +\caption{The 21-category SPID project taxonomy}\label{tab:taxonomy}
5 +\begin{threeparttable}
1 6 \begin{tabular}{ll}
2 7 \toprule
3 8 Code & Label \\
@@ -25,3 +30,8 @@ Code & Label \\
25 30 \texttt{technology\_deployment} & Technology Deployment \\
26 31 \bottomrule
27 32 \end{tabular}
33 +\begin{tablenotes}\footnotesize
34 +\item Codes and labels read from \texttt{spid/taxonomy.py} of the frozen snapshot (\texttt{code/audit/spid\_snapshot/}, SHA-256 in \texttt{SHA256SUMS}); the labels are passed verbatim to the model in the order shown (Appendix~\ref{app:prompt}). A label outside the list is mapped by substring to the closest code or, failing that, to \texttt{technology\_deployment}.
35 +\end{tablenotes}
36 +\end{threeparttable}
37 +\end{table}
modified paper/tables/tab_timeseries_cohort.tex +34 −36
@@ -1,40 +1,38 @@
1 −\begin{tabular}{lrrrrrrrrrr}
1 +% Generated by code/make_tables.py from results/timeseries/first\_seen\_fixed\_cohort.csv, summary.json. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\scriptsize
4 +\setlength{\tabcolsep}{3pt}
5 +\caption{Mentions and projects first seen by filing year: all issuers versus a fixed issuer cohort and windowed keys}\label{tab:timeseries_cohort}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
8 +\begin{tabular}{lrrrrrrrrr}
2 9 \toprule
3 −series & year & issuers\_filing & mentions & issuers\_with\_mentions & mentions\_per\_issuer\_filing & first\_seen\_current\_key & first\_seen\_per\_issuer & first\_seen\_k3 & first\_seen\_k5 & flag \\
10 + & \multicolumn{5}{c}{All issuers filing in the year} & \multicolumn{4}{c}{Fixed cohort: issuers filing in every year 2010--2025} \\
11 +\cmidrule(lr){2-6}\cmidrule(lr){7-10}
12 +Year & Issuers & \multicolumn{1}{c}{\makecell{Mentions\\per issuer}} & \multicolumn{1}{c}{\makecell{First seen\\(current key)}} & \multicolumn{1}{c}{\makecell{First seen\\($k = 3$)}} & \multicolumn{1}{c}{\makecell{First seen\\($k = 5$)}} & Issuers & \multicolumn{1}{c}{\makecell{Mentions\\per issuer}} & \multicolumn{1}{c}{\makecell{First seen\\(current key)}} & \multicolumn{1}{c}{\makecell{First seen\\per issuer}} \\
4 13 \midrule
5 −all\_issuers & 2{,}010 & 1{,}392 & 11{,}908 & 1{,}224 & 8.55 & 7{,}835 & 5.63 & 7{,}835 & 7{,}835 & left-censored \\
6 −all\_issuers & 2{,}011 & 1{,}424 & 13{,}551 & 1{,}287 & 9.52 & 6{,}679 & 4.69 & 6{,}679 & 6{,}679 & \\
7 −all\_issuers & 2{,}012 & 1{,}472 & 14{,}302 & 1{,}333 & 9.72 & 6{,}444 & 4.38 & 6{,}444 & 6{,}444 & \\
8 −all\_issuers & 2{,}013 & 1{,}539 & 14{,}611 & 1{,}408 & 9.49 & 6{,}286 & 4.08 & 6{,}385 & 6{,}286 & \\
9 −all\_issuers & 2{,}014 & 1{,}619 & 16{,}274 & 1{,}490 & 10.05 & 6{,}732 & 4.16 & 7{,}004 & 6{,}732 & \\
10 −all\_issuers & 2{,}015 & 1{,}689 & 17{,}073 & 1{,}535 & 10.11 & 6{,}675 & 3.95 & 7{,}092 & 6{,}734 & \\
11 −all\_issuers & 2{,}016 & 1{,}744 & 16{,}429 & 1{,}579 & 9.42 & 6{,}240 & 3.58 & 6{,}710 & 6{,}372 & \\
12 −all\_issuers & 2{,}017 & 1{,}810 & 17{,}350 & 1{,}636 & 9.59 & 6{,}490 & 3.59 & 7{,}120 & 6{,}725 & \\
13 −all\_issuers & 2{,}018 & 1{,}893 & 18{,}064 & 1{,}737 & 9.54 & 6{,}815 & 3.6 & 7{,}529 & 7{,}115 & \\
14 −all\_issuers & 2{,}019 & 1{,}973 & 18{,}737 & 1{,}806 & 9.5 & 6{,}837 & 3.47 & 7{,}644 & 7{,}208 & \\
15 −all\_issuers & 2{,}020 & 2{,}089 & 17{,}970 & 1{,}919 & 8.6 & 7{,}212 & 3.45 & 8{,}010 & 7{,}649 & \\
16 −all\_issuers & 2{,}021 & 2{,}247 & 21{,}312 & 2{,}077 & 9.48 & 8{,}216 & 3.66 & 9{,}191 & 8{,}732 & \\
17 −all\_issuers & 2{,}022 & 2{,}291 & 22{,}720 & 2{,}105 & 9.92 & 8{,}158 & 3.56 & 9{,}135 & 8{,}689 & \\
18 −all\_issuers & 2{,}023 & 2{,}329 & 22{,}955 & 2{,}129 & 9.86 & 7{,}977 & 3.43 & 9{,}061 & 8{,}557 & \\
19 −all\_issuers & 2{,}024 & 2{,}387 & 22{,}503 & 2{,}204 & 9.43 & 7{,}819 & 3.28 & 8{,}954 & 8{,}500 & \\
20 −all\_issuers & 2{,}025 & 2{,}453 & 23{,}220 & 2{,}280 & 9.47 & 7{,}990 & 3.26 & 9{,}252 & 8{,}719 & \\
21 −all\_issuers & 2{,}026 & 2{,}498 & 19{,}086 & 2{,}260 & 7.64 & 6{,}694 & 2.68 & 7{,}778 & 7{,}342 & partial year \\
22 −fixed\_2010\_cohort & 2{,}010 & 1{,}389 & 11{,}889 & 1{,}221 & 8.56 & 7{,}819 & 5.63 & 7{,}819 & 7{,}819 & left-censored \\
23 −fixed\_2010\_cohort & 2{,}011 & 1{,}389 & 13{,}333 & 1{,}255 & 9.6 & 6{,}533 & 4.7 & 6{,}533 & 6{,}533 & \\
24 −fixed\_2010\_cohort & 2{,}012 & 1{,}389 & 13{,}775 & 1{,}262 & 9.92 & 6{,}125 & 4.41 & 6{,}125 & 6{,}125 & \\
25 −fixed\_2010\_cohort & 2{,}013 & 1{,}389 & 13{,}411 & 1{,}276 & 9.66 & 5{,}602 & 4.03 & 5{,}701 & 5{,}602 & \\
26 −fixed\_2010\_cohort & 2{,}014 & 1{,}389 & 13{,}999 & 1{,}285 & 10.08 & 5{,}583 & 4.02 & 5{,}852 & 5{,}583 & \\
27 −fixed\_2010\_cohort & 2{,}015 & 1{,}389 & 14{,}038 & 1{,}270 & 10.11 & 5{,}288 & 3.81 & 5{,}700 & 5{,}347 & \\
28 −fixed\_2010\_cohort & 2{,}016 & 1{,}389 & 13{,}093 & 1{,}275 & 9.43 & 4{,}810 & 3.46 & 5{,}260 & 4{,}941 & \\
29 −fixed\_2010\_cohort & 2{,}017 & 1{,}389 & 13{,}088 & 1{,}258 & 9.42 & 4{,}674 & 3.37 & 5{,}274 & 4{,}907 & \\
30 −fixed\_2010\_cohort & 2{,}018 & 1{,}389 & 13{,}035 & 1{,}271 & 9.38 & 4{,}719 & 3.4 & 5{,}373 & 5{,}009 & \\
31 −fixed\_2010\_cohort & 2{,}019 & 1{,}389 & 12{,}937 & 1{,}277 & 9.31 & 4{,}496 & 3.24 & 5{,}235 & 4{,}852 & \\
32 −fixed\_2010\_cohort & 2{,}020 & 1{,}389 & 11{,}371 & 1{,}294 & 8.19 & 4{,}380 & 3.15 & 5{,}069 & 4{,}779 & \\
33 −fixed\_2010\_cohort & 2{,}021 & 1{,}389 & 12{,}376 & 1{,}284 & 8.91 & 4{,}505 & 3.24 & 5{,}327 & 4{,}972 & \\
34 −fixed\_2010\_cohort & 2{,}022 & 1{,}389 & 12{,}870 & 1{,}273 & 9.27 & 4{,}447 & 3.2 & 5{,}224 & 4{,}902 & \\
35 −fixed\_2010\_cohort & 2{,}023 & 1{,}389 & 12{,}649 & 1{,}254 & 9.11 & 4{,}251 & 3.06 & 5{,}098 & 4{,}752 & \\
36 −fixed\_2010\_cohort & 2{,}024 & 1{,}389 & 12{,}170 & 1{,}277 & 8.76 & 4{,}085 & 2.94 & 4{,}953 & 4{,}663 & \\
37 −fixed\_2010\_cohort & 2{,}025 & 1{,}389 & 12{,}156 & 1{,}285 & 8.75 & 3{,}926 & 2.83 & 4{,}858 & 4{,}518 & \\
38 −fixed\_2010\_cohort & 2{,}026 & 1{,}389 & 9{,}792 & 1{,}244 & 7.05 & 3{,}192 & 2.3 & 3{,}958 & 3{,}697 & partial year \\
14 +2010$^{a}$ & 1{,}392 & 8.6 & 7{,}835 & 7{,}835 & 7{,}835 & 1{,}389 & 8.6 & 7{,}819 & 5.6 \\
15 +2011 & 1{,}424 & 9.5 & 6{,}679 & 6{,}679 & 6{,}679 & 1{,}389 & 9.6 & 6{,}533 & 4.7 \\
16 +2012 & 1{,}472 & 9.7 & 6{,}444 & 6{,}444 & 6{,}444 & 1{,}389 & 9.9 & 6{,}125 & 4.4 \\
17 +2013 & 1{,}539 & 9.5 & 6{,}286 & 6{,}385 & 6{,}286 & 1{,}389 & 9.7 & 5{,}602 & 4.0 \\
18 +2014 & 1{,}619 & 10.1 & 6{,}732 & 7{,}004 & 6{,}732 & 1{,}389 & 10.1 & 5{,}583 & 4.0 \\
19 +2015 & 1{,}689 & 10.1 & 6{,}675 & 7{,}092 & 6{,}734 & 1{,}389 & 10.1 & 5{,}288 & 3.8 \\
20 +2016 & 1{,}744 & 9.4 & 6{,}240 & 6{,}710 & 6{,}372 & 1{,}389 & 9.4 & 4{,}810 & 3.5 \\
21 +2017 & 1{,}810 & 9.6 & 6{,}490 & 7{,}120 & 6{,}725 & 1{,}389 & 9.4 & 4{,}674 & 3.4 \\
22 +2018 & 1{,}893 & 9.5 & 6{,}815 & 7{,}529 & 7{,}115 & 1{,}389 & 9.4 & 4{,}719 & 3.4 \\
23 +2019 & 1{,}973 & 9.5 & 6{,}837 & 7{,}644 & 7{,}208 & 1{,}389 & 9.3 & 4{,}496 & 3.2 \\
24 +2020 & 2{,}089 & 8.6 & 7{,}212 & 8{,}010 & 7{,}649 & 1{,}389 & 8.2 & 4{,}380 & 3.2 \\
25 +2021 & 2{,}247 & 9.5 & 8{,}216 & 9{,}191 & 8{,}732 & 1{,}389 & 8.9 & 4{,}505 & 3.2 \\
26 +2022 & 2{,}291 & 9.9 & 8{,}158 & 9{,}135 & 8{,}689 & 1{,}389 & 9.3 & 4{,}447 & 3.2 \\
27 +2023 & 2{,}329 & 9.9 & 7{,}977 & 9{,}061 & 8{,}557 & 1{,}389 & 9.1 & 4{,}251 & 3.1 \\
28 +2024 & 2{,}387 & 9.4 & 7{,}819 & 8{,}954 & 8{,}500 & 1{,}389 & 8.8 & 4{,}085 & 2.9 \\
29 +2025 & 2{,}453 & 9.5 & 7{,}990 & 9{,}252 & 8{,}719 & 1{,}389 & 8.8 & 3{,}926 & 2.8 \\
30 +2026$^{b}$ & 2{,}498 & 7.6 & 6{,}694 & 7{,}778 & 7{,}342 & 1{,}389 & 7.1 & 3{,}192 & 2.3 \\
39 31 \bottomrule
40 32 \end{tabular}
33 +\end{adjustbox}
34 +\begin{tablenotes}\footnotesize
35 +\item $^{a}$Left-censored year (a project under way before the corpus start is first seen at its first in-window filing); $^{b}$partial year (filings to 2026-10-27). ``First seen'' counts projects whose earliest mention falls in the year; the windowed keys split a current-key project into episodes whenever the gap between consecutive mentions exceeds $k$ years (131{,}823 episodes at $k = 3$ and 126{,}318 at $k = 5$ against 121{,}099 projects). The fixed cohort holds the issuer composition constant: its mentions per issuer are flat while its new projects per issuer fall, which is consistent with a time-invariant key attaching later mentions to existing projects, with a change in disclosure, or with both; the series do not discriminate between these readings.
36 +\end{tablenotes}
37 +\end{threeparttable}
38 +\end{table}
modified paper/tables/tab_top_issuers.tex +12 −2
@@ -1,3 +1,8 @@
1 +% Generated by code/make_tables.py from data/top\_issuers.csv. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\small
4 +\caption{Issuers with the most resolved projects}\label{tab:top_issuers}
5 +\begin{threeparttable}
1 6 \begin{tabular}{llr}
2 7 \toprule
3 8 Ticker & Issuer & Resolved projects \\
@@ -9,10 +14,15 @@ HAL & Halliburton & 201 \\
9 14 RIOT & Riot Platforms & 195 \\
10 15 EHC & Encompass Health & 191 \\
11 16 EBS & Emergent Biosolutions & 187 \\
12 −MUX & Mcewen Inc & 180 \\
13 17 CDE & Coeur Mining & 180 \\
18 +MUX & Mcewen Inc & 180 \\
14 19 CLSK & Cleanspark & 170 \\
15 −CWEN & Clearway Energy Inc Class C & 168 \\
16 20 ALK & Alaska Air Group Inc & 168 \\
21 +CWEN & Clearway Energy Inc Class C & 168 \\
17 22 \bottomrule
18 23 \end{tabular}
24 +\begin{tablenotes}\footnotesize
25 +\item Projects under the current resolution key; ties are ordered by ticker. Issuers whose business consists of enumerable sites (mines, wells, routes, data-center sites) accumulate projects by construction of the key, which keys on the first location or name token of each mention (Section~\ref{sec:resolution}).
26 +\end{tablenotes}
27 +\end{threeparttable}
28 +\end{table}
modified paper/tables/tab_top_name_tokens.tex +26 −22
@@ -1,27 +1,31 @@
1 +% Generated by code/make_tables.py from results/resolver/top\_name\_tokens.csv. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\small
4 +\caption{Most frequent name tokens used as resolution keys for location-less mentions}\label{tab:top_name_tokens}
5 +\begin{threeparttable}
1 6 \begin{tabular}{lrrrr}
2 7 \toprule
3 −name\_tok & mentions & projects & pct\_of\_tokenkeyed\_mentions & pct\_of\_tokenkeyed\_projects \\
8 +Name token (key) & Mentions & Projects & \multicolumn{1}{c}{\makecell{Share of token-keyed\\mentions (\%)}} & \multicolumn{1}{c}{\makecell{Share of token-keyed\\projects (\%)}} \\
4 9 \midrule
5 −acquisition & 40{,}407 & 2{,}256 & 21.35 & 3.39 \\
6 −share & 5{,}106 & 2{,}060 & 2.7 & 3.09 \\
7 −expansion & 2{,}645 & 1{,}171 & 1.4 & 1.76 \\
8 −stock & 2{,}624 & 1{,}146 & 1.39 & 1.72 \\
9 −investment & 2{,}054 & 1{,}086 & 1.09 & 1.63 \\
10 −merger & 3{,}357 & 895 & 1.77 & 1.34 \\
11 −sale & 2{,}694 & 842 & 1.42 & 1.26 \\
12 −development & 4{,}514 & 805 & 2.38 & 1.21 \\
13 −strategic & 1{,}358 & 629 & 0.72 & 0.94 \\
14 −capital & 2{,}295 & 562 & 1.21 & 0.84 \\
15 −integration & 1{,}436 & 558 & 0.76 & 0.84 \\
16 −credit & 635 & 473 & 0.34 & 0.71 \\
17 −restructuring & 1{,}650 & 468 & 0.87 & 0.7 \\
18 −research & 1{,}160 & 416 & 0.61 & 0.62 \\
19 −product & 1{,}004 & 386 & 0.53 & 0.58 \\
20 −private & 528 & 385 & 0.28 & 0.58 \\
21 −global & 1{,}096 & 375 & 0.58 & 0.56 \\
22 −business & 893 & 372 & 0.47 & 0.56 \\
23 −senior & 506 & 357 & 0.27 & 0.54 \\
24 −acquisitions & 935 & 354 & 0.49 & 0.53 \\
25 −\multicolumn{5}{l}{\ldots 30 more rows in \texttt{results/resolver/top\_name\_tokens.csv}} \\
10 +\texttt{acquisition} & 40{,}407 & 2{,}256 & 21.4 & 3.4 \\
11 +\texttt{share} & 5{,}106 & 2{,}060 & 2.7 & 3.1 \\
12 +\texttt{expansion} & 2{,}645 & 1{,}171 & 1.4 & 1.8 \\
13 +\texttt{stock} & 2{,}624 & 1{,}146 & 1.4 & 1.7 \\
14 +\texttt{investment} & 2{,}054 & 1{,}086 & 1.1 & 1.6 \\
15 +\texttt{merger} & 3{,}357 & 895 & 1.8 & 1.3 \\
16 +\texttt{sale} & 2{,}694 & 842 & 1.4 & 1.3 \\
17 +\texttt{development} & 4{,}514 & 805 & 2.4 & 1.2 \\
18 +\texttt{strategic} & 1{,}358 & 629 & 0.7 & 0.9 \\
19 +\texttt{capital} & 2{,}295 & 562 & 1.2 & 0.8 \\
20 +\texttt{integration} & 1{,}436 & 558 & 0.8 & 0.8 \\
21 +\texttt{credit} & 635 & 473 & 0.3 & 0.7 \\
22 +\texttt{restructuring} & 1{,}650 & 468 & 0.9 & 0.7 \\
23 +\texttt{research} & 1{,}160 & 416 & 0.6 & 0.6 \\
24 +\texttt{product} & 1{,}004 & 386 & 0.5 & 0.6 \\
26 25 \bottomrule
27 26 \end{tabular}
27 +\begin{tablenotes}\footnotesize
28 +\item The key for a mention without an extracted location is the first token of at least four letters in the normalised project name (after a short stop-word list). Generic head words therefore merge unrelated initiatives of the same issuer and type into one project; the full list is in \texttt{results/resolver/top\_name\_tokens.csv}.
29 +\end{tablenotes}
30 +\end{threeparttable}
31 +\end{table}
modified paper/tables/tab_types.tex +37 −24
@@ -1,29 +1,42 @@
1 −\begin{tabular}{llrrrrrrr}
1 +% Generated by code/make_tables.py from data/projects\_by\_type.csv, projects\_by\_type\_ci.csv, results/fp\_classes/table5\_restated\_excl\_financing.csv, results/resolver/overmerge\_by\_type.csv. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\scriptsize
4 +\setlength{\tabcolsep}{3pt}
5 +\caption{Resolved projects by taxonomy category: counts, financing-class restatement, disclosed amounts and over-merge indicator}\label{tab:types}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
8 +\begin{tabular}{lrrrrrrrr}
2 9 \toprule
3 −Code & Category & Projects & Share (\%) & With amount ($N$) & Median amount (M USD) & 95\% CI of the median & Mentions / project & $\geq 3$ distinct names (\%) \\
10 +Category & Projects & \multicolumn{1}{c}{\makecell{Share\\(\%)}} & \multicolumn{1}{c}{\makecell{Excl. financing\\class ($N$)}} & \multicolumn{1}{c}{\makecell{With\\amount ($N$)}} & \multicolumn{1}{c}{\makecell{Median amount\\(M USD)}} & \multicolumn{1}{c}{\makecell{95\% CI of\\the median}} & \multicolumn{1}{c}{\makecell{Mentions\\per project}} & \multicolumn{1}{c}{\makecell{$\geq 3$ distinct\\names (\%)}} \\
4 11 \midrule
5 −\texttt{ma\_integration} & M\&A / integration & 41{,}742 & 34.5 & 28{,}044 & 155.0 & -- & 3.12 & 14.6 \\
6 −\texttt{capex\_program} & Capital expenditure program & 10{,}720 & 8.9 & 9{,}452 & 300.0 & -- & 1.79 & 6.4 \\
7 −\texttt{partnership} & Strategic partnership & 9{,}909 & 8.2 & 2{,}943 & 75.0 & -- & 1.77 & 6.7 \\
8 −\texttt{geographic\_expansion} & Geographic expansion & 7{,}868 & 6.5 & 1{,}431 & 36.7 & -- & 2.25 & 10.2 \\
9 −\texttt{plant\_construction} & Plant / site construction & 7{,}590 & 6.3 & 2{,}511 & 56.0 & -- & 2.42 & 13.5 \\
10 −\texttt{cost\_reduction} & Cost reduction / restructuring & 6{,}481 & 5.4 & 4{,}378 & 50.0 & -- & 2.03 & 5.7 \\
11 −\texttt{drug\_pipeline} & Drug / clinical pipeline & 5{,}360 & 4.4 & 778 & 46.1 & -- & 4.99 & 27.9 \\
12 −\texttt{product\_launch} & New product / launch & 5{,}356 & 4.4 & 447 & 26.7 & -- & 2.33 & 12.2 \\
13 −\texttt{rd\_program} & R\&D program & 5{,}080 & 4.2 & 1{,}272 & 20.0 & -- & 2.31 & 11.4 \\
14 −\texttt{infrastructure} & Infrastructure investment & 4{,}481 & 3.7 & 1{,}694 & 48.0 & -- & 1.90 & 7.5 \\
15 −\texttt{manufacturing\_expansion} & Manufacturing / capacity expansion & 4{,}140 & 3.4 & 1{,}040 & 45.0 & -- & 2.13 & 11.3 \\
16 −\texttt{technology\_deployment} & Technology deployment & 4{,}128 & 3.4 & 1{,}219 & 135.0 & -- & 1.63 & 4.8 \\
17 −\texttt{digital\_transformation} & Digital transformation & 2{,}642 & 2.2 & 240 & 34.2 & -- & 1.99 & 6.2 \\
18 −\texttt{erp\_implementation} & ERP / systems implementation & 1{,}735 & 1.4 & 184 & 15.0 & -- & 2.44 & 3.5 \\
19 −\texttt{sustainability} & Sustainability / ESG & 1{,}305 & 1.1 & 410 & 34.4 & -- & 2.00 & 6.1 \\
20 −\texttt{supply\_chain} & Supply-chain initiative & 684 & 0.6 & 139 & 38.0 & -- & 1.71 & 3.5 \\
21 −\texttt{data\_center} & Data center & 449 & 0.4 & 129 & 166.0 & -- & 1.98 & 9.3 \\
22 −\texttt{energy\_transition} & Energy transition / renewables & 415 & 0.3 & 109 & 109.0 & -- & 2.09 & 10.1 \\
23 −\texttt{ai\_initiative} & AI / ML initiative & 376 & 0.3 & 20 & \textcolor{gray}{127.5} & -- & 1.68 & 4.8 \\
24 −\texttt{automation} & Automation / robotics & 374 & 0.3 & 25 & \textcolor{gray}{13.7} & -- & 1.68 & 2.7 \\
25 −\texttt{cloud\_migration} & Cloud migration & 264 & 0.2 & 35 & \textcolor{gray}{50.0} & -- & 1.97 & 5.7 \\
12 +M\&A / integration & 41{,}742 & 34.5 & 36{,}687 & 28{,}044 & 155.0 & [150.0{,} 161.5] & 3.12 & 14.6 \\
13 +Capital expenditure program & 10{,}720 & 8.9 & 4{,}519 & 9{,}452 & 300.0 & [300.0{,} 323.2] & 1.79 & 6.4 \\
14 +Strategic partnership & 9{,}909 & 8.2 & 9{,}548 & 2{,}943 & 75.0 & [60.0{,} 81.9] & 1.77 & 6.7 \\
15 +Geographic expansion & 7{,}868 & 6.5 & 7{,}850 & 1{,}431 & 36.7 & [30.1{,} 44.6] & 2.25 & 10.2 \\
16 +Plant / site construction & 7{,}590 & 6.3 & 7{,}557 & 2{,}511 & 56.0 & [50.0{,} 64.9] & 2.42 & 13.5 \\
17 +Cost reduction / restructuring & 6{,}481 & 5.4 & 5{,}397 & 4{,}378 & 50.0 & [45.0{,} 50.0] & 2.03 & 5.7 \\
18 +Drug / clinical pipeline & 5{,}360 & 4.4 & 5{,}355 & 778 & 46.1 & [35.5{,} 60.0] & 4.99 & 27.9 \\
19 +New product / launch & 5{,}356 & 4.4 & 5{,}353 & 447 & 26.7 & [22.0{,} 38.1] & 2.33 & 12.2 \\
20 +R\&D program & 5{,}080 & 4.2 & 5{,}073 & 1{,}272 & 20.0 & [18.4{,} 25.0] & 2.31 & 11.4 \\
21 +Infrastructure investment & 4{,}481 & 3.7 & 4{,}452 & 1{,}694 & 48.0 & [41.1{,} 55.0] & 1.90 & 7.5 \\
22 +Manufacturing / capacity expansion & 4{,}140 & 3.4 & 4{,}130 & 1{,}040 & 45.0 & [38.0{,} 53.2] & 2.13 & 11.3 \\
23 +Technology deployment & 4{,}128 & 3.4 & 3{,}824 & 1{,}219 & 135.0 & [120.0{,} 150.0] & 1.63 & 4.8 \\
24 +Digital transformation & 2{,}642 & 2.2 & 2{,}642 & 240 & 34.2 & [21.8{,} 50.0] & 1.99 & 6.2 \\
25 +ERP / systems implementation & 1{,}735 & 1.4 & 1{,}735 & 184 & 15.0 & [9.3{,} 21.0] & 2.44 & 3.5 \\
26 +Sustainability / ESG & 1{,}305 & 1.1 & 1{,}284 & 410 & 34.4 & [20.1{,} 45.0] & 2.00 & 6.1 \\
27 +Supply-chain initiative & 684 & 0.6 & 684 & 139 & 38.0 & [25.0{,} 75.0] & 1.71 & 3.5 \\
28 +Data center & 449 & 0.4 & 443 & 129 & 166.0 & [93.0{,} 375.0] & 1.98 & 9.3 \\
29 +Energy transition / renewables & 415 & 0.3 & 413 & 109 & 109.0 & [85.0{,} 254.0] & 2.09 & 10.1 \\
30 +AI / ML initiative & 376 & 0.3 & 376 & 20 & \textcolor{gray}{127.5} & \textcolor{gray}{[35.0{,} 612.5]} & 1.68 & 4.8 \\
31 +Automation / robotics & 374 & 0.3 & 374 & 25 & \textcolor{gray}{13.7} & \textcolor{gray}{[3.4{,} 38.4]} & 1.68 & 2.7 \\
32 +Cloud migration & 264 & 0.2 & 264 & 35 & \textcolor{gray}{50.0} & \textcolor{gray}{[9.4{,} 250.0]} & 1.97 & 5.7 \\
26 33 \midrule
27 − & Total & 121{,}099 & 100.1 & 56{,}500 & 128.5 & -- & 2.54 & \\
34 +Total & 121{,}099 & 100.1 & 107{,}960 & 56{,}500 & 128.5 & -- & 2.54 & \\
28 35 \bottomrule
29 36 \end{tabular}
37 +\end{adjustbox}
38 +\begin{tablenotes}\footnotesize
39 +\item Category codes are listed in Table~\ref{tab:taxonomy}. Shares are rounded to one decimal and sum to 100.1. ``Excl. financing class'' removes projects with at least one mention matching the repurchase / dividend / credit-facility / notes-offering pattern of Table~\ref{tab:fp_classes} (13{,}139 projects, 10.8\%); the two columns bracket the construct violation, they do not measure precision. ``With amount'' counts projects for which at least one mention carries a USD figure; ``median amount'' is the median across those projects of the largest amount cited (Section~\ref{sec:amounts} on why amounts are never summed). Medians printed in grey rest on fewer than 50 projects with an amount (\texttt{ai\_initiative}, \texttt{automation}, \texttt{cloud\_migration}) and should not be quoted without their $N$. The 95\% interval of the median is a percentile bootstrap over projects (B = 1{,}000, seed 20261105, \texttt{data/projects\_by\_type\_ci.csv}); an interval equal to the point estimate reflects the rounding of disclosed amounts to round numbers. ``$\geq 3$ distinct names'' is the share of the category's projects whose mentions carry three or more distinct project names, an over-merge indicator of the resolution key (Table~\ref{tab:spec_curve}). All counts are under the current resolution key at the 0.45 confidence threshold.
40 +\end{tablenotes}
41 +\end{threeparttable}
42 +\end{table}
added paper/tables/tab_universe_artefacts.tex +26 −0
@@ -0,0 +1,26 @@
1 +% Generated by code/make_tables.py from results/universe/universe\_artefacts.json, results/russell\_coverage.json. Do not edit by hand.
2 +\begin{table}[H]
3 +\centering\footnotesize
4 +\setlength{\tabcolsep}{3pt}
5 +\caption{Universe artefacts: file digests computed on the master node and release status}\label{tab:universe_artefacts}
6 +\begin{threeparttable}
7 +\begin{adjustbox}{max width=\textwidth}
8 +\begin{tabular}{p{3.4cm}p{5.5cm}rp{2.9cm}}
9 +\toprule
10 +Artefact & SHA-256 & Bytes & Shipped with the paper \\
11 +\midrule
12 +\texttt{universe.\allowbreak{}json} & \texttt{\scriptsize 3967b29b378e50fbbac139bfc9051207} \texttt{\scriptsize 49ff09dcf8ec5769c3fbb12cb1c016e2} & 839{,}099 & yes (data/metadata/) \\
13 +\texttt{russell3000\_\allowbreak{}constituents.\allowbreak{}json} & \texttt{\scriptsize 758cbebf58540230ede17fd35890336b} \texttt{\scriptsize a6bf9e29fad58e3792ce7134997c6b41} & 751{,}897 & yes (data/metadata/) \\
14 +\texttt{sp500\_\allowbreak{}constituents.\allowbreak{}json} & \texttt{\scriptsize 5084075260692130896c3c9a187223e2} \texttt{\scriptsize 870b8e73774b35d1e28763fe8ffddb7d} & 109{,}110 & yes (data/metadata/) \\
15 +\texttt{cik\_\allowbreak{}mapping.\allowbreak{}json} & \texttt{\scriptsize 7ec59b276cef779f8f714d29d7b77938} \texttt{\scriptsize ee3731f11ea5bd95526006fd03ed20fc} & 481{,}386 & no (hash only) \\
16 +\texttt{shards.\allowbreak{}json} & \texttt{\scriptsize 8351ff54bea877175ca4bba51fc043ba} \texttt{\scriptsize 279b2bfbcc7ddb80db1da534ff922771} & 57{,}411 & no (hash only) \\
17 +FTSE Russell factsheet (2026-09-30) & \texttt{\scriptsize 281e92643781cf19a3f4bc6a670e0719} \texttt{\scriptsize aa5ef1347d1071300491274aed0436e4} & -- & no (public URL) \\
18 +Russell US indexes methodology (v7.2) & \texttt{\scriptsize 26d2d051beb27a6a808af7c17a2e2871} \texttt{\scriptsize cc5388e669bedbb42cbc4d0d3ce47c76} & -- & no (public URL) \\
19 +\bottomrule
20 +\end{tabular}
21 +\end{adjustbox}
22 +\begin{tablenotes}\footnotesize
23 +\item Digests computed read-only on the master node (\texttt{results/universe/SHA256SUMS}); the three constituent files are shipped under \texttt{data/metadata/}. The iShares holdings CSV and the SEC \texttt{company\_tickers.json} consumed by the build were searched for on the node and not found (none): gate (a) of Table~\ref{tab:gates} is met for the frozen JSON artefacts only, not for their upstream sources. \texttt{cik\_mapping.json} and \texttt{shards.json} are hashed but not released (the latter names private cluster nodes); the URLs of the two public FTSE Russell documents are recorded in \texttt{results/russell\_coverage.json}.
24 +\end{tablenotes}
25 +\end{threeparttable}
26 +\end{table}
modified results/inline_numbers.json +3172 −57
@@ -4,6 +4,26 @@
4 4 "source": "count reported by the build log of scripts/build_universe.py (2026-10-27); the iShares latest-holdings.csv used by the build is not archived (verified on M3U96b, Stage D feasibility report); not reconstructible",
5 5 "formula": "documented input or stats.json"
6 6 },
7 + "russellIndexConstituents": {
8 + "value": "2{,}996",
9 + "source": "results/russell_coverage.json:index_constituents",
10 + "formula": "https://research.ftserussell.com/Analytics/FactSheets/Home/DownloadSingleIssue?issueName=US3000USD&isManual=True"
11 + },
12 + "russellProxyCoveragePct": {
13 + "value": "85.3",
14 + "source": "results/russell_coverage.json",
15 + "formula": "100 * russell_distinct_ciks / index_constituents"
16 + },
17 + "iwvHoldingsCount": {
18 + "value": "2{,}588",
19 + "source": "results/russell_coverage.json:fund_holdings_count",
20 + "formula": "https://www.ishares.com/us/products/239714/ishares-russell-3000-etf"
21 + },
22 + "iwvReplicationMethod": {
23 + "value": "representative sampling",
24 + "source": "results/russell_coverage.json:replication_method",
25 + "formula": "https://www.ishares.com/us/products/239714/ishares-russell-3000-etf"
26 + },
7 27 "universeN": {
8 28 "value": "2{,}564",
9 29 "source": "stats.json:universe.n",
@@ -24,25 +44,10 @@
24 44 "source": "stats.json:universe.russell_unmatched",
25 45 "formula": "len(unmatched)"
26 46 },
27 − "russellIndexConstituents": {
28 − "value": "2{,}996",
29 − "source": "results/russell_coverage.json:index_constituents",
30 − "formula": "https://research.ftserussell.com/Analytics/FactSheets/Home/DownloadSingleIssue?issueName=US3000USD&isManual=True"
31 − },
32 − "russellProxyCoveragePct": {
33 − "value": "85.3",
34 − "source": "results/russell_coverage.json",
35 − "formula": "100 * russell_distinct_ciks / index_constituents"
36 − },
37 − "iwvHoldingsCount": {
38 − "value": "2{,}588",
39 − "source": "results/russell_coverage.json:fund_holdings_count",
40 − "formula": "https://www.ishares.com/us/products/239714/ishares-russell-3000-etf"
41 − },
42 − "iwvReplicationMethod": {
43 − "value": "representative sampling",
44 − "source": "results/russell_coverage.json:replication_method",
45 − "formula": "https://www.ishares.com/us/products/239714/ishares-russell-3000-etf"
47 + "russellDualClassCiks": {
48 + "value": "18",
49 + "source": "stats.json:universe",
50 + "formula": "mapped lines - distinct CIKs"
46 51 },
47 52 "filingDateFirst": {
48 53 "value": "2010-01-04",
@@ -69,6 +74,11 @@
69 74 "source": "data/parse_status.csv",
70 75 "formula": "sum(missing)"
71 76 },
77 + "filingsParserError": {
78 + "value": "14",
79 + "source": "data/parse_status.csv",
80 + "formula": "sum(error)"
81 + },
72 82 "rawGb": {
73 83 "value": "254.5",
74 84 "source": "stats.json:raw_gb",
@@ -134,6 +144,16 @@
134 144 "source": "data/issuers_by_year.csv",
135 145 "formula": "max year (partial)"
136 146 },
147 + "issuersFilingFirstYear": {
148 + "value": "1{,}392",
149 + "source": "data/issuers_by_year.csv",
150 + "formula": "issuers in 2010"
151 + },
152 + "issuersFilingLastYear": {
153 + "value": "2{,}498",
154 + "source": "data/issuers_by_year.csv",
155 + "formula": "issuers in 2026"
156 + },
137 157 "callsOneZeroK": {
138 158 "value": "135{,}310",
139 159 "source": "results/ledger/table3_ledger_vs_stored.csv",
@@ -236,8 +256,8 @@
236 256 },
237 257 "gatePassTotal": {
238 258 "value": "703{,}725",
239 − "source": "stats.json:gate_pass_total",
240 − "formula": "regexp_matches(_PROJECT_GATE) over the ledger"
259 + "source": "results/ledger/gate_pass_totals.json:calls or stats.json:gate_pass_total",
260 + "formula": "gate-passing rows with >= 30 words (true calls)"
241 261 },
242 262 "productiveShareCalls": {
243 263 "value": "23.9",
@@ -249,6 +269,41 @@
249 269 "source": "results/ledger/gate_pass_totals.json",
250 270 "formula": "mentions_per_call"
251 271 },
272 + "gatePassRowsAll": {
273 + "value": "703{,}737",
274 + "source": "stats.json:gate_pass_total",
275 + "formula": "regexp_matches(_PROJECT_GATE) over all ledger rows"
276 + },
277 + "resumeBatchCalls": {
278 + "value": "2{,}686",
279 + "source": "results/ledger/resume_batch1_vs_expected.csv",
280 + "formula": "sum(calls)"
281 + },
282 + "resumeBatchProductive": {
283 + "value": "23",
284 + "source": "results/ledger/resume_batch1_vs_expected.csv",
285 + "formula": "sum(with_mentions)"
286 + },
287 + "resumeBatchExpected": {
288 + "value": "536",
289 + "source": "results/ledger/resume_batch1_vs_expected.csv",
290 + "formula": "sum(expected_with_mentions)"
291 + },
292 + "resumeBatchSections": {
293 + "value": "5{,}198",
294 + "source": "results/ledger/log_summary.json:october.resume_batch1.log_sections",
295 + "formula": "log"
296 + },
297 + "resumeBatchCiks": {
298 + "value": "19",
299 + "source": "results/ledger/log_summary.json",
300 + "formula": "len(ciks)"
301 + },
302 + "outageZeroBatches": {
303 + "value": "14",
304 + "source": "results/ledger/log_summary.json:october.anomalous_batches",
305 + "formula": "count"
306 + },
252 307 "tenKmdnaMentions": {
253 308 "value": "39{,}099",
254 309 "source": "data/ledger_10k_items.csv / ledger_10q_items.csv",
@@ -294,6 +349,51 @@
294 349 "source": "data/projects_by_type.csv",
295 350 "formula": "with_amount < 50"
296 351 },
352 + "projectsExclFinancing": {
353 + "value": "107{,}960",
354 + "source": "results/fp_classes/table5_restated_excl_financing.csv",
355 + "formula": "sum(n_excl_any)"
356 + },
357 + "projectsWithFinancingMention": {
358 + "value": "13{,}139",
359 + "source": "results/fp_classes/table5_restated_excl_financing.csv",
360 + "formula": "projects - sum(n_excl_any)"
361 + },
362 + "projectsWithFinancingMentionPct": {
363 + "value": "10.8",
364 + "source": "results/fp_classes/table5_restated_excl_financing.csv",
365 + "formula": "100*(projects - sum(n_excl_any))/projects"
366 + },
367 + "nExclFinancingCapexProgram": {
368 + "value": "4{,}519",
369 + "source": "results/fp_classes/table5_restated_excl_financing.csv",
370 + "formula": "n_excl_any where project_type=capex_program"
371 + },
372 + "shareExclFinancingCapexProgram": {
373 + "value": "4.2",
374 + "source": "results/fp_classes/table5_restated_excl_financing.csv",
375 + "formula": "pct_excl_any where project_type=capex_program"
376 + },
377 + "nExclFinancingCostReduction": {
378 + "value": "5{,}397",
379 + "source": "results/fp_classes/table5_restated_excl_financing.csv",
380 + "formula": "n_excl_any where project_type=cost_reduction"
381 + },
382 + "shareExclFinancingCostReduction": {
383 + "value": "5.0",
384 + "source": "results/fp_classes/table5_restated_excl_financing.csv",
385 + "formula": "pct_excl_any where project_type=cost_reduction"
386 + },
387 + "nExclFinancingMaIntegration": {
388 + "value": "36{,}687",
389 + "source": "results/fp_classes/table5_restated_excl_financing.csv",
390 + "formula": "n_excl_any where project_type=ma_integration"
391 + },
392 + "shareExclFinancingMaIntegration": {
393 + "value": "34.0",
394 + "source": "results/fp_classes/table5_restated_excl_financing.csv",
395 + "formula": "pct_excl_any where project_type=ma_integration"
396 + },
297 397 "shareDataCenter": {
298 398 "value": "0.4",
299 399 "source": "data/projects_by_type.csv",
@@ -314,6 +414,11 @@
314 414 "source": "data/projects_by_type.csv",
315 415 "formula": "median_amount_musd where project_type=data_center"
316 416 },
417 + "medianAmountCIDataCenter": {
418 + "value": "93.0--375.0",
419 + "source": "data/projects_by_type_ci.csv",
420 + "formula": "ci_low--ci_high where project_type=data_center"
421 + },
317 422 "shareAiInitiative": {
318 423 "value": "0.3",
319 424 "source": "data/projects_by_type.csv",
@@ -334,6 +439,11 @@
334 439 "source": "data/projects_by_type.csv",
335 440 "formula": "median_amount_musd where project_type=ai_initiative"
336 441 },
442 + "medianAmountCIAiInitiative": {
443 + "value": "35.0--612.5",
444 + "source": "data/projects_by_type_ci.csv",
445 + "formula": "ci_low--ci_high where project_type=ai_initiative"
446 + },
337 447 "shareCloudMigration": {
338 448 "value": "0.2",
339 449 "source": "data/projects_by_type.csv",
@@ -354,6 +464,11 @@
354 464 "source": "data/projects_by_type.csv",
355 465 "formula": "median_amount_musd where project_type=cloud_migration"
356 466 },
467 + "medianAmountCICloudMigration": {
468 + "value": "9.4--250.0",
469 + "source": "data/projects_by_type_ci.csv",
470 + "formula": "ci_low--ci_high where project_type=cloud_migration"
471 + },
357 472 "shareAutomation": {
358 473 "value": "0.3",
359 474 "source": "data/projects_by_type.csv",
@@ -374,6 +489,11 @@
374 489 "source": "data/projects_by_type.csv",
375 490 "formula": "median_amount_musd where project_type=automation"
376 491 },
492 + "medianAmountCIAutomation": {
493 + "value": "3.4--38.4",
494 + "source": "data/projects_by_type_ci.csv",
495 + "formula": "ci_low--ci_high where project_type=automation"
496 + },
377 497 "shareMaIntegration": {
378 498 "value": "34.5",
379 499 "source": "data/projects_by_type.csv",
@@ -394,6 +514,11 @@
394 514 "source": "data/projects_by_type.csv",
395 515 "formula": "median_amount_musd where project_type=ma_integration"
396 516 },
517 + "medianAmountCIMaIntegration": {
518 + "value": "150.0--161.5",
519 + "source": "data/projects_by_type_ci.csv",
520 + "formula": "ci_low--ci_high where project_type=ma_integration"
521 + },
397 522 "shareCapexProgram": {
398 523 "value": "8.9",
399 524 "source": "data/projects_by_type.csv",
@@ -414,6 +539,11 @@
414 539 "source": "data/projects_by_type.csv",
415 540 "formula": "median_amount_musd where project_type=capex_program"
416 541 },
542 + "medianAmountCICapexProgram": {
543 + "value": "300.0--323.2",
544 + "source": "data/projects_by_type_ci.csv",
545 + "formula": "ci_low--ci_high where project_type=capex_program"
546 + },
417 547 "sharePartnership": {
418 548 "value": "8.2",
419 549 "source": "data/projects_by_type.csv",
@@ -434,6 +564,11 @@
434 564 "source": "data/projects_by_type.csv",
435 565 "formula": "median_amount_musd where project_type=partnership"
436 566 },
567 + "medianAmountCIPartnership": {
568 + "value": "60.0--81.9",
569 + "source": "data/projects_by_type_ci.csv",
570 + "formula": "ci_low--ci_high where project_type=partnership"
571 + },
437 572 "shareGeographicExpansion": {
438 573 "value": "6.5",
439 574 "source": "data/projects_by_type.csv",
@@ -454,6 +589,11 @@
454 589 "source": "data/projects_by_type.csv",
455 590 "formula": "median_amount_musd where project_type=geographic_expansion"
456 591 },
592 + "medianAmountCIGeographicExpansion": {
593 + "value": "30.1--44.6",
594 + "source": "data/projects_by_type_ci.csv",
595 + "formula": "ci_low--ci_high where project_type=geographic_expansion"
596 + },
457 597 "sharePlantConstruction": {
458 598 "value": "6.3",
459 599 "source": "data/projects_by_type.csv",
@@ -474,6 +614,11 @@
474 614 "source": "data/projects_by_type.csv",
475 615 "formula": "median_amount_musd where project_type=plant_construction"
476 616 },
617 + "medianAmountCIPlantConstruction": {
618 + "value": "50.0--64.9",
619 + "source": "data/projects_by_type_ci.csv",
620 + "formula": "ci_low--ci_high where project_type=plant_construction"
621 + },
477 622 "techCategoriesCountRange": {
478 623 "value": "264--449",
479 624 "source": "data/projects_by_type.csv",
@@ -514,6 +659,66 @@
514 659 "source": "data/projects_by_sector.csv",
515 660 "formula": "issuers for Industrials"
516 661 },
662 + "cohortEffectAll": {
663 + "value": "8.8",
664 + "source": "results/runs/table6_cohort_regression.json",
665 + "formula": "projects_all_on_sp500.in_sp500.coef"
666 + },
667 + "cohortEffectAllSE": {
668 + "value": "1.62",
669 + "source": "results/runs/table6_cohort_regression.json",
670 + "formula": "projects_all_on_sp500.in_sp500.hc1_se"
671 + },
672 + "cohortEffectOctober": {
673 + "value": "-23.0",
674 + "source": "results/runs/table6_cohort_regression.json",
675 + "formula": "projects_october_only_on_sp500.in_sp500.coef"
676 + },
677 + "cohortEffectOctoberSE": {
678 + "value": "1.20",
679 + "source": "results/runs/table6_cohort_regression.json",
680 + "formula": "projects_october_only_on_sp500.in_sp500.hc1_se"
681 + },
682 + "cohortEffectVolumeControl": {
683 + "value": "-0.28",
684 + "source": "results/runs/table6_cohort_regression.json",
685 + "formula": "projects_all_on_sp500_log_rows.in_sp500.coef"
686 + },
687 + "cohortEffectVolumeControlSE": {
688 + "value": "1.52",
689 + "source": "results/runs/table6_cohort_regression.json",
690 + "formula": "projects_all_on_sp500_log_rows.in_sp500.hc1_se"
691 + },
692 + "perIssuerAllBoth": {
693 + "value": "55.8",
694 + "source": "results/runs/table6_cohort.csv",
695 + "formula": "per_issuer_all where cohort=both"
696 + },
697 + "perIssuerOctoberBoth": {
698 + "value": "25.1",
699 + "source": "results/runs/table6_cohort.csv",
700 + "formula": "per_issuer_october_only where cohort=both"
701 + },
702 + "perIssuerAllRussellOnly": {
703 + "value": "46.9",
704 + "source": "results/runs/table6_cohort.csv",
705 + "formula": "per_issuer_all where cohort=russell_only"
706 + },
707 + "perIssuerOctoberRussellOnly": {
708 + "value": "46.9",
709 + "source": "results/runs/table6_cohort.csv",
710 + "formula": "per_issuer_october_only where cohort=russell_only"
711 + },
712 + "perIssuerAllSpFiveZeroZeroOnly": {
713 + "value": "42.7",
714 + "source": "results/runs/table6_cohort.csv",
715 + "formula": "per_issuer_all where cohort=sp500_only"
716 + },
717 + "perIssuerOctoberSpFiveZeroZeroOnly": {
718 + "value": "13.1",
719 + "source": "results/runs/table6_cohort.csv",
720 + "formula": "per_issuer_october_only where cohort=sp500_only"
721 + },
517 722 "spanKnownN": {
518 723 "value": "103{,}500",
519 724 "source": "data/duration.csv",
@@ -574,6 +779,16 @@
574 779 "source": "data/mentions_per_project.csv",
575 780 "formula": "100*n(bucket=1)/projects"
576 781 },
782 + "twoMentionShare": {
783 + "value": "17.0",
784 + "source": "data/mentions_per_project.csv",
785 + "formula": "100*n(bucket=2)/projects"
786 + },
787 + "overFiveMentionShare": {
788 + "value": "8.2",
789 + "source": "data/mentions_per_project.csv",
790 + "formula": "100*(n(6-10)+n(>10))/projects"
791 + },
577 792 "overTenMentionShare": {
578 793 "value": "3.1",
579 794 "source": "data/mentions_per_project.csv",
@@ -594,6 +809,66 @@
594 809 "source": "data/confidence_dist.csv",
595 810 "formula": "100*n(conf<=0.6)/mentions"
596 811 },
812 + "confExactDefaultCount": {
813 + "value": "3{,}278",
814 + "source": "stats.json:conf_exact_default_count",
815 + "formula": "count(round(confidence,3)=0.600)"
816 + },
817 + "amountMaxBusd": {
818 + "value": "1{,}000.0",
819 + "source": "stats.json:amount_max",
820 + "formula": "max(total_amount_usd)/1e9"
821 + },
822 + "amountGeFiftyB": {
823 + "value": "104",
824 + "source": "stats.json:amount_ge_50b",
825 + "formula": "count(total_amount_usd >= 50e9)"
826 + },
827 + "amountLeZero": {
828 + "value": "259",
829 + "source": "stats.json:amount_le_zero",
830 + "formula": "count(total_amount_usd <= 0)"
831 + },
832 + "amountRawDeviations": {
833 + "value": "584",
834 + "source": "stats.json:amount_raw_deviations",
835 + "formula": "count(amount_raw is distinct from format(amount_usd))"
836 + },
837 + "amountMentionsGeFiftyB": {
838 + "value": "161",
839 + "source": "results/grounding/amount_tail.json",
840 + "formula": "ge_50e9"
841 + },
842 + "amountMentionsZero": {
843 + "value": "584",
844 + "source": "results/grounding/amount_tail.json",
845 + "formula": "eq_0"
846 + },
847 + "amountMentionsNegative": {
848 + "value": "24",
849 + "source": "results/grounding/amount_tail.json",
850 + "formula": "lt_0"
851 + },
852 + "amountProjectsGeFiftyB": {
853 + "value": "104",
854 + "source": "results/grounding/amount_tail.json",
855 + "formula": "projects_max_amount_ge_50e9"
856 + },
857 + "amountTopTwoHundredNumberFound": {
858 + "value": "191",
859 + "source": "results/grounding/amount_tail.json",
860 + "formula": "top200_grounded_number[0]"
861 + },
862 + "amountTopTwoHundredCurrency": {
863 + "value": "178",
864 + "source": "results/grounding/amount_tail.json",
865 + "formula": "top200_grounded_number[1]"
866 + },
867 + "amountNonUsdTokenShare": {
868 + "value": "1.6",
869 + "source": "results/grounding/amount_tail.json",
870 + "formula": "100*nonusd_within_40_share[0]/[1]"
871 + },
597 872 "amountMentions": {
598 873 "value": "120{,}240",
599 874 "source": "stats.json:mentions_fields[0]",
@@ -699,6 +974,11 @@
699 974 "source": "data/example_provenance.csv",
700 975 "formula": "filing year of the last mention (representative name source)"
701 976 },
977 + "provenanceProjectId": {
978 + "value": "3e2705ba",
979 + "source": "data/example_provenance.csv",
980 + "formula": "project_id[:8]"
981 + },
702 982 "gateRegexFlags": {
703 983 "value": "re.IGNORECASE",
704 984 "source": "code/audit/spid_snapshot/rules.py",
@@ -719,6 +999,746 @@
719 999 "source": "taxonomy.py:PROJECT_TYPES",
720 1000 "formula": "len"
721 1001 },
1002 + "yearsRegexEqualPct": {
1003 + "value": "39",
1004 + "source": "results/grounding/fallback_bounds.json",
1005 + "formula": "100*years_eq_regex_desc/years_nonempty"
1006 + },
1007 + "techsRegexEqualPct": {
1008 + "value": "46",
1009 + "source": "results/grounding/fallback_bounds.json",
1010 + "formula": "100*techs_eq_regex_desc/techs_nonempty"
1011 + },
1012 + "yearsNotInText": {
1013 + "value": "604",
1014 + "source": "results/grounding/fallback_bounds.json",
1015 + "formula": "years_not_subset_of_text"
1016 + },
1017 + "techDeployMentionedNoSignal": {
1018 + "value": "90",
1019 + "source": "results/grounding/fallback_bounds.json",
1020 + "formula": "tech_deploy_mentioned_no_any_signal"
1021 + },
1022 + "techDeployMentionedTotal": {
1023 + "value": "124",
1024 + "source": "results/grounding/fallback_bounds.json",
1025 + "formula": "tech_deploy_total[1]"
1026 + },
1027 + "groundedYearsPct": {
1028 + "value": "99.8",
1029 + "source": "results/grounding/grounding_by_group.csv",
1030 + "formula": "grounded_share all/years"
1031 + },
1032 + "groundedYearsCI": {
1033 + "value": "[99.7, 99.8]",
1034 + "source": "results/grounding/grounding_by_group.csv",
1035 + "formula": "ci all/years"
1036 + },
1037 + "groundedYearsOneZeroKPct": {
1038 + "value": "99.6",
1039 + "source": "results/grounding/grounding_by_group.csv",
1040 + "formula": "grounded_share form=10-K/years"
1041 + },
1042 + "groundedYearsOneZeroQPct": {
1043 + "value": "99.8",
1044 + "source": "results/grounding/grounding_by_group.csv",
1045 + "formula": "grounded_share form=10-Q/years"
1046 + },
1047 + "groundedYearsEightKPct": {
1048 + "value": "99.8",
1049 + "source": "results/grounding/grounding_by_group.csv",
1050 + "formula": "grounded_share form=8-K/years"
1051 + },
1052 + "groundedPartnersPct": {
1053 + "value": "99.4",
1054 + "source": "results/grounding/grounding_by_group.csv",
1055 + "formula": "grounded_share all/partners"
1056 + },
1057 + "groundedPartnersCI": {
1058 + "value": "[99.3, 99.5]",
1059 + "source": "results/grounding/grounding_by_group.csv",
1060 + "formula": "ci all/partners"
1061 + },
1062 + "groundedPartnersOneZeroKPct": {
1063 + "value": "99.3",
1064 + "source": "results/grounding/grounding_by_group.csv",
1065 + "formula": "grounded_share form=10-K/partners"
1066 + },
1067 + "groundedPartnersOneZeroQPct": {
1068 + "value": "99.1",
1069 + "source": "results/grounding/grounding_by_group.csv",
1070 + "formula": "grounded_share form=10-Q/partners"
1071 + },
1072 + "groundedPartnersEightKPct": {
1073 + "value": "99.6",
1074 + "source": "results/grounding/grounding_by_group.csv",
1075 + "formula": "grounded_share form=8-K/partners"
1076 + },
1077 + "groundedAmountNumberPct": {
1078 + "value": "93.7",
1079 + "source": "results/grounding/grounding_by_group.csv",
1080 + "formula": "grounded_share all/amount_number"
1081 + },
1082 + "groundedAmountNumberCI": {
1083 + "value": "[93.6, 93.9]",
1084 + "source": "results/grounding/grounding_by_group.csv",
1085 + "formula": "ci all/amount_number"
1086 + },
1087 + "groundedAmountNumberOneZeroKPct": {
1088 + "value": "97.4",
1089 + "source": "results/grounding/grounding_by_group.csv",
1090 + "formula": "grounded_share form=10-K/amount_number"
1091 + },
1092 + "groundedAmountNumberOneZeroQPct": {
1093 + "value": "97.5",
1094 + "source": "results/grounding/grounding_by_group.csv",
1095 + "formula": "grounded_share form=10-Q/amount_number"
1096 + },
1097 + "groundedAmountNumberEightKPct": {
1098 + "value": "86.9",
1099 + "source": "results/grounding/grounding_by_group.csv",
1100 + "formula": "grounded_share form=8-K/amount_number"
1101 + },
1102 + "groundedAmountWithCurrencyPct": {
1103 + "value": "80.5",
1104 + "source": "results/grounding/grounding_by_group.csv",
1105 + "formula": "grounded_share all/amount_with_currency"
1106 + },
1107 + "groundedAmountWithCurrencyCI": {
1108 + "value": "[80.2, 80.7]",
1109 + "source": "results/grounding/grounding_by_group.csv",
1110 + "formula": "ci all/amount_with_currency"
1111 + },
1112 + "groundedAmountWithCurrencyOneZeroKPct": {
1113 + "value": "86.8",
1114 + "source": "results/grounding/grounding_by_group.csv",
1115 + "formula": "grounded_share form=10-K/amount_with_currency"
1116 + },
1117 + "groundedAmountWithCurrencyOneZeroQPct": {
1118 + "value": "82.3",
1119 + "source": "results/grounding/grounding_by_group.csv",
1120 + "formula": "grounded_share form=10-Q/amount_with_currency"
1121 + },
1122 + "groundedAmountWithCurrencyEightKPct": {
1123 + "value": "74.9",
1124 + "source": "results/grounding/grounding_by_group.csv",
1125 + "formula": "grounded_share form=8-K/amount_with_currency"
1126 + },
1127 + "groundedLocationsPct": {
1128 + "value": "78.3",
1129 + "source": "results/grounding/grounding_by_group.csv",
1130 + "formula": "grounded_share all/locations"
1131 + },
1132 + "groundedLocationsCI": {
1133 + "value": "[78.0, 78.6]",
1134 + "source": "results/grounding/grounding_by_group.csv",
1135 + "formula": "ci all/locations"
1136 + },
1137 + "groundedLocationsOneZeroKPct": {
1138 + "value": "85.7",
1139 + "source": "results/grounding/grounding_by_group.csv",
1140 + "formula": "grounded_share form=10-K/locations"
1141 + },
1142 + "groundedLocationsOneZeroQPct": {
1143 + "value": "82.1",
1144 + "source": "results/grounding/grounding_by_group.csv",
1145 + "formula": "grounded_share form=10-Q/locations"
1146 + },
1147 + "groundedLocationsEightKPct": {
1148 + "value": "67.8",
1149 + "source": "results/grounding/grounding_by_group.csv",
1150 + "formula": "grounded_share form=8-K/locations"
1151 + },
1152 + "groundedTechnologiesPct": {
1153 + "value": "63.6",
1154 + "source": "results/grounding/grounding_by_group.csv",
1155 + "formula": "grounded_share all/technologies"
1156 + },
1157 + "groundedTechnologiesCI": {
1158 + "value": "[63.0, 64.2]",
1159 + "source": "results/grounding/grounding_by_group.csv",
1160 + "formula": "ci all/technologies"
1161 + },
1162 + "groundedTechnologiesOneZeroKPct": {
1163 + "value": "63.8",
1164 + "source": "results/grounding/grounding_by_group.csv",
1165 + "formula": "grounded_share form=10-K/technologies"
1166 + },
1167 + "groundedTechnologiesOneZeroQPct": {
1168 + "value": "64.8",
1169 + "source": "results/grounding/grounding_by_group.csv",
1170 + "formula": "grounded_share form=10-Q/technologies"
1171 + },
1172 + "groundedTechnologiesEightKPct": {
1173 + "value": "58.2",
1174 + "source": "results/grounding/grounding_by_group.csv",
1175 + "formula": "grounded_share form=8-K/technologies"
1176 + },
1177 + "groundedAllFieldsPct": {
1178 + "value": "88.2",
1179 + "source": "results/grounding/grounding_all_structured.csv",
1180 + "formula": "pct where g=all"
1181 + },
1182 + "groundedAllFieldsTenKPct": {
1183 + "value": "92.2",
1184 + "source": "results/grounding/grounding_all_structured.csv",
1185 + "formula": "pct where g=10-K"
1186 + },
1187 + "groundedAllFieldsTenQPct": {
1188 + "value": "92.4",
1189 + "source": "results/grounding/grounding_all_structured.csv",
1190 + "formula": "pct where g=10-Q"
1191 + },
1192 + "groundedAllFieldsEightKPct": {
1193 + "value": "76.6",
1194 + "source": "results/grounding/grounding_all_structured.csv",
1195 + "formula": "pct where g=8-K"
1196 + },
1197 + "groundedAllFieldsJunePct": {
1198 + "value": "84.5",
1199 + "source": "results/grounding/grounding_all_structured.csv",
1200 + "formula": "pct where g=backfilled_june"
1201 + },
1202 + "groundedAllFieldsOctoberPct": {
1203 + "value": "88.7",
1204 + "source": "results/grounding/grounding_all_structured.csv",
1205 + "formula": "pct where g=october"
1206 + },
1207 + "groundedAllFieldsN": {
1208 + "value": "276{,}168",
1209 + "source": "results/grounding/grounding_all_structured.csv",
1210 + "formula": "n_with_fields where g=all"
1211 + },
1212 + "projectCountRangeKeys": {
1213 + "value": "21{,}027--308{,}065",
1214 + "source": "results/resolver/spec_curve.csv",
1215 + "formula": "min/max projects over keys at threshold 0.45"
1216 + },
1217 + "projectCountRangeKeysN": {
1218 + "value": "9",
1219 + "source": "results/resolver/spec_curve.csv",
1220 + "formula": "number of keys at threshold 0.45"
1221 + },
1222 + "projectCountRangeResolvedKeys": {
1223 + "value": "21{,}027--198{,}488",
1224 + "source": "results/resolver/spec_curve.csv",
1225 + "formula": "min/max projects over keys at 0.45 excluding the mention level"
1226 + },
1227 + "projectCountRangeAll": {
1228 + "value": "16{,}562--308{,}065",
1229 + "source": "results/resolver/spec_curve.csv",
1230 + "formula": "min/max projects over all keys x thresholds"
1231 + },
1232 + "projectCountCurrentKey": {
1233 + "value": "121{,}099",
1234 + "source": "results/resolver/spec_curve.csv",
1235 + "formula": "key=k_current at 0.45"
1236 + },
1237 + "projectCountStrict": {
1238 + "value": "198{,}488",
1239 + "source": "results/resolver/spec_curve.csv",
1240 + "formula": "key=k_strict at 0.45"
1241 + },
1242 + "projectCountCikType": {
1243 + "value": "21{,}027",
1244 + "source": "results/resolver/spec_curve.csv",
1245 + "formula": "key=k_cik_type at 0.45"
1246 + },
1247 + "projectCountTypeDropped": {
1248 + "value": "96{,}749",
1249 + "source": "results/resolver/spec_curve.csv",
1250 + "formula": "key=k_type_dropped at 0.45"
1251 + },
1252 + "projectCountNameOnly": {
1253 + "value": "114{,}244",
1254 + "source": "results/resolver/spec_curve.csv",
1255 + "formula": "key=k_name_only at 0.45"
1256 + },
1257 + "projectCountCurrentKeyHighThreshold": {
1258 + "value": "83{,}483",
1259 + "source": "results/resolver/spec_curve.csv",
1260 + "formula": "key=k_current at 0.9"
1261 + },
1262 + "specCurveThresholdMax": {
1263 + "value": "0.9",
1264 + "source": "results/resolver/spec_curve.csv",
1265 + "formula": "max threshold"
1266 + },
1267 + "topNameTokens": {
1268 + "value": "\\texttt{acquisition} (3.4\\%), \\texttt{share} (3.1\\%), \\texttt{expansion} (1.8\\%), \\texttt{stock} (1.7\\%), \\texttt{investment} (1.6\\%), \\texttt{merger} (1.3\\%), \\texttt{sale} (1.3\\%), \\texttt{development} (1.2\\%), \\texttt{strategic} (0.9\\%), \\texttt{capital} (0.8\\%)",
1269 + "source": "results/resolver/top_name_tokens.csv",
1270 + "formula": "top-10 tokens, pct of token-keyed projects"
1271 + },
1272 + "topNameTokensProjectsPct": {
1273 + "value": "17.2",
1274 + "source": "results/resolver/top_name_tokens.csv",
1275 + "formula": "sum of pct_of_tokenkeyed_projects over the top 10"
1276 + },
1277 + "topNameToken": {
1278 + "value": "acquisition",
1279 + "source": "results/resolver/top_name_tokens.csv",
1280 + "formula": "name_tok[0]"
1281 + },
1282 + "topNameTokenMentions": {
1283 + "value": "40{,}407",
1284 + "source": "results/resolver/top_name_tokens.csv",
1285 + "formula": "mentions[0]"
1286 + },
1287 + "topNameTokenProjects": {
1288 + "value": "2{,}256",
1289 + "source": "results/resolver/top_name_tokens.csv",
1290 + "formula": "projects[0]"
1291 + },
1292 + "maProjectsAmountOtherCounterparty": {
1293 + "value": "1{,}630",
1294 + "source": "results/resolver/composition.json",
1295 + "formula": "amount_from_other_counterparty_ma[0]"
1296 + },
1297 + "maProjectsBothNamed": {
1298 + "value": "12{,}372",
1299 + "source": "results/resolver/composition.json",
1300 + "formula": "amount_from_other_counterparty_ma[1]"
1301 + },
1302 + "maGeThreeNamesPct": {
1303 + "value": "14.6",
1304 + "source": "results/resolver/overmerge_by_type.csv",
1305 + "formula": "pct_ge3_names where project_type=ma_integration"
1306 + },
1307 + "tenKmdnaShownMedianPct": {
1308 + "value": "9.3",
1309 + "source": "results/focus/stats_keys.json",
1310 + "formula": "ledger_10k_mdna_shown_p50"
1311 + },
1312 + "tenKmdnaLastOffsetMedianPct": {
1313 + "value": "16",
1314 + "source": "results/focus/stats_keys.json",
1315 + "formula": "ledger_10k_mdna_last_p50"
1316 + },
1317 + "tenKmdnaShownLtQuarterPct": {
1318 + "value": "90.5",
1319 + "source": "results/focus/stats_keys.json",
1320 + "formula": "ledger_10k_mdna_pct_shown_lt_25"
1321 + },
1322 + "ledgerSectionsOverBudget": {
1323 + "value": "326{,}095",
1324 + "source": "results/focus/stats_keys.json",
1325 + "formula": "ledger_sections_over_9000_chars"
1326 + },
1327 + "callsOverBudget": {
1328 + "value": "324{,}386",
1329 + "source": "results/focus/stats_keys.json",
1330 + "formula": "calls_over_9000_chars"
1331 + },
1332 + "mentionsFromShownLtQuarter": {
1333 + "value": "193{,}416",
1334 + "source": "results/focus/stats_keys.json",
1335 + "formula": "mentions_from_sections_shown_lt_25"
1336 + },
1337 + "meanShownOverBudgetPct": {
1338 + "value": "15.9",
1339 + "source": "results/focus/stats_keys.json",
1340 + "formula": "mean_shown_frac_over_budget"
1341 + },
1342 + "tenKmdnaMedianChars": {
1343 + "value": "64{,}194",
1344 + "source": "results/focus/stats_keys.json",
1345 + "formula": "ledger_10k_mdna_median_chars"
1346 + },
1347 + "messagesTruncated": {
1348 + "value": "0",
1349 + "source": "results/focus/stats_keys.json",
1350 + "formula": "msg_truncated_14k"
1351 + },
1352 + "mentionsFromShownLtQuarterPct": {
1353 + "value": "62.7",
1354 + "source": "results/focus/stats_keys.json",
1355 + "formula": "100*mentions_from_sections_shown_lt_25/mentions_total"
1356 + },
1357 + "ledgerSectionsOverBudgetPct": {
1358 + "value": "29",
1359 + "source": "results/focus/stats_keys.json",
1360 + "formula": "100*over_9000/ledger_total"
1361 + },
1362 + "mentionsFromShownLtQuarterOneZeroKPct": {
1363 + "value": "84",
1364 + "source": "results/focus/focus_coverage_by_form.csv",
1365 + "formula": "pct_mentions_from_lt25 where form=10-K"
1366 + },
1367 + "mentionsFromShownLtQuarterOneZeroQPct": {
1368 + "value": "79",
1369 + "source": "results/focus/focus_coverage_by_form.csv",
1370 + "formula": "pct_mentions_from_lt25 where form=10-Q"
1371 + },
1372 + "mentionsFromShownLtQuarterEightKPct": {
1373 + "value": "6",
1374 + "source": "results/focus/focus_coverage_by_form.csv",
1375 + "formula": "pct_mentions_from_lt25 where form=8-K"
1376 + },
1377 + "tenKmdnaShortSections": {
1378 + "value": "169",
1379 + "source": "results/focus/mdna_10k_short_by_year.csv",
1380 + "formula": "sum(lt30_words)"
1381 + },
1382 + "tenKmdnaParsedSections": {
1383 + "value": "29{,}088",
1384 + "source": "results/focus/mdna_10k_short_by_year.csv",
1385 + "formula": "sum(mdna_sections)"
1386 + },
1387 + "tenKmdnaShortPct": {
1388 + "value": "0.6",
1389 + "source": "results/focus/mdna_10k_short_by_year.csv",
1390 + "formula": "100*sum(lt30)/sum(sections)"
1391 + },
1392 + "financingMentions": {
1393 + "value": "22{,}412",
1394 + "source": "results/fp_classes/summary.json",
1395 + "formula": "mentions_matched[0]"
1396 + },
1397 + "financingMentionsPct": {
1398 + "value": "7.3",
1399 + "source": "results/fp_classes/summary.json",
1400 + "formula": "mentions_matched[2]"
1401 + },
1402 + "financingProjectsAnyMention": {
1403 + "value": "13{,}139",
1404 + "source": "results/fp_classes/summary.json",
1405 + "formula": "projects_matched_rep[1]"
1406 + },
1407 + "financingProjectsRep": {
1408 + "value": "12{,}027",
1409 + "source": "results/fp_classes/summary.json",
1410 + "formula": "projects_matched_rep[0]"
1411 + },
1412 + "financingAmountTusd": {
1413 + "value": "17.8",
1414 + "source": "results/fp_classes/summary.json",
1415 + "formula": "matched_amount_gusd[0]/1e3"
1416 + },
1417 + "mentionAmountTotalTusd": {
1418 + "value": "104.2",
1419 + "source": "results/fp_classes/summary.json",
1420 + "formula": "matched_amount_gusd[1]/1e3"
1421 + },
1422 + "financingUnregisteredSalesPct": {
1423 + "value": "54.5",
1424 + "source": "results/fp_classes/summary.json",
1425 + "formula": "100*unregistered_sales_matched[0]/[1]"
1426 + },
1427 + "financingMaIntegrationPct": {
1428 + "value": "7.0",
1429 + "source": "results/fp_classes/financing_regex_by_type.csv",
1430 + "formula": "pct where project_type=ma_integration"
1431 + },
1432 + "financingCapexProgramPct": {
1433 + "value": "52.6",
1434 + "source": "results/fp_classes/financing_regex_by_type.csv",
1435 + "formula": "pct where project_type=capex_program"
1436 + },
1437 + "financingCostReductionPct": {
1438 + "value": "16.4",
1439 + "source": "results/fp_classes/financing_regex_by_type.csv",
1440 + "formula": "pct where project_type=cost_reduction"
1441 + },
1442 + "financingOneZeroKPct": {
1443 + "value": "0.8",
1444 + "source": "results/fp_classes/financing_regex_by_form.csv",
1445 + "formula": "pct where form_type=10-K"
1446 + },
1447 + "financingOneZeroQPct": {
1448 + "value": "4.9",
1449 + "source": "results/fp_classes/financing_regex_by_form.csv",
1450 + "formula": "pct where form_type=10-Q"
1451 + },
1452 + "financingEightKPct": {
1453 + "value": "19.2",
1454 + "source": "results/fp_classes/financing_regex_by_form.csv",
1455 + "formula": "pct where form_type=8-K"
1456 + },
1457 + "itemTwoCollisionSections": {
1458 + "value": "1{,}001",
1459 + "source": "results/fp_classes/summary.json",
1460 + "formula": "item2_collision[3] (unreg_gt_3000)"
1461 + },
1462 + "itemTwoCollisionSwapCandidates": {
1463 + "value": "296",
1464 + "source": "results/fp_classes/summary.json",
1465 + "formula": "item2_collision[7]"
1466 + },
1467 + "pTypeGivenItemMaIntegrationItemTwoZeroOne": {
1468 + "value": "91.1",
1469 + "source": "results/benchmark_8k/item_vs_type.csv",
1470 + "formula": "p_type_given_item ma_integration Item 2.01"
1471 + },
1472 + "pItemGivenTypeMaIntegrationItemTwoZeroOne": {
1473 + "value": "13.1",
1474 + "source": "results/benchmark_8k/item_vs_type.csv",
1475 + "formula": "p_item_given_type ma_integration Item 2.01"
1476 + },
1477 + "liftMaIntegrationItemTwoZeroOne": {
1478 + "value": "10",
1479 + "source": "results/benchmark_8k/item_vs_type.csv",
1480 + "formula": "lift ma_integration Item 2.01"
1481 + },
1482 + "pTypeGivenItemMaIntegrationItemTwoZeroOneorOneZeroOne": {
1483 + "value": "35.6",
1484 + "source": "results/benchmark_8k/item_vs_type.csv",
1485 + "formula": "p_type_given_item ma_integration Item 2.01 or 1.01"
1486 + },
1487 + "pItemGivenTypeMaIntegrationItemTwoZeroOneorOneZeroOne": {
1488 + "value": "46.7",
1489 + "source": "results/benchmark_8k/item_vs_type.csv",
1490 + "formula": "p_item_given_type ma_integration Item 2.01 or 1.01"
1491 + },
1492 + "liftMaIntegrationItemTwoZeroOneorOneZeroOne": {
1493 + "value": "4",
1494 + "source": "results/benchmark_8k/item_vs_type.csv",
1495 + "formula": "lift ma_integration Item 2.01 or 1.01"
1496 + },
1497 + "pTypeGivenItemMaIntegrationItemOneZeroOne": {
1498 + "value": "31.8",
1499 + "source": "results/benchmark_8k/item_vs_type.csv",
1500 + "formula": "p_type_given_item ma_integration Item 1.01"
1501 + },
1502 + "pItemGivenTypeMaIntegrationItemOneZeroOne": {
1503 + "value": "39.2",
1504 + "source": "results/benchmark_8k/item_vs_type.csv",
1505 + "formula": "p_item_given_type ma_integration Item 1.01"
1506 + },
1507 + "liftMaIntegrationItemOneZeroOne": {
1508 + "value": "3",
1509 + "source": "results/benchmark_8k/item_vs_type.csv",
1510 + "formula": "lift ma_integration Item 1.01"
1511 + },
1512 + "pTypeGivenItemCostReductionItemTwoZeroFive": {
1513 + "value": "70.9",
1514 + "source": "results/benchmark_8k/item_vs_type.csv",
1515 + "formula": "p_type_given_item cost_reduction Item 2.05"
1516 + },
1517 + "pItemGivenTypeCostReductionItemTwoZeroFive": {
1518 + "value": "39.2",
1519 + "source": "results/benchmark_8k/item_vs_type.csv",
1520 + "formula": "p_item_given_type cost_reduction Item 2.05"
1521 + },
1522 + "liftCostReductionItemTwoZeroFive": {
1523 + "value": "92",
1524 + "source": "results/benchmark_8k/item_vs_type.csv",
1525 + "formula": "lift cost_reduction Item 2.05"
1526 + },
1527 + "pTypeGivenItemPartnershipItemOneZeroOne": {
1528 + "value": "4.0",
1529 + "source": "results/benchmark_8k/item_vs_type.csv",
1530 + "formula": "p_type_given_item partnership Item 1.01"
1531 + },
1532 + "pItemGivenTypePartnershipItemOneZeroOne": {
1533 + "value": "42.1",
1534 + "source": "results/benchmark_8k/item_vs_type.csv",
1535 + "formula": "p_item_given_type partnership Item 1.01"
1536 + },
1537 + "liftPartnershipItemOneZeroOne": {
1538 + "value": "4",
1539 + "source": "results/benchmark_8k/item_vs_type.csv",
1540 + "formula": "lift partnership Item 1.01"
1541 + },
1542 + "pTypeGivenItemCapexTypeItemOneZeroOne": {
1543 + "value": "13.2",
1544 + "source": "results/benchmark_8k/item_vs_type.csv",
1545 + "formula": "p_type_given_item capex-type Item 1.01"
1546 + },
1547 + "pItemGivenTypeCapexTypeItemOneZeroOne": {
1548 + "value": "46.8",
1549 + "source": "results/benchmark_8k/item_vs_type.csv",
1550 + "formula": "p_item_given_type capex-type Item 1.01"
1551 + },
1552 + "liftCapexTypeItemOneZeroOne": {
1553 + "value": "4",
1554 + "source": "results/benchmark_8k/item_vs_type.csv",
1555 + "formula": "lift capex-type Item 1.01"
1556 + },
1557 + "pTypeGivenItemMaIntegrationItemEightZeroOnecontrol": {
1558 + "value": "19.9",
1559 + "source": "results/benchmark_8k/item_vs_type.csv",
1560 + "formula": "p_type_given_item ma_integration Item 8.01 (control)"
1561 + },
1562 + "pItemGivenTypeMaIntegrationItemEightZeroOnecontrol": {
1563 + "value": "48.7",
1564 + "source": "results/benchmark_8k/item_vs_type.csv",
1565 + "formula": "p_item_given_type ma_integration Item 8.01 (control)"
1566 + },
1567 + "liftMaIntegrationItemEightZeroOnecontrol": {
1568 + "value": "2",
1569 + "source": "results/benchmark_8k/item_vs_type.csv",
1570 + "formula": "lift ma_integration Item 8.01 (control)"
1571 + },
1572 + "pTypeGivenItemMaIntegrationItemFiveZeroTwocontrol": {
1573 + "value": "3.1",
1574 + "source": "results/benchmark_8k/item_vs_type.csv",
1575 + "formula": "p_type_given_item ma_integration Item 5.02 (control)"
1576 + },
1577 + "pItemGivenTypeMaIntegrationItemFiveZeroTwocontrol": {
1578 + "value": "5.9",
1579 + "source": "results/benchmark_8k/item_vs_type.csv",
1580 + "formula": "p_item_given_type ma_integration Item 5.02 (control)"
1581 + },
1582 + "liftMaIntegrationItemFiveZeroTwocontrol": {
1583 + "value": "0",
1584 + "source": "results/benchmark_8k/item_vs_type.csv",
1585 + "formula": "lift ma_integration Item 5.02 (control)"
1586 + },
1587 + "pTypeGivenItemCostReductionItemEightZeroOnecontrol": {
1588 + "value": "1.5",
1589 + "source": "results/benchmark_8k/item_vs_type.csv",
1590 + "formula": "p_type_given_item cost_reduction Item 8.01 (control)"
1591 + },
1592 + "pItemGivenTypeCostReductionItemEightZeroOnecontrol": {
1593 + "value": "45.1",
1594 + "source": "results/benchmark_8k/item_vs_type.csv",
1595 + "formula": "p_item_given_type cost_reduction Item 8.01 (control)"
1596 + },
1597 + "liftCostReductionItemEightZeroOnecontrol": {
1598 + "value": "2",
1599 + "source": "results/benchmark_8k/item_vs_type.csv",
1600 + "formula": "lift cost_reduction Item 8.01 (control)"
1601 + },
1602 + "pTypeGivenItemMaIntegrationItemTwoZeroThreecontrol": {
1603 + "value": "21.0",
1604 + "source": "results/benchmark_8k/item_vs_type.csv",
1605 + "formula": "p_type_given_item ma_integration Item 2.03 (control)"
1606 + },
1607 + "pItemGivenTypeMaIntegrationItemTwoZeroThreecontrol": {
1608 + "value": "12.4",
1609 + "source": "results/benchmark_8k/item_vs_type.csv",
1610 + "formula": "p_item_given_type ma_integration Item 2.03 (control)"
1611 + },
1612 + "liftMaIntegrationItemTwoZeroThreecontrol": {
1613 + "value": "2",
1614 + "source": "results/benchmark_8k/item_vs_type.csv",
1615 + "formula": "lift ma_integration Item 2.03 (control)"
1616 + },
1617 + "pTypeGivenItemPartnershipItemEightZeroOnecontrol": {
1618 + "value": "1.7",
1619 + "source": "results/benchmark_8k/item_vs_type.csv",
1620 + "formula": "p_type_given_item partnership Item 8.01 (control)"
1621 + },
1622 + "pItemGivenTypePartnershipItemEightZeroOnecontrol": {
1623 + "value": "34.9",
1624 + "source": "results/benchmark_8k/item_vs_type.csv",
1625 + "formula": "p_item_given_type partnership Item 8.01 (control)"
1626 + },
1627 + "liftPartnershipItemEightZeroOnecontrol": {
1628 + "value": "2",
1629 + "source": "results/benchmark_8k/item_vs_type.csv",
1630 + "formula": "lift partnership Item 8.01 (control)"
1631 + },
1632 + "cohortIssuers": {
1633 + "value": "1{,}389",
1634 + "source": "results/timeseries/summary.json",
1635 + "formula": "cohort_issuers"
1636 + },
1637 + "cohortMentionsPerIssuerFirst": {
1638 + "value": "9.6",
1639 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
1640 + "formula": "fixed cohort mentions per issuer 2011"
1641 + },
1642 + "cohortMentionsPerIssuerLast": {
1643 + "value": "8.8",
1644 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
1645 + "formula": "fixed cohort mentions per issuer 2025"
1646 + },
1647 + "cohortFirstSeenPerIssuerFirst": {
1648 + "value": "4.7",
1649 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
1650 + "formula": "fixed cohort first seen per issuer 2011"
1651 + },
1652 + "cohortFirstSeenPerIssuerLast": {
1653 + "value": "2.8",
1654 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
1655 + "formula": "fixed cohort first seen per issuer 2025"
1656 + },
1657 + "cohortFirstSeenFirst": {
1658 + "value": "6{,}533",
1659 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
1660 + "formula": "fixed cohort first seen 2011"
1661 + },
1662 + "cohortFirstSeenLast": {
1663 + "value": "3{,}926",
1664 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
1665 + "formula": "fixed cohort first seen 2025"
1666 + },
1667 + "episodesKThree": {
1668 + "value": "131{,}823",
1669 + "source": "results/timeseries/summary.json",
1670 + "formula": "episodes_k3_total"
1671 + },
1672 + "episodesKFive": {
1673 + "value": "126{,}318",
1674 + "source": "results/timeseries/summary.json",
1675 + "formula": "episodes_k5_total"
1676 + },
1677 + "newProjectsPerIssuerFilingFirstYear": {
1678 + "value": "5.6",
1679 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
1680 + "formula": "first seen / issuers filing, first year"
1681 + },
1682 + "newProjectsPerIssuerFilingLastFullYear": {
1683 + "value": "3.3",
1684 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
1685 + "formula": "first seen / issuers filing, 2025"
1686 + },
1687 + "newProjectsPerIssuerFirstYear": {
1688 + "value": "6.4",
1689 + "source": "data/projects_by_first_seen_year.csv, mentions_by_year.csv",
1690 + "formula": "first seen / issuers with mentions"
1691 + },
1692 + "newProjectsPerIssuerLastFullYear": {
1693 + "value": "3.5",
1694 + "source": "data/projects_by_first_seen_year.csv, mentions_by_year.csv",
1695 + "formula": "first seen / issuers with mentions"
1696 + },
1697 + "focusRecallRecoveredPct": {
1698 + "value": "26.2",
1699 + "source": "results/rules/focus_recall_loss_overall.csv",
1700 + "formula": "100 - pct_lost"
1701 + },
1702 + "focusRecallRecoveredOneZeroKPct": {
1703 + "value": "25.0",
1704 + "source": "results/rules/focus_recall_loss.csv",
1705 + "formula": "sum(rules_focused)/sum(rules_full) where form=10-K"
1706 + },
1707 + "focusRecallRecoveredOneZeroQPct": {
1708 + "value": "24.9",
1709 + "source": "results/rules/focus_recall_loss.csv",
1710 + "formula": "sum(rules_focused)/sum(rules_full) where form=10-Q"
1711 + },
1712 + "focusRecallRecoveredEightKPct": {
1713 + "value": "84.2",
1714 + "source": "results/rules/focus_recall_loss.csv",
1715 + "formula": "sum(rules_focused)/sum(rules_full) where form=8-K"
1716 + },
1717 + "rulesGivenLlmPct": {
1718 + "value": "85.7",
1719 + "source": "results/rules/agreement_overall.csv",
1720 + "formula": "p_rules_given_llm"
1721 + },
1722 + "llmGivenRulesPct": {
1723 + "value": "32.5",
1724 + "source": "results/rules/agreement_overall.csv",
1725 + "formula": "p_llm_given_rules_weighted"
1726 + },
1727 + "rulesLlmAgreementPct": {
1728 + "value": "71.2",
1729 + "source": "results/rules/agreement_overall.csv",
1730 + "formula": "agreement_pct_w"
1731 + },
1732 + "rulesLlmTypeOverlapPct": {
1733 + "value": "84.6",
1734 + "source": "results/rules/agreement_overall.csv",
1735 + "formula": "type_overlap_pct_codetected"
1736 + },
1737 + "rulesSampleN": {
1738 + "value": "60{,}000",
1739 + "source": "results/rules/agreement_overall.csv",
1740 + "formula": "n_sampled"
1741 + },
722 1742 "callsTotal": {
723 1743 "value": "703{,}725",
724 1744 "source": "results/ledger/gate_pass_totals.json",
@@ -774,6 +1794,11 @@
774 1794 "source": "results/ledger/throughput.json",
775 1795 "formula": "rows_per_second_effective"
776 1796 },
1797 + "octoberRowsPerSecondWallClock": {
1798 + "value": "19.7",
1799 + "source": "results/ledger/throughput.json",
1800 + "formula": "rows_per_second_wall"
1801 + },
777 1802 "octoberCallsPerSecondEffective": {
778 1803 "value": "20.1",
779 1804 "source": "results/ledger/throughput.json",
@@ -789,10 +1814,15 @@
789 1814 "source": "results/ledger/throughput.json",
790 1815 "formula": "october_last_flush"
791 1816 },
1817 + "paperRateImpliedByTwelveHours": {
1818 + "value": "22.4",
1819 + "source": "results/ledger/throughput.json",
1820 + "formula": "paper_rate_implied_by_12h"
1821 + },
792 1822 "backfilledRows": {
793 1823 "value": "154{,}964",
794 − "source": "results/ledger/backfill_block.json",
795 − "formula": "rows_at_min_timestamp"
1824 + "source": "stats.json:backfilled_rows",
1825 + "formula": "export_stats.py"
796 1826 },
797 1827 "juneLogSections": {
798 1828 "value": "153{,}894",
@@ -806,8 +1836,8 @@
806 1836 },
807 1837 "backfilledMentions": {
808 1838 "value": "39{,}930",
809 − "source": "results/ledger/backfill_block.json",
810 − "formula": "block_stored_mentions"
1839 + "source": "stats.json:backfilled_mentions",
1840 + "formula": "export_stats.py"
811 1841 },
812 1842 "backfilledCiks": {
813 1843 "value": "500",
@@ -840,9 +1870,14 @@
840 1870 "formula": "llm_call_failed_inside_window"
841 1871 },
842 1872 "llmCallFailedOutsideOutage": {
843 − "value": "142",
1873 + "value": "14",
844 1874 "source": "results/ledger/log_summary.json:october",
845 − "formula": "llm_call_failed_outside_window"
1875 + "formula": "silent_empty_results_outside_outage"
1876 + },
1877 + "llmRetryableTailLines": {
1878 + "value": "128",
1879 + "source": "results/ledger/log_summary.json:october.outside_window_by_reason",
1880 + "formula": "retryable_http_429_5xx"
846 1881 },
847 1882 "llmFailedJsonDecodeError": {
848 1883 "value": "14",
@@ -859,6 +1894,21 @@
859 1894 "source": "results/ledger/log_summary.json:october.llm_call_failed_by_reason",
860 1895 "formula": "connection_error"
861 1896 },
1897 + "outageLogWindowStart": {
1898 + "value": "2026-10-28 01:10",
1899 + "source": "results/ledger/log_summary.json",
1900 + "formula": "outage_window_from_log[0]"
1901 + },
1902 + "outageLogWindowEnd": {
1903 + "value": "2026-10-28 06:22",
1904 + "source": "results/ledger/log_summary.json",
1905 + "formula": "outage_window_from_log[1]"
1906 + },
1907 + "outageRowsRemoved": {
1908 + "value": "149{,}352",
1909 + "source": "results/ledger/log_summary.json:october.outage_rows_reconciliation",
1910 + "formula": "difference"
1911 + },
862 1912 "juneLlmCallFailed": {
863 1913 "value": "3",
864 1914 "source": "results/ledger/log_summary.json:june",
@@ -929,35 +1979,2010 @@
929 1979 "source": "results/resolver/ties_idempotence.json",
930 1980 "formula": "mentions_at_confidence_1"
931 1981 },
932 − "projectCountRangeKeys": {
933 − "value": "21{,}027--308{,}065",
1982 + "rebuiltNamesDiffer": {
1983 + "value": "394",
1984 + "source": "results/resolver/ties_idempotence.json",
1985 + "formula": "rebuilt_vs_stored_diff[0]"
1986 + },
1987 + "rebuiltDescriptionsDiffer": {
1988 + "value": "600",
1989 + "source": "results/resolver/ties_idempotence.json",
1990 + "formula": "rebuilt_vs_stored_diff[2]"
1991 + },
1992 + "annotationFrameProductive": {
1993 + "value": "1{,}677",
1994 + "source": "results/annotation_frame/design.json",
1995 + "formula": "n_productive"
1996 + },
1997 + "annotationFrameZero": {
1998 + "value": "385",
1999 + "source": "results/annotation_frame/design.json",
2000 + "formula": "n_zero"
2001 + },
2002 + "annotationStrata": {
2003 + "value": "192",
2004 + "source": "results/annotation_frame/design.json",
2005 + "formula": "n_strata_productive"
2006 + },
2007 + "annotationHalfWidthPrecision": {
2008 + "value": "4.4",
2009 + "source": "results/annotation_frame/design.json",
2010 + "formula": "half_width_95_precision_p0.5"
2011 + },
2012 + "annotationMdeGateRecall": {
2013 + "value": "7.8",
2014 + "source": "results/annotation_frame/design.json",
2015 + "formula": "mde_gate_recall_diff_at_p0.05"
2016 + },
2017 + "annotationCoreProductive": {
2018 + "value": "510",
2019 + "source": "results/annotation_frame/design.json",
2020 + "formula": "core_subsample.productive"
2021 + },
2022 + "annotationDev": {
2023 + "value": "1{,}058",
2024 + "source": "results/annotation_frame/design.json",
2025 + "formula": "split.dev"
2026 + },
2027 + "annotationHoldout": {
2028 + "value": "1{,}004",
2029 + "source": "results/annotation_frame/design.json",
2030 + "formula": "split.holdout"
2031 + },
2032 + "fullBodyFilings": {
2033 + "value": "1{,}230",
2034 + "source": "results/runs/segmenters.json",
2035 + "formula": "full_body_rows[1]"
2036 + },
2037 + "legacyRows": {
2038 + "value": "27{,}164",
2039 + "source": "results/runs/segmenters.json",
2040 + "formula": "legacy_rows"
2041 + },
2042 + "legacyAccessions": {
2043 + "value": "7{,}368",
2044 + "source": "results/runs/segmenters.json",
2045 + "formula": "legacy_accessions"
2046 + },
2047 + "fiscalYearNullMentions": {
2048 + "value": "68{,}827",
2049 + "source": "stats.json:fiscal_year_null_mentions",
2050 + "formula": "count(fiscal_year is null)"
2051 + },
2052 + "outageLargestGapStart": {
2053 + "value": "01:25",
2054 + "source": "results/ledger/throughput.json",
2055 + "formula": "largest_gaps_seconds[-1][1] hh:mm"
2056 + },
2057 + "outageLargestGapEnd": {
2058 + "value": "06:40",
2059 + "source": "results/ledger/throughput.json",
2060 + "formula": "largest_gaps_seconds[-1][2] hh:mm"
2061 + },
2062 + "outageZeroBatchRange": {
2063 + "value": "47--60",
2064 + "source": "results/ledger/log_summary.json:october.anomalous_batches",
2065 + "formula": "min--max batch id with 0 mentions inside the log window"
2066 + },
2067 + "outageZeroBatchWindow": {
2068 + "value": "01:44--06:05",
2069 + "source": "results/ledger/log_summary.json:october.anomalous_batches",
2070 + "formula": "first--last timestamp"
2071 + },
2072 + "resumeBatchMentions": {
2073 + "value": "34",
2074 + "source": "results/ledger/log_summary.json:october.resume_batch1.log_mentions",
2075 + "formula": "log"
2076 + },
2077 + "resumeBatchWindow": {
2078 + "value": "06:38--06:40",
2079 + "source": "results/ledger/log_summary.json:october.resume_batch1.window",
2080 + "formula": "hh:mm"
2081 + },
2082 + "logExtractionCompleteSum": {
2083 + "value": "1{,}117{,}479",
2084 + "source": "results/ledger/log_summary.json:october.outage_rows_reconciliation",
2085 + "formula": "extraction_complete_sum_sections"
2086 + },
2087 + "logPendingSecondStart": {
2088 + "value": "968{,}127",
2089 + "source": "results/ledger/log_summary.json:october.outage_rows_reconciliation",
2090 + "formula": "pending_at_second_start"
2091 + },
2092 + "jsonFailBeforeOutage": {
2093 + "value": "nine",
2094 + "source": "results/ledger/log_summary.json:october.outside_window_list",
2095 + "formula": "json_decode_error lines before the window"
2096 + },
2097 + "jsonFailAfterOutage": {
2098 + "value": "five",
2099 + "source": "results/ledger/log_summary.json:october.outside_window_list",
2100 + "formula": "json_decode_error lines after the window"
2101 + },
2102 + "workers": {
2103 + "value": "48",
2104 + "source": "results/ledger/log_summary.json:october.workers_values",
2105 + "formula": "max"
2106 + },
2107 + "outageSurvivingRows": {
2108 + "value": "504",
2109 + "source": "results/ledger/backfill_block.json",
2110 + "formula": "rows_in_outage_window[0]"
2111 + },
2112 + "outageSurvivingMentions": {
2113 + "value": "1{,}011",
2114 + "source": "results/ledger/backfill_block.json",
2115 + "formula": "rows_in_outage_window[1]"
2116 + },
2117 + "backfillTimestamp": {
2118 + "value": "October~27, 2026, 13:12",
2119 + "source": "results/ledger/backfill_block.json:min_extracted_at",
2120 + "formula": "date, hh:mm"
2121 + },
2122 + "resumeBatchExpectedProductive": {
2123 + "value": "536",
2124 + "source": "results/ledger/resume_batch1_vs_expected.csv",
2125 + "formula": "sum(expected_with_mentions), rounded"
2126 + },
2127 + "resumeBatchZeroSharePct": {
2128 + "value": "99.2",
2129 + "source": "results/ledger/flush_zero_groups_after_0622.csv",
2130 + "formula": "zero_pct_among_calls of the first minute bin"
2131 + },
2132 + "juneCalls": {
2133 + "value": "95{,}286",
2134 + "source": "results/ledger/gate_pass_by_run.csv",
2135 + "formula": "calls where run=backfilled_june"
2136 + },
2137 + "juneProductiveShareCalls": {
2138 + "value": "25.6",
2139 + "source": "results/ledger/gate_pass_by_run.csv",
2140 + "formula": "productive_pct_calls where run=backfilled_june"
2141 + },
2142 + "octoberProductiveShareCalls": {
2143 + "value": "23.6",
2144 + "source": "results/ledger/gate_pass_by_run.csv",
2145 + "formula": "productive_pct_calls where run=october"
2146 + },
2147 + "gateRejectedPct": {
2148 + "value": "37.3",
2149 + "source": "results/ledger/gate_pass_totals.json",
2150 + "formula": "100*gate_rejected_zero/ledger_rows"
2151 + },
2152 + "usdPerOctoberRow": {
2153 + "value": "0.0008",
2154 + "source": "results/ledger/gate_pass_totals.json",
2155 + "formula": "usd_per_october_row_paper_total_775"
2156 + },
2157 + "confExactDefault": {
2158 + "value": "3{,}278",
2159 + "source": "results/ledger/code_vs_data_checks.json",
2160 + "formula": "confidence_exact_0600_total"
2161 + },
2162 + "confExactDefaultOctober": {
2163 + "value": "2{,}974",
2164 + "source": "results/ledger/code_vs_data_checks.json",
2165 + "formula": "confidence_exact_0600_by_run[october]"
2166 + },
2167 + "confExactDefaultJune": {
2168 + "value": "304",
2169 + "source": "results/ledger/code_vs_data_checks.json",
2170 + "formula": "confidence_exact_0600_by_run[backfilled_june]"
2171 + },
2172 + "ledgerBackendValue": {
2173 + "value": "llm",
2174 + "source": "results/ledger/code_vs_data_checks.json",
2175 + "formula": "distinct_backend_ledger"
2176 + },
2177 + "amountNegative": {
2178 + "value": "24",
2179 + "source": "results/grounding/amount_tail.json",
2180 + "formula": "lt_0"
2181 + },
2182 + "amountZero": {
2183 + "value": "584",
2184 + "source": "results/grounding/amount_tail.json",
2185 + "formula": "eq_0"
2186 + },
2187 + "amountMaxSci": {
2188 + "value": "1.0 \\times 10^{12}",
2189 + "source": "results/grounding/amount_tail.json:max_amount",
2190 + "formula": "mantissa x 10^exponent (math mode)"
2191 + },
2192 + "amountGeFiftyBMentions": {
2193 + "value": "161",
2194 + "source": "results/grounding/amount_tail.json",
2195 + "formula": "ge_50e9"
2196 + },
2197 + "amountGeFiftyBProjects": {
2198 + "value": "104",
2199 + "source": "results/grounding/amount_tail.json",
2200 + "formula": "projects_max_amount_ge_50e9"
2201 + },
2202 + "amountTopNumberFound": {
2203 + "value": "191",
2204 + "source": "results/grounding/amount_tail.json",
2205 + "formula": "top200_grounded_number[0]"
2206 + },
2207 + "amountTopCurrencyFound": {
2208 + "value": "178",
2209 + "source": "results/grounding/amount_tail.json",
2210 + "formula": "top200_grounded_number[1]"
2211 + },
2212 + "amountTopN": {
2213 + "value": "200",
2214 + "source": "results/grounding/amount_tail.json",
2215 + "formula": "top200_grounded_number[2]"
2216 + },
2217 + "amountNonUsdTokenN": {
2218 + "value": "1{,}837",
2219 + "source": "results/grounding/amount_tail.json",
2220 + "formula": "nonusd_within_40_share[0]"
2221 + },
2222 + "amountLocatedN": {
2223 + "value": "112{,}692",
2224 + "source": "results/grounding/amount_tail.json",
2225 + "formula": "nonusd_within_40_share[1]"
2226 + },
2227 + "amountNonUsdTokenPct": {
2228 + "value": "1.6",
2229 + "source": "results/grounding/amount_tail.json",
2230 + "formula": "100*[0]/[1]"
2231 + },
2232 + "groundBootstrapReps": {
2233 + "value": "1{,}000",
2234 + "source": "code/audit/a02_grounding.py",
2235 + "formula": "bootstrap replicates (B) of the grounding audit"
2236 + },
2237 + "groundYearsPct": {
2238 + "value": "99.8",
2239 + "source": "results/grounding/grounding_by_group.csv",
2240 + "formula": "all/years grounded_share"
2241 + },
2242 + "groundPartnersPct": {
2243 + "value": "99.4",
2244 + "source": "results/grounding/grounding_by_group.csv",
2245 + "formula": "all/partners grounded_share"
2246 + },
2247 + "groundAmountNumberPct": {
2248 + "value": "93.7",
2249 + "source": "results/grounding/grounding_by_group.csv",
2250 + "formula": "all/amount_number grounded_share"
2251 + },
2252 + "groundAmountCurrencyPct": {
2253 + "value": "80.5",
2254 + "source": "results/grounding/grounding_by_group.csv",
2255 + "formula": "all/amount_with_currency grounded_share"
2256 + },
2257 + "groundLocationsPct": {
2258 + "value": "78.3",
2259 + "source": "results/grounding/grounding_by_group.csv",
2260 + "formula": "all/locations grounded_share"
2261 + },
2262 + "groundTechPct": {
2263 + "value": "63.6",
2264 + "source": "results/grounding/grounding_by_group.csv",
2265 + "formula": "all/technologies grounded_share"
2266 + },
2267 + "groundYearsCiLow": {
2268 + "value": "99.7",
2269 + "source": "results/grounding/grounding_by_group.csv",
2270 + "formula": "all/years ci_low"
2271 + },
2272 + "groundYearsCiHigh": {
2273 + "value": "99.8",
2274 + "source": "results/grounding/grounding_by_group.csv",
2275 + "formula": "all/years ci_high"
2276 + },
2277 + "groundLocationsTenK": {
2278 + "value": "85.7",
2279 + "source": "results/grounding/grounding_by_group.csv",
2280 + "formula": "form/locations/10-K"
2281 + },
2282 + "groundLocationsTenQ": {
2283 + "value": "82.1",
2284 + "source": "results/grounding/grounding_by_group.csv",
2285 + "formula": "form/locations/10-Q"
2286 + },
2287 + "groundLocationsEightK": {
2288 + "value": "67.8",
2289 + "source": "results/grounding/grounding_by_group.csv",
2290 + "formula": "form/locations/8-K"
2291 + },
2292 + "groundElemPartners": {
2293 + "value": "99.6",
2294 + "source": "results/grounding/grounding_element_level.csv",
2295 + "formula": "partners"
2296 + },
2297 + "groundElemLocations": {
2298 + "value": "84.2",
2299 + "source": "results/grounding/grounding_element_level.csv",
2300 + "formula": "locations"
2301 + },
2302 + "groundElemTech": {
2303 + "value": "70.6",
2304 + "source": "results/grounding/grounding_element_level.csv",
2305 + "formula": "technologies"
2306 + },
2307 + "groundElemYears": {
2308 + "value": "99.7",
2309 + "source": "results/grounding/grounding_element_level.csv",
2310 + "formula": "years"
2311 + },
2312 + "groundAllPct": {
2313 + "value": "88.2",
2314 + "source": "results/grounding/grounding_all_structured.csv",
2315 + "formula": "all"
2316 + },
2317 + "groundAllN": {
2318 + "value": "276{,}168",
2319 + "source": "results/grounding/grounding_all_structured.csv",
2320 + "formula": "all n_with_fields"
2321 + },
2322 + "groundAllTenK": {
2323 + "value": "92.2",
2324 + "source": "results/grounding/grounding_all_structured.csv",
2325 + "formula": "10-K"
2326 + },
2327 + "groundAllTenQ": {
2328 + "value": "92.4",
2329 + "source": "results/grounding/grounding_all_structured.csv",
2330 + "formula": "10-Q"
2331 + },
2332 + "groundAllEightK": {
2333 + "value": "76.6",
2334 + "source": "results/grounding/grounding_all_structured.csv",
2335 + "formula": "8-K"
2336 + },
2337 + "groundAllJune": {
2338 + "value": "84.5",
2339 + "source": "results/grounding/grounding_all_structured.csv",
2340 + "formula": "backfilled_june"
2341 + },
2342 + "groundAllOctober": {
2343 + "value": "88.7",
2344 + "source": "results/grounding/grounding_all_structured.csv",
2345 + "formula": "october"
2346 + },
2347 + "groundAllTopBin": {
2348 + "value": "86.4",
2349 + "source": "results/grounding/grounding_all_structured.csv",
2350 + "formula": "bin 0.9-1.0"
2351 + },
2352 + "groundAllLowerBinsRange": {
2353 + "value": "90.7--94.2",
2354 + "source": "results/grounding/grounding_all_structured.csv",
2355 + "formula": "min--max over bins 0.45-0.6..0.8-0.9"
2356 + },
2357 + "yearsAbsentFromText": {
2358 + "value": "604",
2359 + "source": "results/grounding/fallback_bounds.json",
2360 + "formula": "years_not_subset_of_text"
2361 + },
2362 + "typeSignalMaPct": {
2363 + "value": "79.8",
2364 + "source": "results/grounding/fallback_bounds.json",
2365 + "formula": "type_signal_in_name_desc_by_type ma_integration"
2366 + },
2367 + "typeSignalTechDeployPct": {
2368 + "value": "5.4",
2369 + "source": "results/grounding/fallback_bounds.json",
2370 + "formula": "type_signal_in_name_desc_by_type technology_deployment"
2371 + },
2372 + "techRegexEqualPct": {
2373 + "value": "46",
2374 + "source": "results/grounding/fallback_bounds.json",
2375 + "formula": "100*techs_eq_regex_desc/techs_nonempty"
2376 + },
2377 + "techDeployMentionedN": {
2378 + "value": "124",
2379 + "source": "results/grounding/fallback_bounds.json",
2380 + "formula": "tech_deploy_total[1]"
2381 + },
2382 + "mentionsKeyedLocation": {
2383 + "value": "118{,}783",
2384 + "source": "results/resolver/composition.json",
2385 + "formula": "mentions_by_key_branch[location]"
2386 + },
2387 + "mentionsKeyedNameToken": {
2388 + "value": "187{,}212",
2389 + "source": "results/resolver/composition.json",
2390 + "formula": "mentions_by_key_branch[name_token]"
2391 + },
2392 + "mentionsKeyedNameTokenPct": {
2393 + "value": "60.8",
2394 + "source": "results/resolver/composition.json",
2395 + "formula": "100*name_token/mentions"
2396 + },
2397 + "mentionsKeyedLocationPct": {
2398 + "value": "38.6",
2399 + "source": "results/resolver/composition.json",
2400 + "formula": "100*location/mentions"
2401 + },
2402 + "locationKeysCountry": {
2403 + "value": "8{,}126",
2404 + "source": "results/resolver/composition.json",
2405 + "formula": "location_keyed_projects_by_geo_kind[country]"
2406 + },
2407 + "locationKeysUsState": {
2408 + "value": "6{,}110",
2409 + "source": "results/resolver/composition.json",
2410 + "formula": "location_keyed_projects_by_geo_kind[us_state]"
2411 + },
2412 + "locationKeysCountryStatePct": {
2413 + "value": "26",
2414 + "source": "results/resolver/composition.json",
2415 + "formula": "100*(country+us_state)/location-keyed projects"
2416 + },
2417 + "maAmountOtherCounterpartyN": {
2418 + "value": "1{,}630",
2419 + "source": "results/resolver/composition.json",
2420 + "formula": "amount_from_other_counterparty_ma[0]"
2421 + },
2422 + "maAmountOtherCounterpartyDenom": {
2423 + "value": "12{,}372",
2424 + "source": "results/resolver/composition.json",
2425 + "formula": "amount_from_other_counterparty_ma[1]"
2426 + },
2427 + "amountOtherCounterpartyN": {
2428 + "value": "2{,}347",
2429 + "source": "results/resolver/composition.json",
2430 + "formula": "amount_from_other_counterparty[0]"
2431 + },
2432 + "amountOtherCounterpartyDenom": {
2433 + "value": "21{,}908",
2434 + "source": "results/resolver/composition.json",
2435 + "formula": "amount_from_other_counterparty[1]"
2436 + },
2437 + "topTokenMentions": {
2438 + "value": "40{,}407",
2439 + "source": "results/resolver/top_name_tokens.csv",
2440 + "formula": "mentions of the top token"
2441 + },
2442 + "topTokenProjects": {
2443 + "value": "2{,}256",
2444 + "source": "results/resolver/top_name_tokens.csv",
2445 + "formula": "projects of the top token"
2446 + },
2447 + "topTokenSharePct": {
2448 + "value": "21.4",
2449 + "source": "results/resolver/top_name_tokens.csv",
2450 + "formula": "pct_of_tokenkeyed_mentions of the top token"
2451 + },
2452 + "locationKeyUnitedStatesProjects": {
2453 + "value": "2{,}551",
2454 + "source": "results/resolver/top_location_keys.csv",
2455 + "formula": "projects where loc1=united states"
2456 + },
2457 + "projectsKeyCikType": {
2458 + "value": "21{,}027",
934 2459 "source": "results/resolver/spec_curve.csv",
935 − "formula": "min/max projects over keys at threshold 0.45"
2460 + "formula": "projects k_cik_type at 0.45"
936 2461 },
937 − "projectCountRangeKeysN": {
938 − "value": "9",
2462 + "projectsKeyTypeDropped": {
2463 + "value": "96{,}749",
939 2464 "source": "results/resolver/spec_curve.csv",
940 − "formula": "number of keys at threshold 0.45"
2465 + "formula": "projects k_type_dropped at 0.45"
941 2466 },
942 − "projectCountRangeAll": {
943 − "value": "16{,}562--308{,}065",
2467 + "projectsKeyNameOnly": {
2468 + "value": "114{,}244",
944 2469 "source": "results/resolver/spec_curve.csv",
945 − "formula": "min/max projects over all keys x thresholds"
2470 + "formula": "projects k_name_only at 0.45"
946 2471 },
947 − "projectCountCurrentKey": {
948 − "value": "121{,}099",
2472 + "projectsKeyCityNorm": {
2473 + "value": "123{,}246",
949 2474 "source": "results/resolver/spec_curve.csv",
950 − "formula": "key=k_current at 0.45"
2475 + "formula": "projects k_city_normalised at 0.45"
951 2476 },
952 − "topNameTokens": {
953 − "value": "\\texttt{acquisition} (3.4\\%), \\texttt{share} (3.1\\%), \\texttt{expansion} (1.8\\%), \\texttt{stock} (1.7\\%), \\texttt{investment} (1.6\\%), \\texttt{merger} (1.3\\%), \\texttt{sale} (1.3\\%), \\texttt{development} (1.2\\%), \\texttt{strategic} (0.9\\%), \\texttt{capital} (0.8\\%)",
954 − "source": "results/resolver/top_name_tokens.csv",
955 − "formula": "top-10 tokens, pct of token-keyed projects"
2477 + "projectsKeyStopwords": {
2478 + "value": "130{,}101",
2479 + "source": "results/resolver/spec_curve.csv",
2480 + "formula": "projects k_current_stopwords at 0.45"
956 2481 },
957 − "topNameTokensProjectsPct": {
958 − "value": "17.2",
959 − "source": "results/resolver/top_name_tokens.csv",
960 − "formula": "sum of pct_of_tokenkeyed_projects over the top 10"
2482 + "projectsKeyTwoTokens": {
2483 + "value": "145{,}697",
2484 + "source": "results/resolver/spec_curve.csv",
2485 + "formula": "projects k_two_tokens at 0.45"
2486 + },
2487 + "projectsKeyStrict": {
2488 + "value": "198{,}488",
2489 + "source": "results/resolver/spec_curve.csv",
2490 + "formula": "projects k_strict at 0.45"
2491 + },
2492 + "projectsKeyMentionLevel": {
2493 + "value": "308{,}065",
2494 + "source": "results/resolver/spec_curve.csv",
2495 + "formula": "projects k_mention_level at 0.45"
2496 + },
2497 + "projectsCurrentKeyAtNine": {
2498 + "value": "83{,}483",
2499 + "source": "results/resolver/spec_curve.csv",
2500 + "formula": "projects k_current at 0.9"
2501 + },
2502 + "singleMentionShareStrict": {
2503 + "value": "75.8",
2504 + "source": "results/resolver/spec_curve.csv",
2505 + "formula": "single_mention_pct k_strict at 0.45"
2506 + },
2507 + "singleMentionShareCikType": {
2508 + "value": "20.7",
2509 + "source": "results/resolver/spec_curve.csv",
2510 + "formula": "single_mention_pct k_cik_type at 0.45"
2511 + },
2512 + "chenierClusterCurrent": {
2513 + "value": "8",
2514 + "source": "results/resolver/spec_curve.csv",
2515 + "formula": "example_cluster_size_cheniere k_current at 0.45"
2516 + },
2517 + "chenierClusterStrict": {
2518 + "value": "1",
2519 + "source": "results/resolver/spec_curve.csv",
2520 + "formula": "example_cluster_size_cheniere k_strict at 0.45"
2521 + },
2522 + "chenierClusterNameOnly": {
2523 + "value": "40",
2524 + "source": "results/resolver/spec_curve.csv",
2525 + "formula": "example_cluster_size_cheniere k_name_only at 0.45"
2526 + },
2527 + "chenierClusterCikType": {
2528 + "value": "176",
2529 + "source": "results/resolver/spec_curve.csv",
2530 + "formula": "example_cluster_size_cheniere k_cik_type at 0.45"
2531 + },
2532 + "maGeThreeNamesOverTenPct": {
2533 + "value": "91.7",
2534 + "source": "results/resolver/overmerge_ma_by_bucket.csv",
2535 + "formula": "pct_ge3_names bucket >10"
2536 + },
2537 + "maGeThreePartnersPct": {
2538 + "value": "10.9",
2539 + "source": "results/resolver/overmerge_by_type.csv",
2540 + "formula": "ma_integration pct_ge3_partners_among_with_partner"
2541 + },
2542 + "projectsTieDistinctDescriptions": {
2543 + "value": "29{,}954",
2544 + "source": "results/resolver/ties_idempotence.json",
2545 + "formula": "projects_with_tie_and_distinct_descriptions"
2546 + },
2547 + "rebuiltNameDiff": {
2548 + "value": "394",
2549 + "source": "results/resolver/ties_idempotence.json",
2550 + "formula": "rebuilt_vs_stored_diff[0]"
2551 + },
2552 + "rebuiltDescDiff": {
2553 + "value": "600",
2554 + "source": "results/resolver/ties_idempotence.json",
2555 + "formula": "rebuilt_vs_stored_diff[2]"
2556 + },
2557 + "tiebreakNameDiff": {
2558 + "value": "11{,}484",
2559 + "source": "results/resolver/ties_idempotence.json",
2560 + "formula": "deterministic_vs_stored_diff[0]"
2561 + },
2562 + "tiebreakStatusDiff": {
2563 + "value": "503",
2564 + "source": "results/resolver/ties_idempotence.json",
2565 + "formula": "deterministic_vs_stored_diff[1]"
2566 + },
2567 + "tiebreakDescDiff": {
2568 + "value": "18{,}256",
2569 + "source": "results/resolver/ties_idempotence.json",
2570 + "formula": "deterministic_vs_stored_diff[2]"
2571 + },
2572 + "juneProjects": {
2573 + "value": "19{,}227",
2574 + "source": "results/resolver/june_october_reconciliation.json",
2575 + "formula": "projects_from_backfilled_block_only"
2576 + },
2577 + "spMentions": {
2578 + "value": "70{,}367",
2579 + "source": "results/resolver/june_october_reconciliation.json",
2580 + "formula": "sp500_mentions_total"
2581 + },
2582 + "spProjects": {
2583 + "value": "27{,}766",
2584 + "source": "results/resolver/june_october_reconciliation.json",
2585 + "formula": "sp500_projects_total"
2586 + },
2587 + "spProjectsJuneOnly": {
2588 + "value": "15{,}910",
2589 + "source": "results/resolver/june_october_reconciliation.json",
2590 + "formula": "sp500_projects_by_run_composition[june only]"
2591 + },
2592 + "spProjectsBothRuns": {
2593 + "value": "3{,}317",
2594 + "source": "results/resolver/june_october_reconciliation.json",
2595 + "formula": "sp500_projects_by_run_composition[both runs]"
2596 + },
2597 + "spProjectsOctoberOnly": {
2598 + "value": "8{,}539",
2599 + "source": "results/resolver/june_october_reconciliation.json",
2600 + "formula": "sp500_projects_by_run_composition[october only]"
2601 + },
2602 + "octoberSpTenQSections": {
2603 + "value": "116{,}231",
2604 + "source": "results/resolver/june_october_reconciliation.json",
2605 + "formula": "sp500_october_ledger_by_form 10-Q sections"
2606 + },
2607 + "octoberSpTenQFilings": {
2608 + "value": "19{,}399",
2609 + "source": "results/resolver/june_october_reconciliation.json",
2610 + "formula": "sp500_october_ledger_by_form 10-Q filings"
2611 + },
2612 + "octoberSpTenQMentions": {
2613 + "value": "28{,}963",
2614 + "source": "results/resolver/june_october_reconciliation.json",
2615 + "formula": "sp500_mentions_by_run_form october 10-Q"
2616 + },
2617 + "octoberSpTenKMentions": {
2618 + "value": "910",
2619 + "source": "results/resolver/june_october_reconciliation.json",
2620 + "formula": "sp500_mentions_by_run_form october 10-K"
2621 + },
2622 + "octoberSpEightKMentions": {
2623 + "value": "564",
2624 + "source": "results/resolver/june_october_reconciliation.json",
2625 + "formula": "sp500_mentions_by_run_form october 8-K"
2626 + },
2627 + "juneTenQMentions": {
2628 + "value": "5{,}817",
2629 + "source": "results/resolver/june_october_reconciliation.json",
2630 + "formula": "sp500_mentions_by_run_form backfilled_june 10-Q"
2631 + },
2632 + "juneTenQFilings": {
2633 + "value": "3{,}710",
2634 + "source": "results/resolver/june_october_reconciliation.json",
2635 + "formula": "june_10q_accessions_in_block_ledger"
2636 + },
2637 + "juneTenQSections": {
2638 + "value": "23{,}873",
2639 + "source": "results/resolver/june_october_reconciliation.json",
2640 + "formula": "ledger_block_accessions_by_form 10-Q sections"
2641 + },
2642 + "repoCommits": {
2643 + "value": "six",
2644 + "source": "results/runs/git_evidence.md",
2645 + "formula": "number of commit lines"
2646 + },
2647 + "extractorMtimeDate": {
2648 + "value": "June~17, 2026",
2649 + "source": "results/runs/git_evidence.md",
2650 + "formula": "mtime of extract/llm.py"
2651 + },
2652 + "diffStoreLines": {
2653 + "value": "$+3/-1$",
2654 + "source": "results/runs/git_diff_df7905d_2324b58.patch",
2655 + "formula": "added/removed lines of the store.py hunks"
2656 + },
2657 + "diffParserLines": {
2658 + "value": "$+13/-7$",
2659 + "source": "results/runs/git_diff_0304133_2324b58.patch",
2660 + "formula": "added/removed lines of the filing_parser hunks"
2661 + },
2662 + "legacyTenKRows": {
2663 + "value": "27{,}164",
2664 + "source": "results/runs/segmenters.json",
2665 + "formula": "legacy_rows"
2666 + },
2667 + "legacyTenKFilings": {
2668 + "value": "7{,}368",
2669 + "source": "results/runs/segmenters.json",
2670 + "formula": "legacy_accessions"
2671 + },
2672 + "segPairs": {
2673 + "value": "25{,}673",
2674 + "source": "results/runs/segmenters.json",
2675 + "formula": "legacy_rows_matched_by_item"
2676 + },
2677 + "fullBodyMedianWords": {
2678 + "value": "44{,}514",
2679 + "source": "results/runs/segmenters.json",
2680 + "formula": "full_body_rows[2]"
2681 + },
2682 + "fullBodyWithParsedItems": {
2683 + "value": "1{,}117",
2684 + "source": "results/runs/segmenters.json",
2685 + "formula": "full_body_accessions_parsed_items_available[0]"
2686 + },
2687 + "fullBodyUnsubmittedSections": {
2688 + "value": "5{,}385",
2689 + "source": "results/runs/segmenters.json",
2690 + "formula": "full_body_accessions_parsed_items_available[1]"
2691 + },
2692 + "fullDocumentTenK": {
2693 + "value": "86",
2694 + "source": "results/runs/segmenters.json",
2695 + "formula": "full_document_10k[0]"
2696 + },
2697 + "fullDocumentTenKLegacy": {
2698 + "value": "51",
2699 + "source": "results/runs/segmenters.json",
2700 + "formula": "full_document_10k_in_legacy"
2701 + },
2702 + "fullDocumentTenKInvisible": {
2703 + "value": "35",
2704 + "source": "results/runs/segmenters.json",
2705 + "formula": "full_document_10k_invisible_accessions"
2706 + },
2707 + "fullDocumentTenQ": {
2708 + "value": "243",
2709 + "source": "results/runs/segmenters.json",
2710 + "formula": "full_document_by_form 10-Q rows"
2711 + },
2712 + "fullDocumentTenQLedgered": {
2713 + "value": "241",
2714 + "source": "results/runs/segmenters.json",
2715 + "formula": "full_document_by_form 10-Q ledgered"
2716 + },
2717 + "fullBodyYield": {
2718 + "value": "0.67",
2719 + "source": "results/runs/segmenters.json",
2720 + "formula": "full_body_ledger_yield[3] mentions per row"
2721 + },
2722 + "fullBodyProductivePct": {
2723 + "value": "25.7",
2724 + "source": "results/runs/segmenters.json",
2725 + "formula": "full_body_ledger_yield[4]"
2726 + },
2727 + "tenKparsedRows": {
2728 + "value": "341{,}207",
2729 + "source": "results/runs/funnel_10k.json",
2730 + "formula": "parsed_10k_rows_total"
2731 + },
2732 + "tenKoutOfScopeRows": {
2733 + "value": "188{,}518",
2734 + "source": "results/runs/funnel_10k.json",
2735 + "formula": "parsed_10k_rows_out_of_scope_item"
2736 + },
2737 + "tenKlegacyAccessionRows": {
2738 + "value": "35{,}037",
2739 + "source": "results/runs/funnel_10k.json",
2740 + "formula": "parsed_10k_in_scope_rows_of_legacy_accessions"
2741 + },
2742 + "tenKunderThirtyRows": {
2743 + "value": "1{,}112",
2744 + "source": "results/runs/funnel_10k.json",
2745 + "formula": "parsed_10k_in_scope_rows_lt30_words_non_legacy"
2746 + },
2747 + "tenKparsedLedgered": {
2748 + "value": "116{,}540",
2749 + "source": "results/runs/funnel_10k.json",
2750 + "formula": "parsed_10k_in_scope_rows_ge30_non_legacy"
2751 + },
2752 + "legacyShareTenKLedgerPct": {
2753 + "value": "19",
2754 + "source": "results/runs/segmenters.json, funnel_10k.json",
2755 + "formula": "100*legacy_rows/ledger_10k_rows"
2756 + },
2757 + "legacyMdnaDollar": {
2758 + "value": "141",
2759 + "source": "results/runs/segmenter_item_comparison.csv",
2760 + "formula": "md_and_a legacy_mean_dollar"
2761 + },
2762 + "parsedMdnaDollar": {
2763 + "value": "272",
2764 + "source": "results/runs/segmenter_item_comparison.csv",
2765 + "formula": "md_and_a parsed_mean_dollar"
2766 + },
2767 + "legacyMdnaWords": {
2768 + "value": "9{,}921",
2769 + "source": "results/runs/segmenter_item_comparison.csv",
2770 + "formula": "md_and_a legacy_median_words"
2771 + },
2772 + "parsedMdnaWords": {
2773 + "value": "11{,}661",
2774 + "source": "results/runs/segmenter_item_comparison.csv",
2775 + "formula": "md_and_a parsed_median_words"
2776 + },
2777 + "legacyFewerMoneyPct": {
2778 + "value": "92.3",
2779 + "source": "results/runs/segmenter_item_comparison.csv",
2780 + "formula": "md_and_a pct_legacy_fewer_money_tokens"
2781 + },
2782 + "legacyMdnaNumeric": {
2783 + "value": "596",
2784 + "source": "results/runs/segmenter_item_comparison.csv",
2785 + "formula": "md_and_a legacy_mean_numeric"
2786 + },
2787 + "parsedMdnaNumeric": {
2788 + "value": "1{,}177",
2789 + "source": "results/runs/segmenter_item_comparison.csv",
2790 + "formula": "md_and_a parsed_mean_numeric"
2791 + },
2792 + "propertiesLtHalfPct": {
2793 + "value": "19.4",
2794 + "source": "results/runs/segmenter_item_comparison.csv",
2795 + "formula": "properties pct_legacy_lt_half_words"
2796 + },
2797 + "withinProductiveJune": {
2798 + "value": "12.4",
2799 + "source": "results/runs/within_sp500_by_run_form.csv",
2800 + "formula": "backfilled_june 10-Q productive_pct"
2801 + },
2802 + "withinMentionsPerRowJune": {
2803 + "value": "0.244",
2804 + "source": "results/runs/within_sp500_by_run_form.csv",
2805 + "formula": "backfilled_june 10-Q mentions_per_row"
2806 + },
2807 + "withinProductiveOctober": {
2808 + "value": "12.7",
2809 + "source": "results/runs/within_sp500_by_run_form.csv",
2810 + "formula": "october 10-Q productive_pct"
2811 + },
2812 + "withinMentionsPerRowOctober": {
2813 + "value": "0.250",
2814 + "source": "results/runs/within_sp500_by_run_form.csv",
2815 + "formula": "october 10-Q mentions_per_row"
2816 + },
2817 + "withinConfJune": {
2818 + "value": "0.889",
2819 + "source": "results/runs/within_sp500_10q_mentions_by_run.csv",
2820 + "formula": "backfilled_june mean_conf"
2821 + },
2822 + "withinConfOctober": {
2823 + "value": "0.893",
2824 + "source": "results/runs/within_sp500_10q_mentions_by_run.csv",
2825 + "formula": "october mean_conf"
2826 + },
2827 + "withinMaShareJune": {
2828 + "value": "49.9",
2829 + "source": "results/runs/within_sp500_10q_type_mix_by_run.csv",
2830 + "formula": "ma_integration june_pct"
2831 + },
2832 + "withinMaShareOctober": {
2833 + "value": "45.7",
2834 + "source": "results/runs/within_sp500_10q_type_mix_by_run.csv",
2835 + "formula": "ma_integration oct_pct"
2836 + },
2837 + "pairedIssuers": {
2838 + "value": "81",
2839 + "source": "results/runs/within_issuer_paired_10q.json",
2840 + "formula": "issuers_paired"
2841 + },
2842 + "pairedDeltaPp": {
2843 + "value": "0.6",
2844 + "source": "results/runs/within_issuer_paired_10q.json",
2845 + "formula": "100*mean_diff_productive_share_oct_minus_june"
2846 + },
2847 + "pairedSePp": {
2848 + "value": "1.3",
2849 + "source": "results/runs/within_issuer_paired_10q.json",
2850 + "formula": "100*se"
2851 + },
2852 + "cohortBothPerIssuerAll": {
2853 + "value": "55.8",
2854 + "source": "results/runs/table6_cohort.csv",
2855 + "formula": "both per_issuer_all"
2856 + },
2857 + "cohortRussellOnlyPerIssuer": {
2858 + "value": "46.9",
2859 + "source": "results/runs/table6_cohort.csv",
2860 + "formula": "russell_only per_issuer_all"
2861 + },
2862 + "cohortBothPerIssuerOctober": {
2863 + "value": "25.1",
2864 + "source": "results/runs/table6_cohort.csv",
2865 + "formula": "both per_issuer_october_only"
2866 + },
2867 + "cohortOlsAll": {
2868 + "value": "8.84",
2869 + "source": "results/runs/table6_cohort_regression.json",
2870 + "formula": "projects_all_on_sp500.in_sp500.coef"
2871 + },
2872 + "cohortOlsAllSe": {
2873 + "value": "1.62",
2874 + "source": "results/runs/table6_cohort_regression.json",
2875 + "formula": "projects_all_on_sp500.in_sp500.hc1_se"
2876 + },
2877 + "cohortOlsOctober": {
2878 + "value": "-22.98",
2879 + "source": "results/runs/table6_cohort_regression.json",
2880 + "formula": "projects_october_only_on_sp500.in_sp500.coef"
2881 + },
2882 + "cohortOlsOctoberSe": {
2883 + "value": "1.20",
2884 + "source": "results/runs/table6_cohort_regression.json",
2885 + "formula": "projects_october_only_on_sp500.in_sp500.hc1_se"
2886 + },
2887 + "cohortOlsControlled": {
2888 + "value": "-0.28",
2889 + "source": "results/runs/table6_cohort_regression.json",
2890 + "formula": "projects_all_on_sp500_log_rows.in_sp500.coef"
2891 + },
2892 + "cohortOlsControlledSe": {
2893 + "value": "1.52",
2894 + "source": "results/runs/table6_cohort_regression.json",
2895 + "formula": "projects_all_on_sp500_log_rows.in_sp500.hc1_se"
2896 + },
2897 + "cohortOlsN": {
2898 + "value": "2{,}499",
2899 + "source": "results/runs/table6_cohort_regression.json",
2900 + "formula": "projects_all_on_sp500.n"
2901 + },
2902 + "fiscalYearNullOctTenK": {
2903 + "value": "823",
2904 + "source": "results/runs/fiscal_year_audit.json",
2905 + "formula": "mentions_fiscal_year_null_by_run_form october 10-K"
2906 + },
2907 + "fiscalYearNullOctTenQ": {
2908 + "value": "28{,}074",
2909 + "source": "results/runs/fiscal_year_audit.json",
2910 + "formula": "mentions_fiscal_year_null_by_run_form october 10-Q"
2911 + },
2912 + "fiscalYearNullFilings": {
2913 + "value": "134{,}124",
2914 + "source": "results/runs/fiscal_year_audit.json",
2915 + "formula": "sum src_filings_fiscal_year_null_by_form"
2916 + },
2917 + "fiscalYearFillAccessions": {
2918 + "value": "31{,}976",
2919 + "source": "results/runs/fiscal_year_fill_by_accession.csv",
2920 + "formula": "row count"
2921 + },
2922 + "focusOverBudgetSections": {
2923 + "value": "326{,}095",
2924 + "source": "results/focus/stats_keys.json",
2925 + "formula": "ledger_sections_over_9000_chars"
2926 + },
2927 + "focusOverBudgetSectionsPct": {
2928 + "value": "29",
2929 + "source": "results/focus/stats_keys.json",
2930 + "formula": "100*over/ledger_sections"
2931 + },
2932 + "focusOverBudgetCalls": {
2933 + "value": "324{,}386",
2934 + "source": "results/focus/stats_keys.json",
2935 + "formula": "calls_over_9000_chars"
2936 + },
2937 + "focusOverBudgetCallsPct": {
2938 + "value": "46",
2939 + "source": "results/focus/stats_keys.json",
2940 + "formula": "100*calls_over/calls"
2941 + },
2942 + "focusMeanShownOverBudgetPct": {
2943 + "value": "15.9",
2944 + "source": "results/focus/stats_keys.json",
2945 + "formula": "100*mean_shown_frac_over_budget"
2946 + },
2947 + "mdnaN": {
2948 + "value": "28{,}919",
2949 + "source": "results/focus/stats_keys.json",
2950 + "formula": "ledger_10k_mdna_n"
2951 + },
2952 + "mdnaMedianWords": {
2953 + "value": "9{,}905",
2954 + "source": "results/focus/stats_keys.json",
2955 + "formula": "ledger_10k_mdna_median_words"
2956 + },
2957 + "mdnaMedianChars": {
2958 + "value": "64{,}194",
2959 + "source": "results/focus/stats_keys.json",
2960 + "formula": "ledger_10k_mdna_median_chars"
2961 + },
2962 + "mdnaShownMedianPct": {
2963 + "value": "9.3",
2964 + "source": "results/focus/stats_keys.json",
2965 + "formula": "100*ledger_10k_mdna_shown_p50"
2966 + },
2967 + "mdnaLastShownMedianPct": {
2968 + "value": "16",
2969 + "source": "results/focus/stats_keys.json",
2970 + "formula": "100*ledger_10k_mdna_last_p50"
2971 + },
2972 + "mdnaShownLtTwentyFivePct": {
2973 + "value": "90.5",
2974 + "source": "results/focus/stats_keys.json",
2975 + "formula": "ledger_10k_mdna_pct_shown_lt_25"
2976 + },
2977 + "msgTruncatedN": {
2978 + "value": "0",
2979 + "source": "results/focus/stats_keys.json",
2980 + "formula": "msg_truncated_14k"
2981 + },
2982 + "mentionsFromLtTwentyFive": {
2983 + "value": "193{,}416",
2984 + "source": "results/focus/stats_keys.json",
2985 + "formula": "mentions_from_sections_shown_lt_25"
2986 + },
2987 + "mentionsFromLtTwentyFivePct": {
2988 + "value": "62.7",
2989 + "source": "results/focus/stats_keys.json",
2990 + "formula": "100*mentions_from_sections_shown_lt_25/mentions_total"
2991 + },
2992 + "mdnaShownPTenPct": {
2993 + "value": "4.3",
2994 + "source": "results/focus/focus_coverage_by_form_item.csv",
2995 + "formula": "10-K md_and_a shown_p10"
2996 + },
2997 + "mdnaShownPNinetyPct": {
2998 + "value": "24",
2999 + "source": "results/focus/focus_coverage_by_form_item.csv",
3000 + "formula": "10-K md_and_a shown_p90"
3001 + },
3002 + "mdnaHitsShownMedianPct": {
3003 + "value": "15.6",
3004 + "source": "results/focus/focus_coverage_by_form_item.csv",
3005 + "formula": "10-K md_and_a hits_shown_p50"
3006 + },
3007 + "businessShownMedianPct": {
3008 + "value": "15.7",
3009 + "source": "results/focus/focus_coverage_by_form_item.csv",
3010 + "formula": "10-K business shown_p50"
3011 + },
3012 + "riskShownMedianPct": {
3013 + "value": "10.1",
3014 + "source": "results/focus/focus_coverage_by_form_item.csv",
3015 + "formula": "10-K risk_factors shown_p50"
3016 + },
3017 + "tenQmdnaShownMedianPct": {
3018 + "value": "13.2",
3019 + "source": "results/focus/focus_coverage_by_form_item.csv",
3020 + "formula": "10-Q md_and_a shown_p50"
3021 + },
3022 + "tenQfinShownMedianPct": {
3023 + "value": "10.6",
3024 + "source": "results/focus/focus_coverage_by_form_item.csv",
3025 + "formula": "10-Q financial_statements shown_p50"
3026 + },
3027 + "capexVocabShownMdnaPct": {
3028 + "value": "5.8",
3029 + "source": "results/focus/focus_coverage_by_form_item.csv",
3030 + "formula": "10-K md_and_a pct_capex_vocab_shown_over_budget"
3031 + },
3032 + "capexVocabShownBusinessPct": {
3033 + "value": "10.0",
3034 + "source": "results/focus/focus_coverage_by_form_item.csv",
3035 + "formula": "10-K business pct_capex_vocab_shown_over_budget"
3036 + },
3037 + "capexVocabShownTenQmdnaPct": {
3038 + "value": "8.3",
3039 + "source": "results/focus/focus_coverage_by_form_item.csv",
3040 + "formula": "10-Q md_and_a pct_capex_vocab_shown_over_budget"
3041 + },
3042 + "eightKWholePct": {
3043 + "value": "91",
3044 + "source": "results/focus/focus_coverage_by_form_item.csv",
3045 + "formula": "100 - 8-K pct_over_9000"
3046 + },
3047 + "mentionsFromLtTwentyFiveTenK": {
3048 + "value": "84",
3049 + "source": "results/focus/focus_coverage_by_form.csv",
3050 + "formula": "10-K pct_mentions_from_lt25"
3051 + },
3052 + "mentionsFromLtTwentyFiveTenQ": {
3053 + "value": "79",
3054 + "source": "results/focus/focus_coverage_by_form.csv",
3055 + "formula": "10-Q pct_mentions_from_lt25"
3056 + },
3057 + "mentionsFromLtTwentyFiveEightK": {
3058 + "value": "6",
3059 + "source": "results/focus/focus_coverage_by_form.csv",
3060 + "formula": "8-K pct_mentions_from_lt25"
3061 + },
3062 + "plateauLow": {
3063 + "value": "0.4",
3064 + "source": "results/focus/mentions_vs_length_by_item.csv",
3065 + "formula": "10-K md_and_a mean_mentions, 3-6k bin"
3066 + },
3067 + "plateauHigh": {
3068 + "value": "1.5",
3069 + "source": "results/focus/mentions_vs_length_by_item.csv",
3070 + "formula": "10-K md_and_a mean_mentions, 20-40k bin (plateau start)"
3071 + },
3072 + "plateauRange": {
3073 + "value": "1.2--1.6",
3074 + "source": "results/focus/mentions_vs_length_by_item.csv",
3075 + "formula": "10-K md_and_a mean_mentions over bins >= 20k"
3076 + },
3077 + "plateauKchars": {
3078 + "value": "20{,}000",
3079 + "source": "results/focus/mentions_vs_length_by_item.csv",
3080 + "formula": "lower edge of the f20-40k bin"
3081 + },
3082 + "mentionsPerTenKShownChars": {
3083 + "value": "2.5",
3084 + "source": "results/focus/mentions_vs_length_by_item.csv",
3085 + "formula": "median mentions_per_10k_shown_chars over bins >= 20k"
3086 + },
3087 + "shortMdnaN": {
3088 + "value": "169",
3089 + "source": "results/focus/mdna_10k_short_by_year.csv",
3090 + "formula": "sum(lt30_words)"
3091 + },
3092 + "shortMdnaDenom": {
3093 + "value": "29{,}088",
3094 + "source": "results/focus/mdna_10k_short_by_year.csv",
3095 + "formula": "sum(mdna_sections)"
3096 + },
3097 + "shortMdnaPct": {
3098 + "value": "0.6",
3099 + "source": "results/focus/mdna_10k_short_by_year.csv",
3100 + "formula": "100*sum(lt30)/sum(sections)"
3101 + },
3102 + "shortMdnaIncorporatedN": {
3103 + "value": "430",
3104 + "source": "results/focus/mdna_10k_short_by_year.csv",
3105 + "formula": "sum(lt300_incorporated_by_ref)"
3106 + },
3107 + "rulesFocusRecovered": {
3108 + "value": "84{,}841",
3109 + "source": "results/rules/focus_recall_loss_overall.csv",
3110 + "formula": "rules_focused"
3111 + },
3112 + "rulesFocusTotal": {
3113 + "value": "324{,}237",
3114 + "source": "results/rules/focus_recall_loss_overall.csv",
3115 + "formula": "rules_full"
3116 + },
3117 + "rulesFocusRecoveredPct": {
3118 + "value": "26.2",
3119 + "source": "results/rules/focus_recall_loss_overall.csv",
3120 + "formula": "100 - pct_lost"
3121 + },
3122 + "rulesFocusBusinessPct": {
3123 + "value": "36.9",
3124 + "source": "results/rules/focus_recall_loss.csv",
3125 + "formula": "10-K business 100 - pct_rules_mentions_lost_to_focus"
3126 + },
3127 + "rulesFocusMdnaPct": {
3128 + "value": "20.8",
3129 + "source": "results/rules/focus_recall_loss.csv",
3130 + "formula": "10-K md_and_a 100 - pct_rules_mentions_lost_to_focus"
3131 + },
3132 + "rulesFocusTenQmdnaPct": {
3133 + "value": "25.1",
3134 + "source": "results/rules/focus_recall_loss.csv",
3135 + "formula": "10-Q md_and_a 100 - pct_rules_mentions_lost_to_focus"
3136 + },
3137 + "rulesFocusEightKPct": {
3138 + "value": "84.2",
3139 + "source": "results/rules/focus_recall_loss.csv",
3140 + "formula": "8-K full_body 100 - pct_rules_mentions_lost_to_focus"
3141 + },
3142 + "rulesSampleProductive": {
3143 + "value": "30{,}000",
3144 + "source": "results/rules/agreement_overall.csv",
3145 + "formula": "llm_pos (sampled productive sections)"
3146 + },
3147 + "rulesSampleZero": {
3148 + "value": "30{,}000",
3149 + "source": "results/rules/agreement_overall.csv",
3150 + "formula": "n_sampled - llm_pos"
3151 + },
3152 + "rulesFlagPct": {
3153 + "value": "39.5",
3154 + "source": "results/rules/agreement_overall.csv",
3155 + "formula": "rules_pos_pct_weighted"
3156 + },
3157 + "rulesAgreementPct": {
3158 + "value": "71.2",
3159 + "source": "results/rules/agreement_overall.csv",
3160 + "formula": "agreement_pct_w"
3161 + },
3162 + "rulesLlmOnlyPct": {
3163 + "value": "2.1",
3164 + "source": "results/rules/agreement_overall.csv",
3165 + "formula": "llm_only_pct_w"
3166 + },
3167 + "rulesOnlyPct": {
3168 + "value": "26.6",
3169 + "source": "results/rules/agreement_overall.csv",
3170 + "formula": "rules_only_pct_w"
3171 + },
3172 + "rulesTypeOverlapPct": {
3173 + "value": "84.6",
3174 + "source": "results/rules/agreement_overall.csv",
3175 + "formula": "type_overlap_pct_codetected"
3176 + },
3177 + "rulesGivenLlmTenK": {
3178 + "value": "97.4",
3179 + "source": "results/rules/agreement_by_form.csv",
3180 + "formula": "10-K p_rules_given_llm"
3181 + },
3182 + "rulesGivenLlmTenQ": {
3183 + "value": "94.4",
3184 + "source": "results/rules/agreement_by_form.csv",
3185 + "formula": "10-Q p_rules_given_llm"
3186 + },
3187 + "rulesGivenLlmEightK": {
3188 + "value": "69.2",
3189 + "source": "results/rules/agreement_by_form.csv",
3190 + "formula": "8-K p_rules_given_llm"
3191 + },
3192 + "rulesGivenLlmJune": {
3193 + "value": "79.8",
3194 + "source": "results/rules/agreement_by_run.csv",
3195 + "formula": "backfilled_june p_rules_given_llm"
3196 + },
3197 + "rulesGivenLlmOctober": {
3198 + "value": "86.7",
3199 + "source": "results/rules/agreement_by_run.csv",
3200 + "formula": "october p_rules_given_llm"
3201 + },
3202 + "rulesTypeMa": {
3203 + "value": "96.8",
3204 + "source": "results/rules/type_agreement.csv",
3205 + "formula": "ma_integration pct"
3206 + },
3207 + "rulesTypeGeo": {
3208 + "value": "36.5",
3209 + "source": "results/rules/type_agreement.csv",
3210 + "formula": "geographic_expansion pct"
3211 + },
3212 + "rulesTypeCapex": {
3213 + "value": "55.2",
3214 + "source": "results/rules/type_agreement.csv",
3215 + "formula": "capex_program pct"
3216 + },
3217 + "rulesTypePlant": {
3218 + "value": "40.7",
3219 + "source": "results/rules/type_agreement.csv",
3220 + "formula": "plant_construction pct"
3221 + },
3222 + "rulesTypeDrug": {
3223 + "value": "92.5",
3224 + "source": "results/rules/type_agreement.csv",
3225 + "formula": "drug_pipeline pct"
3226 + },
3227 + "rulesTypeCost": {
3228 + "value": "76.9",
3229 + "source": "results/rules/type_agreement.csv",
3230 + "formula": "cost_reduction pct"
3231 + },
3232 + "finMentions": {
3233 + "value": "22{,}412",
3234 + "source": "results/fp_classes/summary.json",
3235 + "formula": "mentions_matched[0]"
3236 + },
3237 + "finMentionsPct": {
3238 + "value": "7.3",
3239 + "source": "results/fp_classes/summary.json",
3240 + "formula": "mentions_matched[2]"
3241 + },
3242 + "finAmountB": {
3243 + "value": "17.8",
3244 + "source": "results/fp_classes/summary.json",
3245 + "formula": "matched_amount_gusd[0]/1e3 (T USD)"
3246 + },
3247 + "finAmountDenomB": {
3248 + "value": "104.2",
3249 + "source": "results/fp_classes/summary.json",
3250 + "formula": "matched_amount_gusd[1]/1e3 (T USD)"
3251 + },
3252 + "finAmountSharePct": {
3253 + "value": "17.1",
3254 + "source": "results/fp_classes/summary.json",
3255 + "formula": "100*matched_amount_gusd[0]/[1]"
3256 + },
3257 + "finUnregPct": {
3258 + "value": "54.5",
3259 + "source": "results/fp_classes/summary.json",
3260 + "formula": "100*unregistered_sales_matched[0]/[1]"
3261 + },
3262 + "finUnregN": {
3263 + "value": "5{,}179",
3264 + "source": "results/fp_classes/summary.json",
3265 + "formula": "unregistered_sales_matched[0]"
3266 + },
3267 + "finUnregDenom": {
3268 + "value": "9{,}506",
3269 + "source": "results/fp_classes/summary.json",
3270 + "formula": "unregistered_sales_matched[1]"
3271 + },
3272 + "finFinStatementsPct": {
3273 + "value": "2.4",
3274 + "source": "results/fp_classes/summary.json",
3275 + "formula": "100*financial_statements_matched[0]/[1]"
3276 + },
3277 + "finControlsPct": {
3278 + "value": "0.2",
3279 + "source": "results/fp_classes/summary.json",
3280 + "formula": "100*controls_matched[0]/[1]"
3281 + },
3282 + "finProjectsRep": {
3283 + "value": "12{,}027",
3284 + "source": "results/fp_classes/summary.json",
3285 + "formula": "projects_matched_rep[0]"
3286 + },
3287 + "finProjectsRepPct": {
3288 + "value": "9.9",
3289 + "source": "results/fp_classes/summary.json",
3290 + "formula": "100*projects_matched_rep[0]/projects"
3291 + },
3292 + "finProjectsAny": {
3293 + "value": "13{,}139",
3294 + "source": "results/fp_classes/summary.json",
3295 + "formula": "projects_matched_rep[1]"
3296 + },
3297 + "itemTwoPairs": {
3298 + "value": "77{,}869",
3299 + "source": "results/fp_classes/summary.json",
3300 + "formula": "item2_collision pairs"
3301 + },
3302 + "unregMedianWords": {
3303 + "value": "602",
3304 + "source": "results/fp_classes/summary.json",
3305 + "formula": "item2_collision median_unreg_words"
3306 + },
3307 + "tenQmdnaMedianWords": {
3308 + "value": "7{,}573",
3309 + "source": "results/fp_classes/summary.json",
3310 + "formula": "item2_collision median_mdna_words"
3311 + },
3312 + "unregGtThreeK": {
3313 + "value": "1{,}001",
3314 + "source": "results/fp_classes/summary.json",
3315 + "formula": "item2_collision unreg_gt_3000"
3316 + },
3317 + "unregGtThreeKPct": {
3318 + "value": "1.3",
3319 + "source": "results/fp_classes/summary.json",
3320 + "formula": "item2_collision pct_gt_3000"
3321 + },
3322 + "swapCandidates": {
3323 + "value": "296",
3324 + "source": "results/fp_classes/summary.json",
3325 + "formula": "item2_collision swapped_candidates"
3326 + },
3327 + "unregLongThreshold": {
3328 + "value": "3{,}000",
3329 + "source": "results/fp_classes/summary.json",
3330 + "formula": "item2_collision threshold (unreg_gt_3000)"
3331 + },
3332 + "unregGtThreeKMentions": {
3333 + "value": "425",
3334 + "source": "results/fp_classes/summary.json",
3335 + "formula": "unregistered_sales_mentions_from_gt3000[0]"
3336 + },
3337 + "finEightKPct": {
3338 + "value": "19.2",
3339 + "source": "results/fp_classes/financing_regex_by_item.csv",
3340 + "formula": "8-K full_body pct"
3341 + },
3342 + "finMaPct": {
3343 + "value": "7.0",
3344 + "source": "results/fp_classes/financing_regex_by_type.csv",
3345 + "formula": "ma_integration pct"
3346 + },
3347 + "finCapexPct": {
3348 + "value": "52.6",
3349 + "source": "results/fp_classes/financing_regex_by_type.csv",
3350 + "formula": "capex_program pct"
3351 + },
3352 + "finCostPct": {
3353 + "value": "16.4",
3354 + "source": "results/fp_classes/financing_regex_by_type.csv",
3355 + "formula": "cost_reduction pct"
3356 + },
3357 + "finTermRepurchase": {
3358 + "value": "10{,}886",
3359 + "source": "results/fp_classes/financing_regex_terms.csv",
3360 + "formula": "repurchase n"
3361 + },
3362 + "finTermSeniorNotes": {
3363 + "value": "3{,}375",
3364 + "source": "results/fp_classes/financing_regex_terms.csv",
3365 + "formula": "senior notes n"
3366 + },
3367 + "finTermTermLoan": {
3368 + "value": "2{,}263",
3369 + "source": "results/fp_classes/financing_regex_terms.csv",
3370 + "formula": "term loan n"
3371 + },
3372 + "capexProjectsExcl": {
3373 + "value": "4{,}725",
3374 + "source": "results/fp_classes/table5_restated_excl_financing.csv",
3375 + "formula": "capex_program n_excl_rep"
3376 + },
3377 + "costProjectsExcl": {
3378 + "value": "5{,}403",
3379 + "source": "results/fp_classes/table5_restated_excl_financing.csv",
3380 + "formula": "cost_reduction n_excl_rep"
3381 + },
3382 + "maProjectsExcl": {
3383 + "value": "37{,}527",
3384 + "source": "results/fp_classes/table5_restated_excl_financing.csv",
3385 + "formula": "ma_integration n_excl_rep"
3386 + },
3387 + "capexShareExcl": {
3388 + "value": "4.3",
3389 + "source": "results/fp_classes/table5_restated_excl_financing.csv",
3390 + "formula": "capex_program pct_excl_rep"
3391 + },
3392 + "eightKItemCodePct": {
3393 + "value": "99.7",
3394 + "source": "results/benchmark_8k/summary.json",
3395 + "formula": "coverage_pct"
3396 + },
3397 + "benchMaGivenTwoOhOne": {
3398 + "value": "0.911",
3399 + "source": "results/benchmark_8k/item_vs_type.csv",
3400 + "formula": "ma_integration Item 2.01 p_type_given_item"
3401 + },
3402 + "benchMaGivenTwoOhOneCiLow": {
3403 + "value": "0.903",
3404 + "source": "results/benchmark_8k/item_vs_type.csv",
3405 + "formula": "ci_low_1"
3406 + },
3407 + "benchMaGivenTwoOhOneCiHigh": {
3408 + "value": "0.918",
3409 + "source": "results/benchmark_8k/item_vs_type.csv",
3410 + "formula": "ci_high_1"
3411 + },
3412 + "benchTwoOhOneN": {
3413 + "value": "5{,}456",
3414 + "source": "results/benchmark_8k/item_vs_type.csv",
3415 + "formula": "n_item Item 2.01"
3416 + },
3417 + "benchMaBase": {
3418 + "value": "0.095",
3419 + "source": "results/benchmark_8k/item_vs_type.csv",
3420 + "formula": "ma_integration base_rate_type"
3421 + },
3422 + "benchMaGivenEightOhOne": {
3423 + "value": "0.199",
3424 + "source": "results/benchmark_8k/item_vs_type.csv",
3425 + "formula": "ma_integration Item 8.01 p_type_given_item"
3426 + },
3427 + "benchMaGivenFiveOhTwo": {
3428 + "value": "0.031",
3429 + "source": "results/benchmark_8k/item_vs_type.csv",
3430 + "formula": "ma_integration Item 5.02 p_type_given_item"
3431 + },
3432 + "benchItemsGivenMa": {
3433 + "value": "0.467",
3434 + "source": "results/benchmark_8k/item_vs_type.csv",
3435 + "formula": "ma_integration Item 2.01 or 1.01 p_item_given_type"
3436 + },
3437 + "benchCostGivenTwoOhFive": {
3438 + "value": "0.709",
3439 + "source": "results/benchmark_8k/item_vs_type.csv",
3440 + "formula": "cost_reduction Item 2.05 p_type_given_item"
3441 + },
3442 + "benchCostGivenTwoOhFiveCiLow": {
3443 + "value": "0.687",
3444 + "source": "results/benchmark_8k/item_vs_type.csv",
3445 + "formula": "ci_low_1"
3446 + },
3447 + "benchCostGivenTwoOhFiveCiHigh": {
3448 + "value": "0.730",
3449 + "source": "results/benchmark_8k/item_vs_type.csv",
3450 + "formula": "ci_high_1"
3451 + },
3452 + "benchTwoOhFiveN": {
3453 + "value": "1{,}700",
3454 + "source": "results/benchmark_8k/item_vs_type.csv",
3455 + "formula": "n_item Item 2.05"
3456 + },
3457 + "benchCostLift": {
3458 + "value": "92",
3459 + "source": "results/benchmark_8k/item_vs_type.csv",
3460 + "formula": "lift_type_given_item"
3461 + },
3462 + "benchTwoOhFiveGivenCost": {
3463 + "value": "0.392",
3464 + "source": "results/benchmark_8k/item_vs_type.csv",
3465 + "formula": "p_item_given_type"
3466 + },
3467 + "benchPartnershipGivenOneOhOne": {
3468 + "value": "0.040",
3469 + "source": "results/benchmark_8k/item_vs_type.csv",
3470 + "formula": "partnership Item 1.01 p_type_given_item"
3471 + },
3472 + "benchPartnershipBase": {
3473 + "value": "0.011",
3474 + "source": "results/benchmark_8k/item_vs_type.csv",
3475 + "formula": "partnership base_rate_type"
3476 + },
3477 + "annSeed": {
3478 + "value": "20261105",
3479 + "source": "results/annotation_frame/design.json",
3480 + "formula": "seed"
3481 + },
3482 + "annStrata": {
3483 + "value": "192",
3484 + "source": "results/annotation_frame/design.json",
3485 + "formula": "n_strata_productive"
3486 + },
3487 + "annNProductive": {
3488 + "value": "1{,}677",
3489 + "source": "results/annotation_frame/design.json",
3490 + "formula": "n_productive"
3491 + },
3492 + "annNZero": {
3493 + "value": "385",
3494 + "source": "results/annotation_frame/design.json",
3495 + "formula": "n_zero"
3496 + },
3497 + "annZeroGatePass": {
3498 + "value": "285",
3499 + "source": "results/annotation_frame/design.json",
3500 + "formula": "zero_frame_gate_pass"
3501 + },
3502 + "annZeroGateReject": {
3503 + "value": "100",
3504 + "source": "results/annotation_frame/design.json",
3505 + "formula": "zero_frame_gate_reject"
3506 + },
3507 + "annDeffProductive": {
3508 + "value": "3.4",
3509 + "source": "results/annotation_frame/design.json",
3510 + "formula": "deff_productive"
3511 + },
3512 + "annDeffZero": {
3513 + "value": "1.2",
3514 + "source": "results/annotation_frame/design.json",
3515 + "formula": "deff_zero"
3516 + },
3517 + "annHalfWidthPrecision": {
3518 + "value": "4.4",
3519 + "source": "results/annotation_frame/design.json",
3520 + "formula": "half_width_95_precision_p0.5"
3521 + },
3522 + "annMde": {
3523 + "value": "7.8",
3524 + "source": "results/annotation_frame/design.json",
3525 + "formula": "mde_gate_recall_diff_at_p0.05"
3526 + },
3527 + "annFloor": {
3528 + "value": "10",
3529 + "source": "results/annotation_frame/design.json",
3530 + "formula": "floor"
3531 + },
3532 + "annOversample": {
3533 + "value": "2",
3534 + "source": "results/annotation_frame/design.json",
3535 + "formula": "oversample_conf_0.45_0.7"
3536 + },
3537 + "annPopProductive": {
3538 + "value": "168{,}230",
3539 + "source": "results/annotation_frame/design.json",
3540 + "formula": "population_productive"
3541 + },
3542 + "annPopZero": {
3543 + "value": "954{,}868",
3544 + "source": "results/annotation_frame/design.json",
3545 + "formula": "population_zero"
3546 + },
3547 + "annHalfWidthFn": {
3548 + "value": "2.4",
3549 + "source": "results/annotation_frame/design.json",
3550 + "formula": "half_width_95_zero_fn_rate[0.05]"
3551 + },
3552 + "annCore": {
3553 + "value": "510",
3554 + "source": "results/annotation_frame/design.json",
3555 + "formula": "core_subsample.productive"
3556 + },
3557 + "annDev": {
3558 + "value": "1{,}058",
3559 + "source": "results/annotation_frame/design.json",
3560 + "formula": "split.dev"
3561 + },
3562 + "annHoldout": {
3563 + "value": "1{,}004",
3564 + "source": "results/annotation_frame/design.json",
3565 + "formula": "split.holdout"
3566 + },
3567 + "annTextChars": {
3568 + "value": "2{,}000",
3569 + "source": "results/annotation_frame/frame_dev.csv",
3570 + "formula": "text truncation of the worktree frames (characters)"
3571 + },
3572 + "annFrameMb": {
3573 + "value": "77",
3574 + "source": "data/documented_inputs.json:annotation_frame_mb",
3575 + "formula": "size of the full-text frames kept on the node (M3U96b:~/firc0001_review/frames/, N11 implemented_changes.md); not shipped"
3576 + },
3577 + "firstSeenLastYear": {
3578 + "value": "6{,}694",
3579 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
3580 + "formula": "all_issuers last year first_seen_current_key"
3581 + },
3582 + "fixedCohortIssuers": {
3583 + "value": "1{,}389",
3584 + "source": "results/timeseries/summary.json",
3585 + "formula": "cohort_issuers"
3586 + },
3587 + "fixedCohortMentionsPerIssuerFirst": {
3588 + "value": "9.6",
3589 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
3590 + "formula": "fixed cohort 2011"
3591 + },
3592 + "fixedCohortMentionsPerIssuerLast": {
3593 + "value": "8.8",
3594 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
3595 + "formula": "fixed cohort 2025"
3596 + },
3597 + "fixedCohortNewPerIssuerFirst": {
3598 + "value": "4.7",
3599 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
3600 + "formula": "fixed cohort 2011"
3601 + },
3602 + "fixedCohortNewPerIssuerLast": {
3603 + "value": "2.8",
3604 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
3605 + "formula": "fixed cohort 2025"
3606 + },
3607 + "fixedCohortFirstSeenFirst": {
3608 + "value": "6{,}533",
3609 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
3610 + "formula": "fixed cohort 2011"
3611 + },
3612 + "fixedCohortFirstSeenLast": {
3613 + "value": "3{,}926",
3614 + "source": "results/timeseries/first_seen_fixed_cohort.csv",
3615 + "formula": "fixed cohort 2025"
3616 + },
3617 + "episodesKthree": {
3618 + "value": "131{,}823",
3619 + "source": "results/timeseries/summary.json",
3620 + "formula": "episodes_k3_total"
3621 + },
3622 + "episodesKfive": {
3623 + "value": "126{,}318",
3624 + "source": "results/timeseries/summary.json",
3625 + "formula": "episodes_k5_total"
3626 + },
3627 + "dualClassCiks": {
3628 + "value": "18",
3629 + "source": "stats.json:universe",
3630 + "formula": "mapped lines - distinct CIKs"
3631 + },
3632 + "universeBoth": {
3633 + "value": "491",
3634 + "source": "stats.json:universe.both",
3635 + "formula": "count"
3636 + },
3637 + "universeSpOnly": {
3638 + "value": "9",
3639 + "source": "stats.json:universe.sp_only",
3640 + "formula": "count"
3641 + },
3642 + "universeRuOnly": {
3643 + "value": "2{,}064",
3644 + "source": "stats.json:universe.ru_only",
3645 + "formula": "count"
3646 + },
3647 + "russellGapMax": {
3648 + "value": "441",
3649 + "source": "results/russell_coverage.json",
3650 + "formula": "index_constituents - russell_distinct_ciks"
3651 + },
3652 + "russellGapMaxPct": {
3653 + "value": "14.7",
3654 + "source": "results/russell_coverage.json",
3655 + "formula": "100*(index - proxy)/index"
3656 + },
3657 + "factsheetDate": {
3658 + "value": "September~30, 2026",
3659 + "source": "results/russell_coverage.json:index_as_of",
3660 + "formula": "date"
3661 + },
3662 + "iwvHoldingsDate": {
3663 + "value": "October~23, 2026",
3664 + "source": "stats.json:universe.russell_holdings_as_of",
3665 + "formula": "date"
3666 + },
3667 + "iwvFetchDate": {
3668 + "value": "October~27, 2026",
3669 + "source": "stats.json:universe.russell_fetched_at",
3670 + "formula": "date"
3671 + },
3672 + "spWikipediaRows": {
3673 + "value": "503",
3674 + "source": "stats.json:universe.sp500_rows",
3675 + "formula": "count"
3676 + },
3677 + "spWikipediaDate": {
3678 + "value": "May~25, 2026",
3679 + "source": "stats.json:universe.sp500_fetched_at",
3680 + "formula": "date"
3681 + },
3682 + "tickerMapSize": {
3683 + "value": "10{,}430",
3684 + "source": "results/universe/universe_artefacts.json",
3685 + "formula": "cik_mapping_scalars.count"
3686 + },
3687 + "issuersFilingsNoProject": {
3688 + "value": "7",
3689 + "source": "stats.json",
3690 + "formula": "issuers_with_filings - issuers_with_projects"
3691 + },
3692 + "parseErrors": {
3693 + "value": "14",
3694 + "source": "data/parse_status.csv",
3695 + "formula": "sum(error)"
3696 + },
3697 + "filingsNotParsedPct": {
3698 + "value": "0.003",
3699 + "source": "data/parse_status.csv, stats.json",
3700 + "formula": "100*not_parsed/filings_total"
3701 + },
3702 + "spidDbGb": {
3703 + "value": "3.2",
3704 + "source": "results/rules/manifest.json",
3705 + "formula": "spid.duckdb bytes / 1e9"
3706 + },
3707 + "corpusDbGb": {
3708 + "value": "68",
3709 + "source": "results/rules/manifest.json",
3710 + "formula": "edgar_research.duckdb bytes / 2^30"
3711 + },
3712 + "corpusParquetGb": {
3713 + "value": "29.1",
3714 + "source": "data/documented_inputs.json:corpus_parquet_gb",
3715 + "formula": "N0 schema probe (results/n0_probe, commit 7680606): parquet corpus 1,342,283 sections / 29.1 GB on the master node"
3716 + },
3717 + "requirementsLockPackages": {
3718 + "value": "88",
3719 + "source": "requirements.lock",
3720 + "formula": "non-comment lines"
3721 + },
3722 + "pythonVersion": {
3723 + "value": "3.12.15",
3724 + "source": ".python-version",
3725 + "formula": "file content"
3726 + },
3727 + "duckdbVersion": {
3728 + "value": "2.0.0",
3729 + "source": "environment.md",
3730 + "formula": "duckdb (python)"
3731 + },
3732 + "testsN": {
3733 + "value": "22",
3734 + "source": "tests/test_tables.py",
3735 + "formula": "test functions, parametrised cases expanded"
3736 + },
3737 + "snapshotFilesN": {
3738 + "value": "nine",
3739 + "source": "code/audit/spid_snapshot/SHA256SUMS",
3740 + "formula": "lines"
3741 + },
3742 + "annualPanelRows": {
3743 + "value": "32{,}852",
3744 + "source": "data/factor_tables.csv",
3745 + "formula": "annual_panel n"
3746 + },
3747 + "quarterlyPanelRows": {
3748 + "value": "128{,}043",
3749 + "source": "data/factor_tables.csv",
3750 + "formula": "quarterly_panel n"
3751 + },
3752 + "mentionsPerProjectDrug": {
3753 + "value": "4.99",
3754 + "source": "data/projects_by_type.csv",
3755 + "formula": "drug_pipeline mean_mentions"
3756 + },
3757 + "mentionsPerProjectTechDeploy": {
3758 + "value": "1.63",
3759 + "source": "data/projects_by_type.csv",
3760 + "formula": "technology_deployment mean_mentions"
3761 + },
3762 + "nCostReduction": {
3763 + "value": "6{,}481",
3764 + "source": "data/projects_by_type.csv",
3765 + "formula": "cost_reduction n"
3766 + },
3767 + "amountPTwentyFiveMusd": {
3768 + "value": "23",
3769 + "source": "data/amount_dist.csv",
3770 + "formula": "q[1]/1e6"
3771 + },
3772 + "spanZeroN": {
3773 + "value": "67{,}170",
3774 + "source": "data/duration.csv",
3775 + "formula": "n where span_years=0"
3776 + },
3777 + "confShareHalf": {
3778 + "value": "0.5",
3779 + "source": "data/confidence_dist.csv",
3780 + "formula": "100*n(conf=0.5)/mentions"
3781 + },
3782 + "kgEdgesOwns": {
3783 + "value": "121{,}099",
3784 + "source": "data/kg.csv",
3785 + "formula": "edges owns"
3786 + },
3787 + "kgEdgesLocatedIn": {
3788 + "value": "54{,}583",
3789 + "source": "data/kg.csv",
3790 + "formula": "edges located_in"
3791 + },
3792 + "kgEdgesUses": {
3793 + "value": "28{,}774",
3794 + "source": "data/kg.csv",
3795 + "formula": "edges uses"
3796 + },
3797 + "projectsPerIssuerMax": {
3798 + "value": "240",
3799 + "source": "data/projects_per_issuer.csv",
3800 + "formula": "mx"
3801 + },
3802 + "focusWindowBefore": {
3803 + "value": "220",
3804 + "source": "code/audit/spid_snapshot/llm.py",
3805 + "formula": "_focus: characters before a gate hit"
3806 + },
3807 + "focusWindowAfter": {
3808 + "value": "380",
3809 + "source": "code/audit/spid_snapshot/llm.py",
3810 + "formula": "_focus: characters after a gate hit"
3811 + },
3812 + "focusEmitBudget": {
3813 + "value": "9{,}000",
3814 + "source": "code/audit/spid_snapshot/llm.py",
3815 + "formula": "_focus budget"
3816 + },
3817 + "focusCollectBudget": {
3818 + "value": "12{,}600",
3819 + "source": "code/audit/spid_snapshot/llm.py",
3820 + "formula": "budget * collection multiplier"
3821 + },
3822 + "userMessageCap": {
3823 + "value": "14{,}000",
3824 + "source": "code/audit/spid_snapshot/llm.py",
3825 + "formula": "user message cut"
3826 + },
3827 + "confDefault": {
3828 + "value": "0.6",
3829 + "source": "code/audit/spid_snapshot/llm.py",
3830 + "formula": "default confidence"
3831 + },
3832 + "confThreshold": {
3833 + "value": "0.45",
3834 + "source": "code/audit/spid_snapshot/llm.py",
3835 + "formula": "confidence threshold"
3836 + },
3837 + "completionTokens": {
3838 + "value": "2{,}000",
3839 + "source": "code/audit/spid_snapshot/llm.py",
3840 + "formula": "max_tokens"
3841 + },
3842 + "listItemsMax": {
3843 + "value": "eight",
3844 + "source": "code/audit/spid_snapshot/llm.py",
3845 + "formula": "list truncation (items)"
3846 + },
3847 + "listItemChars": {
3848 + "value": "120",
3849 + "source": "code/audit/spid_snapshot/llm.py",
3850 + "formula": "list item truncation (characters)"
3851 + },
3852 + "idNameChars": {
3853 + "value": "40",
3854 + "source": "code/audit/spid_snapshot/llm.py",
3855 + "formula": "anchor name prefix length"
3856 + },
3857 + "retries": {
3858 + "value": "three",
3859 + "source": "code/audit/spid_snapshot/llm.py",
3860 + "formula": "_call retries"
3861 + },
3862 + "timeoutSeconds": {
3863 + "value": "120",
3864 + "source": "code/audit/spid_snapshot/config.py",
3865 + "formula": "llm_timeout"
3866 + },
3867 + "minWords": {
3868 + "value": "30",
3869 + "source": "code/audit/spid_snapshot/pipeline.py",
3870 + "formula": "min_words"
3871 + },
3872 + "chunkWords": {
3873 + "value": "512",
3874 + "source": "src/parsing/chunker.py",
3875 + "formula": "chunk_size"
3876 + },
3877 + "chunkOverlap": {
3878 + "value": "64",
3879 + "source": "src/parsing/chunker.py",
3880 + "formula": "overlap"
3881 + },
3882 + "maxFileMb": {
3883 + "value": "50",
3884 + "source": "src/parsing/html_parser.py",
3885 + "formula": "max_file_size_mb default"
3886 + },
3887 + "cooldownSeconds": {
3888 + "value": "65",
3889 + "source": "src/acquisition/bulk_downloader.py",
3890 + "formula": "COOLDOWN_SECONDS"
3891 + },
3892 + "secRateLimit": {
3893 + "value": "ten",
3894 + "source": "src/acquisition/bulk_downloader.py (docstring) / secfairaccess",
3895 + "formula": "requests per second per IP"
3896 + },
3897 + "acqGatewayDivisor": {
3898 + "value": "nine",
3899 + "source": "src/acquisition/bulk_downloader.py",
3900 + "formula": "default aggregate rate shared behind one IP"
3901 + },
3902 + "acqNewDocs": {
3903 + "value": "about 400{,}000",
3904 + "source": "data/documented_inputs.json:acq_new_docs",
3905 + "formula": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible"
3906 + },
3907 + "acqHours": {
3908 + "value": "seven",
3909 + "source": "data/documented_inputs.json:acq_hours",
3910 + "formula": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible"
3911 + },
3912 + "acqReqPerSec": {
3913 + "value": "17",
3914 + "source": "data/documented_inputs.json:acq_req_per_sec",
3915 + "formula": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible"
3916 + },
3917 + "acqNodes": {
3918 + "value": "ten",
3919 + "source": "data/documented_inputs.json:acq_nodes",
3920 + "formula": "docs/research_log.md 2026-10-27 (10 MacLustr nodes + 1 external gateway)"
3921 + },
3922 + "acqNodeRate": {
3923 + "value": "0.9",
3924 + "source": "data/documented_inputs.json:acq_node_rate",
3925 + "formula": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible (requests per second per node)"
3926 + },
3927 + "acqGatewayRate": {
3928 + "value": "one",
3929 + "source": "data/documented_inputs.json:acq_gateway_rate",
3930 + "formula": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible (requests per second per shard on the gateway)"
3931 + },
3932 + "parseFilingsPerSec": {
3933 + "value": "100",
3934 + "source": "data/documented_inputs.json:parse_filings_per_sec",
3935 + "formula": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible"
3936 + },
3937 + "parseMinutesRange": {
3938 + "value": "five to thirteen",
3939 + "source": "data/documented_inputs.json:parse_minutes_range",
3940 + "formula": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible"
3941 + },
3942 + "embedMinutesRange": {
3943 + "value": "15--40",
3944 + "source": "data/documented_inputs.json:embed_minutes_range",
3945 + "formula": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible"
3946 + },
3947 + "mergeMinutes": {
3948 + "value": "seven",
3949 + "source": "data/documented_inputs.json:merge_minutes",
3950 + "formula": "author-reported run fact (docs/research_log.md, 2026-10-27/28); the orchestrator and acquisition logs are not archived with the paper; not reconstructible"
3951 + },
3952 + "totalCostUsd": {
3953 + "value": "775",
3954 + "source": "data/documented_inputs.json:total_cost_usd",
3955 + "formula": "author-reported total of the October 2026 extraction (docs/research_log.md); the API invoice is not archived"
3956 + },
3957 + "stabilitySections": {
3958 + "value": "500",
3959 + "source": "data/documented_inputs.json:stability_sections",
3960 + "formula": "X1 protocol of peer_reviews/FIRC-0001/consolidated_review.md §6 item 11 (500 sections x 3 re-submissions); not executed (AR-LLM-1 not granted)"
3961 + },
3962 + "stabilityCalls": {
3963 + "value": "about 2{,}500",
3964 + "source": "data/documented_inputs.json:stability_calls",
3965 + "formula": "consolidated_review.md §6 item 11 (cost estimate of the X1/X2 protocol); not executed"
3966 + },
3967 + "embeddingDim": {
3968 + "value": "384",
3969 + "source": "data/documented_inputs.json:embedding_dim",
3970 + "formula": "all-MiniLM-L6-v2 embedding dimension (scripts/build_embeddings.py default model)"
3971 + },
3972 + "factorAnchors": {
3973 + "value": "8",
3974 + "source": "data/documented_inputs.json:factor_anchors",
3975 + "formula": "src/factors/anchors.py registry (thematic anchors), as described in docs/research_log.md"
3976 + },
3977 + "tenKsectionsMax": {
3978 + "value": "fourteen",
3979 + "source": "data/documented_inputs.json:tenk_sections_max",
3980 + "formula": "src/parsing/section_extractor.py FORM_10K_SECTIONS (Items 1 to 9B)"
3981 + },
3982 + "tenQsectionsN": {
3983 + "value": "seven",
3984 + "source": "data/documented_inputs.json:tenq_sections_n",
3985 + "formula": "src/parsing/section_extractor.py FORM_10Q_SECTIONS"
961 3986 },
962 3987 "projects": {
963 3988 "value": "121{,}099",
@@ -979,6 +4004,11 @@
979 4004 "source": "stats.json:issuers_with_filings",
980 4005 "formula": "count(distinct cik) in filings"
981 4006 },
4007 + "issuersWithoutFilings": {
4008 + "value": "65",
4009 + "source": "stats.json:issuers_without_filings",
4010 + "formula": "count"
4011 + },
982 4012 "sectionsTotal": {
983 4013 "value": "1{,}342{,}283",
984 4014 "source": "stats.json:sections_total",
@@ -1009,6 +4039,11 @@
1009 4039 "source": "data/projects_per_issuer.csv",
1010 4040 "formula": "q[2]"
1011 4041 },
4042 + "mentionsPerProject": {
4043 + "value": "2.54",
4044 + "source": "stats.json",
4045 + "formula": "mentions/projects"
4046 + },
1012 4047 "extractedAtFirst": {
1013 4048 "value": "2026-10-27 13:12:32",
1014 4049 "source": "stats.json:extracted_at_range[0]",
@@ -1019,19 +4054,99 @@
1019 4054 "source": "stats.json:extracted_at_range[1]",
1020 4055 "formula": "max(extracted_at)"
1021 4056 },
4057 + "tenKmdnaMedianWords": {
4058 + "value": "9{,}905",
4059 + "source": "stats.json:ledger_10k_mdna_median_words",
4060 + "formula": "export_stats.py"
4061 + },
4062 + "annualPanelFirms": {
4063 + "value": "2{,}499",
4064 + "source": "stats.json:annual_panel_firms",
4065 + "formula": "export_stats.py"
4066 + },
4067 + "spFiveHundredCiks": {
4068 + "value": "500",
4069 + "source": "stats.json:sp500_ciks",
4070 + "formula": "export_stats.py"
4071 + },
4072 + "runSpFiveZeroZeroRunLog": {
4073 + "value": "project-db/logs/extract.log",
4074 + "source": "stats.json:spid_runs.sp500_run.log",
4075 + "formula": "export_stats.py"
4076 + },
4077 + "runSpFiveZeroZeroRunWorkers": {
4078 + "value": "16",
4079 + "source": "stats.json:spid_runs.sp500_run.workers",
4080 + "formula": "export_stats.py"
4081 + },
4082 + "runSpFiveZeroZeroRunBatch": {
4083 + "value": "15",
4084 + "source": "stats.json:spid_runs.sp500_run.batch",
4085 + "formula": "export_stats.py"
4086 + },
4087 + "runSpFiveZeroZeroRunCiks": {
4088 + "value": "500",
4089 + "source": "stats.json:spid_runs.sp500_run.ciks",
4090 + "formula": "export_stats.py"
4091 + },
4092 + "runSpFiveZeroZeroRunSectionsLogged": {
4093 + "value": "153894",
4094 + "source": "stats.json:spid_runs.sp500_run.sections_logged",
4095 + "formula": "export_stats.py"
4096 + },
4097 + "runSpFiveZeroZeroRunLedgerRowsBackfilled": {
4098 + "value": "154964",
4099 + "source": "stats.json:spid_runs.sp500_run.ledger_rows_backfilled",
4100 + "formula": "export_stats.py"
4101 + },
4102 + "runSpFiveZeroZeroRunMentionsBackfilled": {
4103 + "value": "39930",
4104 + "source": "stats.json:spid_runs.sp500_run.mentions_backfilled",
4105 + "formula": "export_stats.py"
4106 + },
4107 + "runSpFiveZeroZeroRunLlmCallFailed": {
4108 + "value": "3",
4109 + "source": "stats.json:spid_runs.sp500_run.llm_call_failed",
4110 + "formula": "export_stats.py"
4111 + },
4112 + "runRussellRunLog": {
4113 + "value": "data/logs/spid\\_extract.log",
4114 + "source": "stats.json:spid_runs.russell_run.log",
4115 + "formula": "export_stats.py"
4116 + },
4117 + "runRussellRunWorkers": {
4118 + "value": "24",
4119 + "source": "stats.json:spid_runs.russell_run.workers",
4120 + "formula": "export_stats.py"
4121 + },
4122 + "runRussellRunLedgerRows": {
4123 + "value": "968134",
4124 + "source": "stats.json:spid_runs.russell_run.ledger_rows",
4125 + "formula": "export_stats.py"
4126 + },
4127 + "runRussellRunExtractedAtFirst": {
4128 + "value": "2026-10-27 13:12:32.140400",
4129 + "source": "stats.json:spid_runs.russell_run.extracted_at_first",
4130 + "formula": "export_stats.py"
4131 + },
4132 + "runRussellRunExtractedAtLast": {
4133 + "value": "2026-10-28 11:15:49.150818",
4134 + "source": "stats.json:spid_runs.russell_run.extracted_at_last",
4135 + "formula": "export_stats.py"
4136 + },
4137 + "runRussellRunLlmCallFailed": {
4138 + "value": "94609",
4139 + "source": "stats.json:spid_runs.russell_run.llm_call_failed",
4140 + "formula": "export_stats.py"
4141 + },
4142 + "runRussellRunSectionFailed": {
4143 + "value": "0",
4144 + "source": "stats.json:spid_runs.russell_run.section_failed",
4145 + "formula": "export_stats.py"
4146 + },
1022 4147 "brief": {
1023 4148 "value": "the research-design brief, i.e. the specification of required tables, keys and validation gates against which \\texttt{docs/implementation\\_audit.md} audits the build",
1024 4149 "source": "data/documented_inputs.json:brief_definition",
1025 4150 "formula": "documented input (author to confirm)"
1026 − },
1027 − "newProjectsPerIssuerFirstYear": {
1028 − "value": "6.4",
1029 − "source": "data/projects_by_first_seen_year.csv, mentions_by_year.csv",
1030 − "formula": "first seen / issuers with mentions"
1031 − },
1032 − "newProjectsPerIssuerLastFullYear": {
1033 − "value": "3.5",
1034 − "source": "data/projects_by_first_seen_year.csv, mentions_by_year.csv",
1035 − "formula": "first seen / issuers with mentions"
1036 4151 }
1037 4152 }
\ No newline at end of file
1038 4153
Menu

Theme