// Builds the FactHub dataset release for the Washington hydropower fact check. // Usage: node build_payload.js // Reads results/ (from build.js), archive-results.json (archive_source outputs), and the raw files (for the // source manifest). Writes release/: the public artifact files, dataset-parts.json (sources, tables, events, // analyses and replications, referenced from the draft with $artifact pointers), and dataset-request.json (the // create_dataset_draft content). const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); const [resDir, rawDir, rel] = process.argv.slice(2); if (!resDir || !rawDir || !rel) { console.error('usage: node build_payload.js '); process.exit(1); } fs.mkdirSync(rel, { recursive: true }); const KEY = 'wa-electricity-generation-by-source'; const RETRIEVED = '2026-10-09'; const EXECUTED = '2026-10-09T17:00:00+00:00'; const sha = (buf) => 'sha256:' + crypto.createHash('sha256').update(buf).digest('hex'); const R = JSON.parse(fs.readFileSync(path.join(resDir, 'results.json'), 'utf8')); const ARCH = JSON.parse(fs.readFileSync(path.join(__dirname, 'archive-results.json'), 'utf8')); const fmt = (n) => Math.round(n).toLocaleString('en-US'); const twh = (mwh) => (mwh / 1e6).toFixed(1); // ---------- Copy tables and scripts ---------- const TABLE_FILES = ['wa-generation-by-source.csv', 'wa-hydro-annual.csv', 'state-hydro-rank-2025.csv', 'wa-supply-disposition.csv', 'largest-plants-capacity-2025.csv', 'largest-plants-generation-2025.csv', 'wa-utility-fuel-mix-2024.csv']; for (const f of TABLE_FILES) fs.copyFileSync(path.join(resDir, f), path.join(rel, f)); for (const f of ['build.js', 'build_payload.js']) fs.copyFileSync(path.join(__dirname, f), path.join(rel, f)); // ---------- Sources ---------- const S = (id, name, url, role, licenseName, redistribution) => { const a = ARCH[url] || {}; const s = { id, name, url, retrievedAt: RETRIEVED, role, licenseName, redistribution }; if (a.archiveUrl) s.archiveUrl = a.archiveUrl; if (a.archivedAt) s.archivedAt = a.archivedAt; if (a.contentDigest) s.contentDigest = a.contentDigest; return s; }; const FED = 'U.S. federal government work (public domain)'; const LINK = 'Linked as a public record; the source file is not redistributed. Its SHA-256 is recorded here and in source-manifest.json.'; const sources = [ S('eia-state-generation', 'U.S. Energy Information Administration, State Historical Tables: Net Generation by State by Type of Producer by Energy Source, 1990-2025 (Final, released September 2026)', 'https://www.eia.gov/electricity/data/state/annual_generation_state.xlsx', 'Primary source for annual Washington net generation by energy source and for the state hydro ranking (EIA-923 and predecessor forms).', FED, LINK), S('eia-sep-washington', 'U.S. Energy Information Administration, State Electricity Profile tables for Washington (data year 2024)', 'https://www.eia.gov/electricity/state/xls/SEP%20Tables%20for%20WA.xlsx', 'Table 10 (supply and disposition: retail sales, international trade, net interstate trade) and cross-check of Table 5 generation totals.', FED, LINK), S('eia-860-2025', 'U.S. Energy Information Administration, Form EIA-860 Annual Electric Generator Report, 2025 final data (eia8602025.zip, file 3_1_Generator_Y2025.xlsx, sheet Operable)', 'https://www.eia.gov/electricity/data/eia860/xls/eia8602025.zip', 'Generator-level nameplate, summer and winter capacity used to rank U.S. plants by capacity.', FED, LINK), S('eia-923-2025', 'U.S. Energy Information Administration, Form EIA-923 Power Plant Operations Report, 2025 final data (f923_2025.zip, Schedules 2-5, Page 1 Generation and Fuel Data)', 'https://www.eia.gov/electricity/data/eia923/xls/f923_2025.zip', 'Plant-level 2025 net generation used to rank U.S. plants by annual output.', FED, LINK), S('wa-commerce-fuel-mix', 'Washington State Department of Commerce, Fuel Mix Disclosure', 'https://www.commerce.wa.gov/energy-policy/electricity-policy/fuel-mix-disclosure/', 'Consumption-side check: the aggregate 2024 fuel mix of electricity Washington utilities reported delivering to Washington customers.', 'Washington State public record', LINK), S('wa-commerce-fuel-mix-chart', 'Washington State Department of Commerce, chart "Washington electric utilities aggregate 2024 fuel mix" (image on the Fuel Mix Disclosure page)', 'https://www.commerce.wa.gov/wp-content/uploads/2026/02/2024_fuel-mix-chart-1536x890.png', 'The labeled percentages transcribed into the wa-utility-fuel-mix-2024 table.', 'Washington State public record', LINK), S('usbr-grand-coulee', 'U.S. Bureau of Reclamation, Grand Coulee Dam: About', 'https://www.usbr.gov/pn/grandcoulee/about/index.html', 'Operator statement of Grand Coulee generating capacity (6,809 MW) and typical output (up to 21 billion kWh), used as a replication check.', FED, LINK), S('eia-tie-2024-drought', 'U.S. Energy Information Administration, Today in Energy, "Drought conditions reduce hydropower generation, particularly in the Pacific Northwest" (November 7, 2024)', 'https://www.eia.gov/todayinenergy/detail.php?id=63664', 'Context on 2023-2024 Pacific Northwest hydro conditions; states Grand Coulee net summer capacity as 6.7 GW.', FED, LINK), S('ecology-drought-2024', 'Washington State Department of Ecology, news release, April 16, 2024 drought declaration', 'https://ecology.wa.gov/about-us/who-we-are/news/2024/april-16-drought-declaration', 'Dates the 2024 statewide drought emergency and the 2023 emergency covering 12 watersheds.', 'Washington State public record', LINK), ]; const SRC_IDS = new Set(sources.map((s) => s.id)); // ---------- Source manifest ---------- const RAW = [ ['annual_generation_state.xlsx', 'https://www.eia.gov/electricity/data/state/annual_generation_state.xlsx'], ['sep_wa.xlsx', 'https://www.eia.gov/electricity/state/xls/SEP%20Tables%20for%20WA.xlsx'], ['eia8602025.zip', 'https://www.eia.gov/electricity/data/eia860/xls/eia8602025.zip'], ['eia860/3_1_Generator_Y2025.xlsx', 'extracted from eia8602025.zip'], ['f923_2025.zip', 'https://www.eia.gov/electricity/data/eia923/xls/f923_2025.zip'], ['eia923/EIA923_Schedules_2_3_4_5_M_12_2025_Final.xlsx', 'extracted from f923_2025.zip'], ['commerce/2024_fuel-mix-chart.png', 'https://www.commerce.wa.gov/wp-content/uploads/2026/02/2024_fuel-mix-chart-1536x890.png'], ]; const manifest = { retrievedAt: RETRIEVED, note: 'Files downloaded with curl on the retrieval date. Digests are SHA-256 of the bytes received. FactHub archive_source independently fetched the URLs and returned the same digests where recorded in the dataset sources.', files: RAW.map(([file, url]) => { const b = fs.readFileSync(path.join(rawDir, file)); return { file, url, byteLength: b.length, contentDigest: sha(b) }; }), }; fs.writeFileSync(path.join(rel, 'source-manifest.json'), JSON.stringify(manifest, null, 2) + '\n'); // ---------- Tables ---------- const F = (name, type, units, description, valueType, sourceIds, extra = {}) => ({ name, type, units, description, nullable: false, valueType, sourceIds, ...extra }); const MWH = 'megawatthours (MWh)'; const tables = [ { id: 'wa-generation-by-source', artifactId: 'wa-generation-by-source', title: 'Washington net generation by energy source, 2001-2025', unitOfObservation: 'One year and one EIA energy-source category for Washington, all producer types (Total Electric Power Industry).', description: 'Annual in-state net generation by energy source as published by EIA, with each source\'s share of the state total.', fields: [ F('year', 'integer', 'calendar year', 'Data year.', 'observed', ['eia-state-generation']), F('source', 'string', null, 'Short code for the EIA energy source (hydro, natural_gas, nuclear, wind, coal, solar, wood, other_biomass, other_gases, petroleum, pumped_storage, other).', 'derived', ['eia-state-generation'], { derivation: 'One-to-one recode of eia_energy_source.' }), F('eia_energy_source', 'string', null, 'EIA ENERGY SOURCE label exactly as published.', 'observed', ['eia-state-generation']), F('net_generation_mwh', 'integer', MWH, 'Net generation. Pumped storage can be negative because pumping consumes more than it generates. A source absent from EIA\'s file for a year has no row (not zero).', 'observed', ['eia-state-generation'], { derivation: 'Rounded to whole MWh; EIA reports a few years with fractional MWh.' }), F('share_of_total_pct', 'number', 'percent', 'net_generation_mwh divided by EIA\'s Washington Total for the year.', 'derived', ['eia-state-generation'], { derivation: '100 * net_generation_mwh / Total, rounded to 0.01.' }), ] }, { id: 'wa-hydro-annual', artifactId: 'wa-hydro-annual', title: 'Washington conventional hydro share and national rank, 2001-2025', unitOfObservation: 'One year for Washington.', description: 'Hydro share of in-state net generation and Washington\'s rank among the 50 states and DC for conventional hydroelectric generation.', fields: [ F('year', 'integer', 'calendar year', 'Data year.', 'observed', ['eia-state-generation']), F('total_net_generation_mwh', 'integer', MWH, 'Washington total net generation, all sources and producer types.', 'observed', ['eia-state-generation']), F('hydro_net_generation_mwh', 'integer', MWH, 'Conventional hydroelectric net generation (excludes pumped storage).', 'observed', ['eia-state-generation']), F('hydro_share_pct', 'number', 'percent', 'Hydro share of in-state net generation.', 'derived', ['eia-state-generation'], { derivation: '100 * hydro / total, rounded to 0.1.' }), F('non_hydro_net_generation_mwh', 'integer', MWH, 'Total minus conventional hydro.', 'derived', ['eia-state-generation'], { derivation: 'total - hydro.' }), F('wa_hydro_rank_among_states', 'integer', 'rank (1 = most)', 'Rank of Washington\'s conventional hydro generation among the 50 states and DC.', 'derived', ['eia-state-generation'], { derivation: 'States sorted by Hydroelectric Conventional, Total Electric Power Industry; US-TOTAL rows excluded.' }), F('us_hydro_net_generation_mwh', 'integer', MWH, 'Sum of conventional hydro across the 50 states and DC.', 'derived', ['eia-state-generation'], { derivation: 'Sum over state rows.' }), F('wa_share_of_us_hydro_pct', 'number', 'percent', 'Washington share of U.S. conventional hydro generation.', 'derived', ['eia-state-generation'], { derivation: '100 * WA hydro / U.S. hydro, rounded to 0.1.' }), F('second_ranked_state', 'string', 'USPS state code', 'State with the second-largest conventional hydro generation that year.', 'derived', ['eia-state-generation']), F('second_ranked_state_hydro_mwh', 'integer', MWH, 'That state\'s conventional hydro generation.', 'observed', ['eia-state-generation']), ] }, { id: 'state-hydro-rank-2025', artifactId: 'state-hydro-rank-2025', title: 'Top 10 states by conventional hydro generation, 2025', unitOfObservation: 'One state in 2025.', description: 'The ten states with the most conventional hydroelectric net generation in 2025.', fields: [ F('year', 'integer', 'calendar year', 'Data year (2025).', 'observed', ['eia-state-generation']), F('rank', 'integer', 'rank (1 = most)', 'Rank among the 50 states and DC.', 'derived', ['eia-state-generation']), F('state', 'string', 'USPS state code', 'State.', 'observed', ['eia-state-generation']), F('hydro_net_generation_mwh', 'integer', MWH, 'Conventional hydro net generation.', 'observed', ['eia-state-generation']), F('share_of_us_hydro_pct', 'number', 'percent', 'Share of U.S. conventional hydro.', 'derived', ['eia-state-generation'], { derivation: '100 * state / sum of states, rounded to 0.1.' }), ] }, { id: 'wa-supply-disposition', artifactId: 'wa-supply-disposition', title: 'Washington electricity supply and disposition, 2001-2024', unitOfObservation: 'One year for Washington.', description: 'EIA State Electricity Profile Table 10 rows: generation, retail sales, direct use, losses, international trade and EIA\'s computed net interstate trade, with two derived ratios.', fields: [ F('year', 'integer', 'calendar year', 'Data year.', 'observed', ['eia-sep-washington']), F('total_net_generation_mwh', 'integer', MWH, 'Table 10 Total net generation.', 'observed', ['eia-sep-washington']), F('retail_sales_mwh', 'integer', MWH, 'Table 10 Total electric industry sales to ultimate customers in Washington.', 'observed', ['eia-sep-washington']), F('direct_use_mwh', 'integer', MWH, 'Table 10 Direct use.', 'observed', ['eia-sep-washington']), F('estimated_losses_mwh', 'integer', MWH, 'Table 10 Estimated losses (allocated by EIA from utility-level reports).', 'estimated', ['eia-sep-washington']), F('international_imports_mwh', 'integer', MWH, 'Table 10 Total international imports (Canada).', 'observed', ['eia-sep-washington']), F('international_exports_mwh', 'integer', MWH, 'Table 10 Total international exports.', 'observed', ['eia-sep-washington']), F('net_interstate_trade_mwh', 'integer', MWH, 'Table 10 Net interstate trade; positive = net exporter to other states, negative = net importer. EIA computes it as a residual.', 'estimated', ['eia-sep-washington']), F('generation_to_retail_sales_ratio', 'number', 'ratio', 'Total net generation divided by retail sales.', 'derived', ['eia-sep-washington'], { derivation: 'Rounded to 0.01.' }), F('hydro_to_retail_sales_pct', 'number', 'percent', 'In-state conventional hydro generation as a percent of in-state retail sales. A volume ratio, not the share of hydro in what customers bought.', 'derived', ['eia-sep-washington', 'eia-state-generation'], { derivation: '100 * hydro (wa-hydro-annual) / retail_sales_mwh, rounded to 0.1.' }), ] }, { id: 'largest-plants-capacity-2025', artifactId: 'largest-plants-capacity-2025', title: 'Ten largest U.S. power plants by nameplate capacity, end of 2025', unitOfObservation: 'One EIA plant (plant code).', description: 'Plant capacity summed over all operable generators in EIA-860 2025, ranked by nameplate capacity, with rank by net summer capacity.', fields: [ F('rank_by_nameplate', 'integer', 'rank (1 = largest)', 'Rank among all U.S. plants by summed nameplate capacity.', 'derived', ['eia-860-2025']), F('rank_by_summer_capacity', 'integer', 'rank (1 = largest)', 'Rank among all U.S. plants by summed net summer capacity.', 'derived', ['eia-860-2025']), F('plant_code', 'integer', null, 'EIA plant code.', 'observed', ['eia-860-2025']), F('plant_name', 'string', null, 'EIA plant name.', 'observed', ['eia-860-2025']), F('state', 'string', 'USPS state code', 'Plant state.', 'observed', ['eia-860-2025']), F('operator', 'string', null, 'Utility name on the first listed generator.', 'observed', ['eia-860-2025']), F('primary_technology', 'string', null, 'EIA technology with the most nameplate capacity at the plant.', 'derived', ['eia-860-2025']), F('operable_generators', 'integer', 'generators', 'Count of operable generator records.', 'derived', ['eia-860-2025']), F('nameplate_capacity_mw', 'number', 'megawatts (MW)', 'Sum of generator nameplate capacity.', 'derived', ['eia-860-2025'], { derivation: 'Sum of Nameplate Capacity (MW), Operable sheet.' }), F('summer_capacity_mw', 'number', 'megawatts (MW)', 'Sum of generator net summer capacity.', 'derived', ['eia-860-2025'], { derivation: 'Sum of Summer Capacity (MW).' }), F('winter_capacity_mw', 'number', 'megawatts (MW)', 'Sum of generator net winter capacity.', 'derived', ['eia-860-2025'], { derivation: 'Sum of Winter Capacity (MW).' }), ] }, { id: 'largest-plants-generation-2025', artifactId: 'largest-plants-generation-2025', title: 'Ten largest U.S. power plants by net generation, 2025', unitOfObservation: 'One EIA plant (plant ID).', description: 'Plant net generation for 2025 from EIA-923, summed over all prime mover and fuel rows, ranked.', fields: [ F('rank_by_net_generation', 'integer', 'rank (1 = most)', 'Rank among all U.S. plants in EIA-923 2025 Page 1.', 'derived', ['eia-923-2025']), F('plant_code', 'integer', null, 'EIA plant ID.', 'observed', ['eia-923-2025']), F('plant_name', 'string', null, 'EIA plant name.', 'observed', ['eia-923-2025']), F('state', 'string', 'USPS state code', 'Plant state.', 'observed', ['eia-923-2025']), F('primary_technology', 'string', null, 'Technology with the most nameplate capacity in EIA-860 2025.', 'derived', ['eia-860-2025']), F('net_generation_2025_mwh', 'integer', MWH, 'Sum of Net Generation (Megawatthours) over the plant\'s rows.', 'derived', ['eia-923-2025']), F('nameplate_capacity_mw', 'number', 'megawatts (MW)', 'Summed EIA-860 nameplate capacity.', 'derived', ['eia-860-2025']), F('capacity_factor_pct', 'number', 'percent', 'Net generation divided by nameplate capacity times 8,760 hours.', 'derived', ['eia-923-2025', 'eia-860-2025'], { derivation: 'Uses year-end capacity; approximate for plants whose capacity changed during 2025.' }), ] }, { id: 'wa-utility-fuel-mix-2024', artifactId: 'wa-utility-fuel-mix-2024', title: 'Washington utilities\' aggregate 2024 fuel mix (Commerce)', unitOfObservation: 'One fuel category in the 2024 statewide utility fuel mix.', description: 'Share of electricity delivered by Washington utilities to Washington customers in 2024, by fuel, as labeled on the Department of Commerce chart.', fields: [ F('year', 'integer', 'calendar year', 'Fuel-mix year (2024).', 'observed', ['wa-commerce-fuel-mix']), F('fuel', 'string', null, 'Commerce fuel category; Unspecified is power whose source the utility could not identify (mostly market purchases).', 'observed', ['wa-commerce-fuel-mix-chart']), F('share_pct', 'number', 'percent', 'Share of the statewide aggregate fuel mix, as printed on the chart.', 'observed', ['wa-commerce-fuel-mix-chart'], { derivation: 'Transcribed by hand from the chart labels; labels sum to 100.02 because of rounding.' }), ] }, ]; // ---------- Events ---------- const events = [ { id: 'drought-2023', eventType: 'droughtDeclaration', startDate: '2023-04-01', endDate: '2023-12-31', label: '2023 drought emergency (12 watersheds)', description: 'Washington\'s 2023 drought emergency covered 12 watersheds; Ecology described the 2024 declaration as a continuation of it. Dates bracket the 2023 year only; see the source for exact declaration dates.', sourceIds: ['ecology-drought-2024'] }, { id: 'drought-2024', eventType: 'droughtDeclaration', date: '2024-04-16', label: '2024 statewide drought emergency', description: 'Ecology declared a drought emergency for most of Washington, excluding the Seattle, Tacoma and Everett service areas, citing water supply below 75% of normal.', sourceIds: ['ecology-drought-2024'] }, ]; // ---------- Analyses ---------- const sum = R.hydroShareSummary; const gc = R.grandCoulee2025; const capTop = R.largestPlantsCapacity2025; const genTop = R.largestPlantsGeneration2025; const second = capTop[1]; const genFirst = genTop[0], genSecond = genTop[1]; const sv24 = R.supplyVsSales.find((s) => s.year === 2024); const fm = R.utilityFuelMix2024.rows; const fmHydro = fm.find((r) => r.fuel === 'Hydro').share_pct; const fmUnspec = fm.find((r) => r.fuel === 'Unspecified').share_pct; const netImportYears = R.supplyVsSales.filter((s) => s.net_interstate_trade_mwh < 0).map((s) => s.year); const GEN_LIMITS = [ 'Net generation measures electricity produced by plants located in Washington, not the electricity Washington customers use; Washington trades large volumes with other states and Canada.', 'Conventional hydro excludes pumped storage, which EIA reports separately and which is near zero or negative in Washington.', ]; const A = (o) => ({ executedAt: EXECUTED, ...o }); const analyses = [ A({ id: 'wa-hydro-share-annual', title: 'Hydro share of Washington in-state net generation, 2001-2025', question: 'What share of electricity generated in Washington came from conventional hydropower each year?', operation: 'ratio', parameters: { tableId: 'wa-hydro-annual', numerator: 'hydro_net_generation_mwh', denominator: 'total_net_generation_mwh', producerType: 'Total Electric Power Industry' }, scope: 'Washington, calendar years 2001-2025 (EIA final data).', resultShape: 'timeSeries', structuredResult: R.hydroShareSeries.map((r) => ({ year: r.year, date: `${r.year}-01-01`, series: r.series, hydro_share_pct: r.hydro_share_pct })), displayResult: `Hydro supplied ${sum.min_share_pct}% (${sum.min_year}) to ${sum.max_share_pct}% (${sum.max_year}) of in-state net generation; ${sum.share_2023_pct}% in 2023, ${sum.share_2024_pct}% in 2024 and ${sum.share_2025_pct}% in 2025.`, methodologicalNotes: ['Share = Hydroelectric Conventional / Total, both for Total Electric Power Industry in EIA\'s State Historical Tables.', 'date is January 1 of each year, supplied only so charts can place annual values on a time axis.'], limitations: [...GEN_LIMITS, 'Annual shares hide large seasonal swings in hydro output (spring runoff versus late summer and winter).'], robustnessChecks: [ { analysisId: 'wa-utility-fuel-mix-2024', checkType: 'alternativeComparison', summary: `Measured by what Washington utilities delivered to customers rather than what in-state plants generated, hydro was ${fmHydro}% of the 2024 mix, just under half, with ${fmUnspec}% unspecified. This weakens "most" for consumption in 2024.` }, { analysisId: 'wa-generation-vs-retail-sales', checkType: 'sensitivity', summary: `Washington generated more electricity than it sold at retail in every year 2001-2024; in-state hydro alone equalled ${sv24.hydro_to_retail_sales_pct}% of 2024 retail sales. EIA estimates small net interstate imports in ${netImportYears.join(', ')}.` }, ] }), A({ id: 'wa-hydro-share-summary', title: 'Summary of the hydro share series', question: 'How low has the hydro share fallen, and in which years was it below 60 percent?', operation: 'summary-statistics', parameters: { analysisId: 'wa-hydro-share-annual' }, scope: 'Washington, 2001-2025.', resultShape: 'table', structuredResult: [sum], displayResult: `Mean ${sum.mean_share_pct}% (2001-2010 mean ${sum.mean_share_2001_2010_pct}%, 2016-2025 mean ${sum.mean_share_2016_2025_pct}%); below 60% only in ${sum.years_below_60_pct.join(' and ')}; never at or below 50%. 2025: ${twh(sum.hydro_2025_mwh)} of ${twh(sum.total_2025_mwh)} TWh.`, methodologicalNotes: ['Means are unweighted averages of annual shares.'], limitations: [...GEN_LIMITS] }), A({ id: 'wa-hydro-state-rank', title: 'Washington rank among states for conventional hydro, 2001-2025', question: 'Is Washington the largest hydropower-producing state, and by how much?', operation: 'rank', parameters: { tableId: 'wa-hydro-annual', universe: '50 states and DC' }, scope: 'All states, 2001-2025.', resultShape: 'table', structuredResult: R.hydroRank, displayResult: `Washington ranked first every year 2001-2025, with ${Math.min(...R.hydroRank.map((r) => r.wa_share_of_us_hydro_pct))}% to ${Math.max(...R.hydroRank.map((r) => r.wa_share_of_us_hydro_pct))}% of U.S. conventional hydro generation; Oregon, California or New York ranked second.`, methodologicalNotes: ['Ranks use annual net generation, not capacity.'], limitations: ['State totals assign each plant to the state where it sits; output from rivers shared with Oregon and Canada is credited to the dam\'s location.'] }), A({ id: 'state-hydro-top10-2025', title: 'Top 10 hydro states, 2025', question: 'Which states produced the most conventional hydropower in 2025?', operation: 'rank', parameters: { tableId: 'state-hydro-rank-2025' }, scope: '2025.', resultShape: 'table', structuredResult: R.stateHydroRank2025, displayResult: R.stateHydroRank2025.slice(0, 3).map((s) => `${s.rank}. ${s.state} ${twh(s.hydro_net_generation_mwh)} TWh (${s.share_of_us_hydro_pct}%)`).join('; ') + '.', limitations: ['One year; hydro rankings below first place shift with precipitation.'] }), A({ id: 'largest-plants-by-capacity-2025', title: 'Largest U.S. power plants by capacity, end of 2025', question: 'Is Grand Coulee the largest U.S. power plant by generating capacity?', operation: 'group-sum-and-rank', parameters: { tableId: 'largest-plants-capacity-2025', file: '3_1_Generator_Y2025.xlsx', sheet: 'Operable', groupBy: 'Plant Code', measures: ['Nameplate Capacity (MW)', 'Summer Capacity (MW)', 'Winter Capacity (MW)'] }, scope: 'All operable U.S. generators reported on EIA-860 for 2025.', resultShape: 'table', structuredResult: capTop, displayResult: `Grand Coulee ranks first by nameplate (${fmt(gc.nameplate_capacity_mw)} MW) and by net summer capacity (${fmt(gc.summer_capacity_mw)} MW); second by nameplate is ${second.plant_name} (${second.state}, ${fmt(second.nameplate_capacity_mw)} MW).`, methodologicalNotes: ['Capacity is summed over operable generators that share an EIA plant code; Grand Coulee\'s total includes six pump-generating units (314 MW nameplate). Conventional hydro units alone total ' + fmt(gc.nameplate_conventional_hydro_only_mw) + ' MW, still the largest.'], limitations: ['Plant boundaries follow EIA plant codes; a site reported under several codes would be split.', 'Net summer capacity exceeds nameplate at Grand Coulee because several units are rated above nameplate; other EIA publications have cited about 6.7 GW of summer capacity.'] }), A({ id: 'largest-plants-by-generation-2025', title: 'Largest U.S. power plants by net generation, 2025', question: 'Is Grand Coulee also the largest U.S. power plant by electricity produced?', operation: 'group-sum-and-rank', parameters: { tableId: 'largest-plants-generation-2025', file: 'EIA923_Schedules_2_3_4_5_M_12_2025_Final.xlsx', sheet: 'Page 1 Generation and Fuel Data', groupBy: 'Plant Id', measure: 'Net Generation (Megawatthours)' }, scope: 'All U.S. plants on EIA-923 2025 Page 1.', resultShape: 'table', structuredResult: genTop, displayResult: `No. ${genFirst.plant_name} (${genFirst.state}) led 2025 with ${twh(genFirst.net_generation_2025_mwh)} TWh and ${genSecond.plant_name} (${genSecond.state}) was second with ${twh(genSecond.net_generation_2025_mwh)} TWh; the top 10 were all nuclear. Grand Coulee produced ${twh(gc.net_generation_2025_mwh)} TWh and ranked ${gc.rank_by_net_generation_2025}th.`, methodologicalNotes: ['Net generation summed over every prime mover and fuel row of a plant, including Grand Coulee\'s pumped-storage row (-2,637 MWh).'], limitations: ['One year. Hydro output varies with water supply; Reclamation says Grand Coulee can produce up to 21 billion kWh, still below the leading nuclear plants.', 'Battery and other energy-storage plants reported on a separate EIA-923 sheet are not included; none is near the top of the ranking.'] }), A({ id: 'grand-coulee-2025-summary', title: 'Grand Coulee in 2025', question: 'What were Grand Coulee\'s capacity, output and ranks in 2025?', operation: 'lookup', parameters: { plantCode: 6163 }, scope: 'Grand Coulee (EIA plant 6163), 2025.', resultShape: 'table', structuredResult: [gc], displayResult: `${fmt(gc.nameplate_capacity_mw)} MW nameplate, ${fmt(gc.summer_capacity_mw)} MW summer, ${twh(gc.net_generation_2025_mwh)} TWh in 2025 (${gc.share_of_wa_2025_net_generation_pct}% of Washington's in-state generation); rank 1 by capacity, ${gc.rank_by_net_generation_2025} by generation.`, limitations: ['Share of Washington generation uses the state total from EIA\'s State Historical Tables, which is built from the same EIA-923 reports.'] }), A({ id: 'wa-generation-vs-retail-sales', title: 'Washington generation versus retail sales and net interstate trade, 2001-2024', question: 'Does Washington generate more electricity than it sells to its own customers?', operation: 'ratio', parameters: { tableId: 'wa-supply-disposition' }, scope: 'Washington, 2001-2024 (EIA State Electricity Profile Table 10; 2025 not yet published).', resultShape: 'table', structuredResult: R.supplyVsSales, displayResult: `Generation exceeded retail sales every year (ratio ${Math.min(...R.supplyVsSales.map((s) => s.generation_to_retail_sales_ratio))} to ${Math.max(...R.supplyVsSales.map((s) => s.generation_to_retail_sales_ratio))}). EIA's residual net interstate trade shows Washington as a net importer only in ${netImportYears.map((y) => `${y} (${fmt(-R.supplyVsSales.find((s) => s.year === y).net_interstate_trade_mwh)} MWh)`).join(', ')}; it was a net exporter in every other year, including 21-29 million MWh a year in 2020-2022.`, methodologicalNotes: ['Net interstate trade is EIA\'s residual: supply minus sales, direct use, international exports and estimated losses.'], limitations: ['Because net interstate trade is a residual, it absorbs errors in estimated losses and is approximate.', 'Physical flows do not identify which generator served which customer.'] }), A({ id: 'wa-utility-fuel-mix-2024', title: 'Hydro share of electricity Washington utilities delivered in 2024', question: 'What share of electricity delivered to Washington customers came from hydropower?', operation: 'transcription', parameters: { tableId: 'wa-utility-fuel-mix-2024' }, scope: 'Washington utilities, aggregate 2024 fuel mix (Commerce).', resultShape: 'table', structuredResult: fm, displayResult: `Hydro ${fmHydro}%, unspecified ${fmUnspec}%, natural gas ${fm.find((r) => r.fuel === 'Natural Gas').share_pct}%, wind ${fm.find((r) => r.fuel === 'Wind').share_pct}%, coal ${fm.find((r) => r.fuel === 'Coal').share_pct}%, nuclear ${fm.find((r) => r.fuel === 'Nuclear').share_pct}%.`, methodologicalNotes: ['Values were read from the labeled chart; Commerce\'s underlying spreadsheets are posted in a Box folder that requires a browser.'], limitations: ['Unspecified power (mostly market purchases) has no fuel attribution and may itself be partly hydro, so 48.73% is a floor on the hydro share of delivered power, not an estimate of it.', 'Utility-reported resource claims, not physical flows; Commerce compiles but does not audit every claim.', 'Only 2024 is included.'] }), A({ id: 'generation-cross-check', title: 'Cross-check of two EIA generation tables', question: 'Do EIA\'s State Historical Tables and the Washington State Electricity Profile agree on total generation?', operation: 'difference', parameters: { tables: ['eia-state-generation Total', 'eia-sep-washington Table 10 Total net generation'] }, scope: 'Washington, 2001-2024.', resultShape: 'table', structuredResult: [R.generationCrossCheck], displayResult: `Agree within ${R.generationCrossCheck.max_abs_difference_mwh} MWh in every year (rounding).`, limitations: ['Both tables come from the same EIA survey data, so agreement checks transcription, not measurement.'] }), ]; const replications = [ { id: 'usbr-nameplate', analysisId: 'grand-coulee-2025-summary', externalSourceId: 'usbr-grand-coulee', externalLocator: 'About page: "generating capacity of more than 6,809-megawatts"', externalValue: 6809, facthubValue: gc.nameplate_capacity_mw, unit: 'MW (nameplate)', note: 'Reclamation\'s figure equals the EIA-860 nameplate total including the pump-generating units.' }, { id: 'eia-tie-summer', analysisId: 'grand-coulee-2025-summary', externalSourceId: 'eia-tie-2024-drought', externalLocator: 'Today in Energy, Nov 7 2024, paragraph on the Columbia River Basin: "net summer capacity of 6.7 gigawatts"', externalValue: 6700, facthubValue: gc.summer_capacity_mw, unit: 'MW (net summer)', note: 'EIA\'s article gives a rounded, lower summer figure than the 2025 EIA-860 generator file sums to; the article does not say which units it counted. Either figure keeps Grand Coulee first: the next plant has 4,530 MW of summer capacity.' }, ]; // Sanity checks for (const t of tables) for (const f of t.fields) for (const s of f.sourceIds) if (!SRC_IDS.has(s)) throw new Error('unknown source ' + s); for (const e of events) for (const s of e.sourceIds) if (!SRC_IDS.has(s)) throw new Error('unknown source ' + s); const parts = { sources, tables, events, analyses, replications }; fs.writeFileSync(path.join(rel, 'dataset-parts.json'), JSON.stringify(parts, null, 2) + '\n'); // ---------- Docs ---------- const readme = `# Washington electricity generation by source and the largest U.S. power plants FactHub-curated research dataset. Not an official publication of EIA, the Bureau of Reclamation or the State of Washington. ## Contents - wa-generation-by-source.csv: Washington net generation by EIA energy source, 2001-2025. - wa-hydro-annual.csv: hydro share of in-state generation and Washington's rank among states, 2001-2025. - state-hydro-rank-2025.csv: top 10 hydro states in 2025. - wa-supply-disposition.csv: generation, retail sales and EIA's net interstate trade, 2001-2024. - largest-plants-capacity-2025.csv / largest-plants-generation-2025.csv: top 10 U.S. plants by capacity (EIA-860 2025) and by 2025 net generation (EIA-923 2025). - wa-utility-fuel-mix-2024.csv: Washington utilities' 2024 delivered fuel mix (Commerce), transcribed from the chart labels. - dataset-parts.json: the sources, tables, events, saved analyses and replications of this FactHub dataset version. - source-manifest.json: URL, byte length and SHA-256 of every downloaded source file. ## Measures "Net generation" is electricity produced by plants located in Washington. It is not the electricity Washington customers use; for that, see wa-supply-disposition.csv and wa-utility-fuel-mix-2024.csv. "Hydro" means EIA's Hydroelectric Conventional and excludes pumped storage. Plant capacity is the sum over operable generators sharing an EIA plant code; nameplate and net summer capacity are both reported. ## Reproduce 1. Download the files listed in source-manifest.json into a raw/ folder (unzip 3_1_Generator_Y2025.xlsx into raw/eia860/ and EIA923_Schedules_2_3_4_5_M_12_2025_Final.xlsx into raw/eia923/), and save the Commerce chart image as raw/commerce/2024_fuel-mix-chart.png. 2. Check each file's SHA-256 against source-manifest.json. EIA revises files in place, so a different digest means different data. 3. Node.js 20 with SheetJS: npm i https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz 4. node build.js raw results 5. node build_payload.js results raw release The Commerce percentages are typed into build.js from the chart labels; compare them with the chart. `; const quality = `# Quality report - Coverage: EIA final data for 2001-2025 (state generation), 2001-2024 (State Electricity Profile Table 10; 2025 not yet published), and 2025 (EIA-860 and EIA-923 final). - Cross-check: EIA's State Historical Tables and the Washington State Electricity Profile Table 10 agree on total net generation within ${R.generationCrossCheck.max_abs_difference_mwh} MWh in all ${R.generationCrossCheck.years} overlapping years. - Source digests: archive_source fetched each EIA file and returned the same SHA-256 as the local downloads in source-manifest.json. - Grand Coulee capacity: the EIA-860 nameplate total (${fmt(gc.nameplate_capacity_mw)} MW) matches Reclamation's published 6,809 MW. Net summer capacity (${fmt(gc.summer_capacity_mw)} MW) is higher than nameplate and higher than the 6.7 GW in an EIA Today in Energy article; both are reported. - Grand Coulee generation: 2025 plant total ${fmt(gc.net_generation_2025_mwh)} MWh. Its pumped-storage row (-2,637 MWh) equals the Washington pumped-storage total in the state table. - Missing values: an energy source absent from EIA's state file for a year has no row in wa-generation-by-source.csv; it is not zero-filled. - Commerce fuel mix: transcribed from chart labels; they sum to ${R.utilityFuelMix2024.sum_of_shares_pct}% because of rounding. - Wayback Machine captures were attempted with archive_source; sources without an archiveUrl could not be captured at authoring time (the Wayback Machine timed out or rate limited). `; fs.writeFileSync(path.join(rel, 'README.md'), readme); fs.writeFileSync(path.join(rel, 'quality-report.md'), quality); // ---------- Artifacts ---------- const ART = [ ['wa-generation-by-source', 'wa-generation-by-source.csv', 'text/csv', 'curatedTable', 'Washington net generation by EIA energy source, 2001-2025.'], ['wa-hydro-annual', 'wa-hydro-annual.csv', 'text/csv', 'derivedTable', 'Hydro share of in-state generation and national hydro rank, 2001-2025.'], ['state-hydro-rank-2025', 'state-hydro-rank-2025.csv', 'text/csv', 'derivedTable', 'Top 10 states by conventional hydro generation, 2025.'], ['wa-supply-disposition', 'wa-supply-disposition.csv', 'text/csv', 'curatedTable', 'Washington supply and disposition (EIA State Electricity Profile Table 10), 2001-2024.'], ['largest-plants-capacity-2025', 'largest-plants-capacity-2025.csv', 'text/csv', 'derivedTable', 'Ten largest U.S. plants by nameplate capacity (EIA-860 2025).'], ['largest-plants-generation-2025', 'largest-plants-generation-2025.csv', 'text/csv', 'derivedTable', 'Ten largest U.S. plants by 2025 net generation (EIA-923 2025).'], ['wa-utility-fuel-mix-2024', 'wa-utility-fuel-mix-2024.csv', 'text/csv', 'curatedTable', 'Washington utilities\' aggregate 2024 fuel mix, transcribed from Commerce\'s chart.'], ['dataset-parts', 'dataset-parts.json', 'application/json', 'documentation', 'Sources, tables, events, saved analyses and replications of this dataset version, as JSON.'], ['source-manifest', 'source-manifest.json', 'application/json', 'sourceManifest', 'URL, byte length and SHA-256 of every downloaded source file.'], ['documentation', 'README.md', 'text/markdown', 'documentation', 'Contents, definitions and reproduction steps.'], ['quality-report', 'quality-report.md', 'text/markdown', 'qualityReport', 'Cross-checks and data-quality notes.'], ['script-build', 'build.js', 'text/javascript', 'transformationManifest', 'Reads the EIA and Commerce source files and writes every table (Node.js 20 + SheetJS).'], ['script-payload', 'build_payload.js', 'text/javascript', 'transformationManifest', 'Writes the release files and this dataset\'s FactHub content.'], ]; const artifacts = ART.map(([id, fileName, mediaType, role, description]) => { const b = fs.readFileSync(path.join(rel, fileName)); return { id, role, fileName, mediaType, byteLength: b.length, contentDigest: sha(b), description, access: 'public' }; }); const ref = (pointer) => ({ $artifact: 'dataset-parts', pointer }); const content = { key: KEY, status: 'Final', rulesVersion: '2.10', title: 'Washington Electricity Generation by Source and the Largest U.S. Power Plants, 2001-2025', description: 'Annual EIA data on Washington in-state net generation by energy source (2001-2025), the state\'s hydro share and national hydro rank, generation versus retail sales and net interstate trade, Washington utilities\' 2024 delivered fuel mix, and EIA-860/EIA-923 rankings of the largest U.S. power plants by capacity and by 2025 generation. FactHub-curated; not an official EIA, Reclamation or Washington State publication.', selectionRationale: 'Tests two common claims: that hydropower supplies most of Washington\'s electricity, and that Grand Coulee is the largest U.S. power plant. Both depend on the measure used (in-state generation versus delivered power; capacity versus annual output), so the release keeps each measure separate.', topics: ['electricity', 'hydropower', 'Washington State', 'power plants'], geography: ['Washington State', 'United States'], temporalCoverage: '2001-2025 (state generation); 2001-2024 (supply and disposition); 2024 (utility fuel mix); 2025 (plant capacity and generation)', unitOfObservation: 'Mostly one state-year; plant tables are one EIA plant in 2025.', updateCadence: 'Immutable research release; EIA annual data for 2026 would be published as a new version.', curator: 'FactHub Research Team', reproducibilityStatus: 'Fully reproducible from public downloads with Node.js 20 and SheetJS.', reproducibilityExplanation: 'source-manifest.json lists every downloaded file with URL and SHA-256; build.js regenerates every table from those files and build_payload.js regenerates the release. The Commerce fuel-mix percentages are transcribed from a chart and are typed into build.js.', limitations: [ ...GEN_LIMITS, 'Washington\'s hydro output depends on Columbia River Basin water supply, so any single year can differ from the long-run pattern; 2023 and 2024 were drought years.', 'Plant rankings use EIA plant codes and 2025 data only; capacity rankings use year-end operable generators.', 'The consumption-side fuel mix covers 2024 only and includes 15.44% unspecified power.', ], sources: ref('/sources'), artifacts, tables: ref('/tables'), events: ref('/events'), derivedFrom: [], analyses: ref('/analyses'), replications: ref('/replications'), changelog: [{ date: '2026-10-09', summary: 'Initial version.' }], }; fs.writeFileSync(path.join(rel, 'dataset-request.json'), JSON.stringify(content) + '\n'); const inline = { ...content, ...parts }; fs.writeFileSync(path.join(rel, 'dataset-content-inline.json'), JSON.stringify(inline, null, 2) + '\n'); console.log(`Wrote ${artifacts.length} artifacts, ${tables.length} tables, ${analyses.length} analyses. Request ${JSON.stringify(content).length} bytes; inline ${JSON.stringify(inline).length} bytes.`); for (const a of analyses) console.log('-', a.id, ':', a.displayResult);