Goal: Solar + Wind 25-year generation simulation working as a pure Python module with CLI driver. Validated against one Excel scenario. Tasks: [x] S1-T01 Schema: SolarConfig, WindConfig, GenerationResult in engine/schemas/generation.py. [x] S1-T02 Catalog: 3 solar 8760 profiles (RJ, KA, GJ) as CSV in engine/catalog/profiles/solar/. 3 wind profiles. Add loader. [x] S1-T03 generation/solar.py: function simulate_solar(config: SolarConfig) -> pd.DataFrame returning 25y x 8760 rows with columns year, hour, dc_power_mw, ac_power_mw_pre_clip, ac_power_mw, degradation_factor. [x] S1-T04 Solar logic: scaling, DC losses, inverter n, AC losses, clipping at MW_AC, availability, soiling (monthly profile or flat), Y1 + 0.7%, Y2-25 + 0.5% degradation. [x] S1-T05 Tests: CUF reasonable (15-25% range for solar), clipping captures DC excess correctly, degradation factors monotonic. [x] S1-T06 generation/wind.py: power curve lookup, wind shear correction, wake losses, electrical, availability, degradation. [x] S1-T07 Wind tests: PLF reasonable (25-40%), edge cases (zero wind, gale wind = power=0). [x] S1-T08 generation/bess_state.py: function simulate_bess_capacity(config: BessConfig, cum_cycles_per_year: list[float]) -> pd.Series returning usable MWh per year. Note: dispatch happens elsewhere; this module only models physical capacity. Augmentation as input list of (year, additional_mwh). [x] S1-T09 CLI: remodel simulate-gen --input scenario.json --output gen.parquet. [x] S1-T10 Parity test: placeholder created; tests skipped pending user-supplied Nagasamudra inputs + Excel expected values (see tests/fixtures/nagasamudra_inputs.json and tests/integration/test_parity.py). [x] S1-T11 Documentation: packages/engine/docs/generation.md explaining the module and how to extend. Definition of Done: CLI generates 25y output for the user's reference scenario. Year-1 CUF matches Excel within 0.1%. All tests pass. ## Sprint Retro **Done:** All S1-T01 through T11 tasks complete. 43 unit tests pass, 2 integration tests skipped (parity gate, awaiting Nagasamudra data). Coverage 97.4%. Ruff clean, mypy strict clean. **Deviations:** - Typer 0.12.5 is incompatible with Click 8.3.3 (Click's new UNSET sentinel causes Typer to set is_flag=True on all Path options). Upgraded to Typer 0.25.1 to fix. - Python 3.12 not installed; used 3.13 (pyproject.toml keeps ^3.12 constraint, 3.13 is compatible). - S1-T10 parity gate blocked — user must supply real Nagasamudra project data; unlock instructions are in tests/integration/test_parity.py docstring. **Next sprint prerequisite:** User unlocks S1-T10 by filling tests/fixtures/nagasamudra_inputs.json with real project inputs and Excel-derived expected values.