Research Loop Audit

Run ID: gw-forecast-production-001-loop02

Status: task_complete

Original goal

# North Star: Investment-Grade GW Forecast vs Actual

## Mission

Build **production-grade research** we can trust for **investment decisions** on whether **more gigawatts (GW) of data-center / AI infrastructure capacity are coming online** — past, present, and future.

For each of **17 target companies**, answer:

1. **What did they say?** — GW forecasts, pipeline, and guidance each quarter  
2. **How did forecasts change?** — vintage panel: Oracle said X GW in Q1, revised to Y in Q3  
3. **What actually happened?** — delivered / operating / under-construction GW vs the original forecast  
4. **Can we see it on a chart?** — one **line graph per company** + one **portfolio line graph**

Example: *"Oracle said they'll have X data centers / Y GW by 2027. Each quarter we capture that statement. We track how the forecast moved quarter-to-quarter and compare the first forecast to what ultimately landed."*

## Target Companies (17)

ORCL, MSFT, AMZN, GOOGL, META, CoreWeave (CRWV), DLR, EQIX, IRM, APLD, CORZ, IREN, WULF, CIFR, HUT, NBIS/Nebius, NVDA

*(Vertiv/Eaton dropped from v1 — infrastructure suppliers, not capacity owners.)*

## Core Metrics (GW-first)

- operating / live GW (actual)
- GW under construction (actual snapshot)
- GW pipeline / future capacity (forecast)
- GW added this quarter (actual)
- forecast vintage: `as_of_quarter` → `target_period` → `forecast_gw`
- capex actuals & guidance (supporting evidence)
- revenue conversion per MW/GW where disclosed

## Canonical Output Layout

All production artifacts live under `research_loop/production/`:

```
production/
  {TICKER}/
    source_manifest.csv
    forecast_vintage.csv      # how forecasts changed each quarter
    capacity_timeseries.csv   # actual vs latest vs original forecast by period
    company_gw_chart.html     # line chart for this company
    extractor.py
    validator.py
  portfolio_gw_timeseries.csv
  portfolio_gw_chart.html
  goal_progress.json          # machine-readable completion status
```

## Done When (`north_star.json`)

- Every company has ≥8 quarters in `forecast_vintage.csv` and `capacity_timeseries.csv`
- Every company has provenance-complete rows (https source URLs, snippets, validation PASS)
- Every company has `company_gw_chart.html`
- Portfolio chart aggregates all companies
- `goal_completion.py` reports ≥85% investment-confidence score

## Source Preference

Primary: SEC 10-Q/10-K/8-K, earnings supplements, IR pages, investor decks, transcripts  
Secondary: industry press (discovery only — not row-level evidence)

## Supervisor Mandate

The auto-continue supervisor runs **until the north star is achieved**, not for a fixed loop count. Each child loop picks **one company or one repair task** that moves the portfolio closest to done.

Current task

(none)

Completed tasks

Task history

Complete ORCL production gates: copy loop01 machine-gate PASS artifacts (source_manifest.csv, extractor.py, forecast_vintage.csv) into production/ORCL/, then derive capacity_timeseries.csv from the vintage panel (≥8 fiscal quarters: FY2024-FQ4 through FY2026-FQ3), build company_gw_chart.html plotting capex-actual vs latest/original FY2026 capex-guidance vintages (USD billions proxy — normalized_gw blank per Oracle non-disclosure), and add validator.py enforcing schema, ≥8 quarter rows, https provenance, and snippet integrity. Do not use EQIX/DLR fallback rows.

goal_progress.json sets next_priority_ticker=ORCL (0/17 complete, 74.7% confidence). Loop01 passed machine gate with real ORCL manifest+extractor+vintage (16 rows, 8 as-of periods) but nothing is promoted to production/ORCL/; capacity_timeseries.csv is falsely credited via eqix_rows.csv fallback. No blocked_reason or machine-gate failure in loop02. Finishing ORCL's remaining pipeline steps (timeseries → chart → validator) is the highest-leverage path to the first complete company and unlocks the portfolio-aggregation gate.

Status: passed

Review cycles: 2

Acceptance criteria

Expected artifacts

Artifacts

Agent calls & decisions

TimeIterRoleTaskVerdict DecisionsBlockersArtifacts
2026-06-07T15:48:48.534171+00:000systemstart
[
  "run started"
]
[]
2026-06-07T15:50:51.110099+00:001plannerComplete ORCL production gates: copy loop01 machine-gate PASS artifacts (source_manifest.csv, extractor.py, forecast_vintage.csv) into production/ORCL/, then derive capacity_timeseries.csv from the vintage panel (≥8 fiscal quarters: FY2024-FQ4 through FY2026-FQ3), build company_gw_chart.html plotting capex-actual vs latest/original FY2026 capex-guidance vintages (USD billions proxy — normalized_gw blank per Oracle non-disclosure), and add validator.py enforcing schema, ≥8 quarter rows, https provenance, and snippet integrity. Do not use EQIX/DLR fallback rows.
[
  "goal_progress.json sets next_priority_ticker=ORCL (0/17 complete, 74.7% confidence). Loop01 passed machine gate with real ORCL manifest+extractor+vintage (16 rows, 8 as-of periods) but nothing is promoted to production/ORCL/; capacity_timeseries.csv is falsely credited via eqix_rows.csv fallback. No blocked_reason or machine-gate failure in loop02. Finishing ORCL's remaining pipeline steps (timeseries \u2192 chart \u2192 validator) is the highest-leverage path to the first complete company and unlocks the portfolio-aggregation gate."
]
[]
2026-06-07T15:54:34.846288+00:001workerComplete ORCL production gates: copy loop01 machine-gate PASS artifacts (source_manifest.csv, extractor.py, forecast_vintage.csv) into production/ORCL/, then derive capacity_timeseries.csv from the vintage panel (≥8 fiscal quarters: FY2024-FQ4 through FY2026-FQ3), build company_gw_chart.html plotting capex-actual vs latest/original FY2026 capex-guidance vintages (USD billions proxy — normalized_gw blank per Oracle non-disclosure), and add validator.py enforcing schema, ≥8 quarter rows, https provenance, and snippet integrity. Do not use EQIX/DLR fallback rows.
[
  "## Decisions",
  "- **Promoted loop01 PASS artifacts unchanged** for `source_manifest.csv`, `forecast_vintage.csv`, and `extractor.py` (19 manifest sources, 16 vintage rows, 8 `as_of_period` vintages, live SEC/IR fetch + call-snippet guidance chain).",
  "- **USD capex proxy, not GW:** Oracle does not disclose MW/GW; all `normalized_gw` / GW timeseries columns are blank. `capacity_timeseries.csv` uses `capex_actual_usd_b` and `capex_guidance_*_usd_b` as investment proxies.",
  "- **Timeseries rollup logic:** Quarterly `capex_actual` rows map directly; FY2025-FQ4 Q4 derived from annual minus Q1\u2013Q3; FY2026 quarters derived from YTD (`capex_actual_ytd`) deltas. Latest FY2026 guidance rolls forward by `as_of_period` (blank before FY2025-FQ4); original fixed at **25** (first vintage, FY2025-FQ4 \u201c>$25B\u201d).",
  "- **Chart:** Self-contained SVG/HTML with three series (capex actual, latest guidance vintage, original guidance) plus visible GW-proxy banner.",
  "- **Validator:** Enforces schema, \u226516 vintage / \u22658 timeseries rows, https provenance, `verified_primary` snippet sampling, guidance revision spot-checks, and live extractor re-run (16 rows). No EQIX/DLR fallbacks.",
  "## Evidence",
  "**PRIMARY**"
]
[
  "Artifact artifacts/extractor.py is too short (339 chars)"
]
capacity_timeseries.csv, company_gw_chart.html, extractor.py, forecast_vintage.csv, production/ORCL/build_timeseries.py, production/ORCL/capacity_timeseries.csv, production/ORCL/company_gw_chart.html, production/ORCL/extractor.py, production/ORCL/forecast_vintage.csv, production/ORCL/source_manifest.csv, production/ORCL/validator.py, source_manifest.csv, validator.py
2026-06-07T15:57:15.195695+00:001fixerComplete ORCL production gates: copy loop01 machine-gate PASS artifacts (source_manifest.csv, extractor.py, forecast_vintage.csv) into production/ORCL/, then derive capacity_timeseries.csv from the vintage panel (≥8 fiscal quarters: FY2024-FQ4 through FY2026-FQ3), build company_gw_chart.html plotting capex-actual vs latest/original FY2026 capex-guidance vintages (USD billions proxy — normalized_gw blank per Oracle non-disclosure), and add validator.py enforcing schema, ≥8 quarter rows, https provenance, and snippet integrity. Do not use EQIX/DLR fallback rows.
[
  "mechanical fix pass 1"
]
[]
capacity_timeseries.csv, company_gw_chart.html, extractor.py, forecast_vintage.csv, production/ORCL/build_timeseries.py, production/ORCL/capacity_timeseries.csv, production/ORCL/company_gw_chart.html, production/ORCL/extractor.py, production/ORCL/forecast_vintage.csv, production/ORCL/source_manifest.csv, production/ORCL/validator.py, source_manifest.csv, validator.py
2026-06-07T15:59:21.689714+00:001reviewerComplete ORCL production gates: copy loop01 machine-gate PASS artifacts (source_manifest.csv, extractor.py, forecast_vintage.csv) into production/ORCL/, then derive capacity_timeseries.csv from the vintage panel (≥8 fiscal quarters: FY2024-FQ4 through FY2026-FQ3), build company_gw_chart.html plotting capex-actual vs latest/original FY2026 capex-guidance vintages (USD billions proxy — normalized_gw blank per Oracle non-disclosure), and add validator.py enforcing schema, ≥8 quarter rows, https provenance, and snippet integrity. Do not use EQIX/DLR fallback rows.PASS
[
  "review cycle 1"
]
[]
capacity_timeseries.csv, company_gw_chart.html, extractor.py, forecast_vintage.csv, production/ORCL/build_timeseries.py, production/ORCL/capacity_timeseries.csv, production/ORCL/company_gw_chart.html, production/ORCL/extractor.py, production/ORCL/forecast_vintage.csv, production/ORCL/source_manifest.csv, production/ORCL/validator.py, source_manifest.csv, validator.py
2026-06-07T15:59:21.710421+00:001machine_gateComplete ORCL production gates: copy loop01 machine-gate PASS artifacts (source_manifest.csv, extractor.py, forecast_vintage.csv) into production/ORCL/, then derive capacity_timeseries.csv from the vintage panel (≥8 fiscal quarters: FY2024-FQ4 through FY2026-FQ3), build company_gw_chart.html plotting capex-actual vs latest/original FY2026 capex-guidance vintages (USD billions proxy — normalized_gw blank per Oracle non-disclosure), and add validator.py enforcing schema, ≥8 quarter rows, https provenance, and snippet integrity. Do not use EQIX/DLR fallback rows.CHANGES_REQUIRED
[
  "machine validation failed after reviewer PASS"
]
[
  "source manifest missing column: metrics_supported",
  "source manifest missing column: caveat"
]
capacity_timeseries.csv, company_gw_chart.html, extractor.py, forecast_vintage.csv, production/ORCL/build_timeseries.py, production/ORCL/capacity_timeseries.csv, production/ORCL/company_gw_chart.html, production/ORCL/extractor.py, production/ORCL/forecast_vintage.csv, production/ORCL/source_manifest.csv, production/ORCL/validator.py, source_manifest.csv, validator.py
2026-06-07T16:02:42.231430+00:001fixerComplete ORCL production gates: copy loop01 machine-gate PASS artifacts (source_manifest.csv, extractor.py, forecast_vintage.csv) into production/ORCL/, then derive capacity_timeseries.csv from the vintage panel (≥8 fiscal quarters: FY2024-FQ4 through FY2026-FQ3), build company_gw_chart.html plotting capex-actual vs latest/original FY2026 capex-guidance vintages (USD billions proxy — normalized_gw blank per Oracle non-disclosure), and add validator.py enforcing schema, ≥8 quarter rows, https provenance, and snippet integrity. Do not use EQIX/DLR fallback rows.
[
  "machine-gate fix cycle 1"
]
[]
capacity_timeseries.csv, company_gw_chart.html, extractor.py, forecast_vintage.csv, production/ORCL/build_timeseries.py, production/ORCL/capacity_timeseries.csv, production/ORCL/company_gw_chart.html, production/ORCL/extractor.py, production/ORCL/forecast_vintage.csv, production/ORCL/source_manifest.csv, production/ORCL/validator.py, source_manifest.csv, validator.py
2026-06-07T16:04:45.353999+00:001reviewerComplete ORCL production gates: copy loop01 machine-gate PASS artifacts (source_manifest.csv, extractor.py, forecast_vintage.csv) into production/ORCL/, then derive capacity_timeseries.csv from the vintage panel (≥8 fiscal quarters: FY2024-FQ4 through FY2026-FQ3), build company_gw_chart.html plotting capex-actual vs latest/original FY2026 capex-guidance vintages (USD billions proxy — normalized_gw blank per Oracle non-disclosure), and add validator.py enforcing schema, ≥8 quarter rows, https provenance, and snippet integrity. Do not use EQIX/DLR fallback rows.PASS
[
  "review cycle 2"
]
[]
capacity_timeseries.csv, company_gw_chart.html, extractor.py, forecast_vintage.csv, production/ORCL/build_timeseries.py, production/ORCL/capacity_timeseries.csv, production/ORCL/company_gw_chart.html, production/ORCL/extractor.py, production/ORCL/forecast_vintage.csv, production/ORCL/source_manifest.csv, production/ORCL/validator.py, source_manifest.csv, validator.py
2026-06-07T16:04:45.382843+00:001machine_gateComplete ORCL production gates: copy loop01 machine-gate PASS artifacts (source_manifest.csv, extractor.py, forecast_vintage.csv) into production/ORCL/, then derive capacity_timeseries.csv from the vintage panel (≥8 fiscal quarters: FY2024-FQ4 through FY2026-FQ3), build company_gw_chart.html plotting capex-actual vs latest/original FY2026 capex-guidance vintages (USD billions proxy — normalized_gw blank per Oracle non-disclosure), and add validator.py enforcing schema, ≥8 quarter rows, https provenance, and snippet integrity. Do not use EQIX/DLR fallback rows.PASS
[
  "expected artifact validators and production gates passed"
]
[]
capacity_timeseries.csv, company_gw_chart.html, extractor.py, forecast_vintage.csv, production/ORCL/build_timeseries.py, production/ORCL/capacity_timeseries.csv, production/ORCL/company_gw_chart.html, production/ORCL/extractor.py, production/ORCL/forecast_vintage.csv, production/ORCL/source_manifest.csv, production/ORCL/validator.py, source_manifest.csv, validator.py

Generated 2026-06-07T16:04:45.483274+00:00