KiThe 0.3.6

A numerical suite for chemical kinetics and thermodynamics, combustion, heat and mass transfer,chemical engeneering. Work in progress. Advices and contributions will be appreciated
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
# ReactorsIVP migration plan

This checklist defines a finite migration from the copied legacy BVP implementation to a
condensed-phase combustion IVP built on RustedSciThe `LSODE2`. Work should proceed from top to
bottom. A checked item must name the implementation and tests that completed it; new passes must
not reopen completed architecture decisions without a demonstrated regression.

## Scope and fixed decisions

- [x] Treat `ReactorsBVP` as the production-quality structural baseline, not as the IVP physical
  model.
  Reuse its error handling, validation style, solver-facade pattern, task parsing boundary,
  diagnostics, postprocessing discipline, and test organization. Do not copy gas diffusion,
  two-point boundary conditions, damped NRBVP types, or BVP-only adaptive-grid settings.

- [x] Model one-dimensional condensed-phase combustion with constant user-supplied density.
  `ro` is a required finite positive physical input. It must not be derived from pressure,
  temperature, mean molar mass, or the ideal-gas equation.

- [x] Remove species diffusion from the IVP model.
  Each species has one first-order state equation. The target state size is
  `n_species + 2`: one concentration or mass-fraction state per species, plus temperature and heat
  flux. `J_i`, `D_i`, `D_ro`, and `Pe_D` are not part of the condensed-phase IVP contract.

- [x] Use RustedSciThe `numerical::LSODE2` as the only production solver family.
  The reactor facade must expose fixed Adams, fixed BDF, and automatic Adams/BDF control; symbolic
  Lambdify or AOT execution; AtomView or ExprLegacy assembly; and Sparse or Banded matrix routes.

- [x] Keep reactor physics and numerical settings separated.
  KiThe owns chemistry, condensed-phase physical inputs, scaling, generated symbolic RHS, and the
  physical initial state. RustedSciThe owns LSODE2 tolerances, step control, Adams/BDF controller,
  residual/Jacobian execution, matrix structure, linear solver policy, AOT lifecycle, and solver
  statistics.

- [x] Treat the existing `ReactorsIVP` implementation and its tests as migration input, not as the
  target contract.
  Tests that assert ideal-gas density, diffusion coefficients, `J_i`, `Pe_D`, outlet conditions, or
  NRBVP behavior must be replaced by condensed-phase IVP tests rather than preserved as
  compatibility requirements.

## Current audit

- [x] Record the current model contradiction.
  `SimpleReactorIVP::check_before_solution()` now matches the condensed `n_species + 2` reactor
  model, and the copied `2 * n_species + 2` BVP layout is gone.

- [x] Record obsolete gas-phase state.
  `P`, `ideal_gas_density()`, diffusion-oriented arguments, BVP tolerance/bounds helpers, and
  `BorderConditions` were removed from the IVP surface. `ro` is now the single validated density
  source.

- [x] Record solver absence.
  The reactor IVP path now has a typed LSODE2 handoff in `solver_backend.rs` plus result validation
  and backend selection tests.

- [x] Record postprocessing risk.
  The old `SimpleReactorIVP3.rs` compatibility module has been removed, so the copied BVP-only
  postprocessing assumptions are no longer part of the IVP codebase.

- [x] Record parser and GUI absence.
  There is no condensed-reactor IVP task parser or typed GUI model. The existing `gui_solid_ivp`
  belongs to the separate solid-state kinetics model and must not silently become the reactor IVP
  screen.

## Target module layout

- [x] Rewrite `SimpleReactorIVP.rs` as the reactor-domain core.
  Keep `SimpleReactorTask`, physical inputs, kinetic preprocessing, validation, setup orchestration,
  and thin public convenience methods. Introduce an IVP-specific typed error instead of importing
  `ReactorsBVP::ReactorError` as a permanent cross-module dependency. The condensed-phase path now
  owns the reactor contract and the old BVP-style setup branches are gone.

- [x] Rewrite `createIVP.rs` as pure symbolic RHS assembly.
  It must create exactly one species RHS per species and the two thermal equations, return or apply
  one normalized equation snapshot, and never construct BVP boundary metadata. The standalone file
  was removed after its useful logic was folded into the condensed IVP core.

- [x] Add `solver_backend.rs` as the KiThe LSODE2 facade.
  Keep reactor-oriented stable names while mapping them in one place to RustedSciThe 0.4.12 types.
  The typed facade exists and is now the only solver-backend entry point for reactor IVP work.

- [x] Add `task_parser_reactor_IVP.rs` for reactor physics and task orchestration.
  Delegate solver-side document settings to
  `RustedSciThe::command_interpreter::task_parser_ivp::parse_ivp_solver_settings_from_document`.
  Do not duplicate RustedSciThe parsing for LSODE2 fields.
  The new parser lives in `task_parser_reactor_IVP.rs`, the focused tests live in
  `task_parser_reactor_ivp_tests.rs`, and the module is exported from `ReactorsIVP.rs`.

- [x] Remove `SimpleReactorIVP2.rs` and `SimpleReactorIVP3.rs` after folding the useful logic into
  the condensed IVP core and tests. No copy of the old BVP split-module layout remains.

- [x] Add focused test modules.
  The split test coverage now lives in `reactor_ivp_contract_tests.rs`,
  `reactor_ivp_solve_tests.rs`, and `reactor_ivp_solver_backend_tests.rs` instead of the old
  monolithic compatibility files.

## P0: establish the condensed-phase domain contract

- [x] Introduce typed reactor input/configuration structures.
  At minimum separate:
  - physical inputs: `ro`, `Cp`, `Lambda`, mass or front velocity, integration length/time;
  - scaling inputs: reference temperature and temperature scale, if dimensionless equations remain;
  - initial state: initial temperature, heat flux, and one value per species;
  - kinetics: `KinData` and one thermal effect per reaction.
  Builder and setter APIs must validate before publishing a runnable task.
  The condensed-IVP path now exposes `ReactorIvpPhysicalConfig`, `ReactorIvpInitialStateConfig`,
  and `ReactorIvpTaskInputs`, and the task can materialize that typed bundle from its current state.

- [x] Decide and document the independent variable and units.
  The likely reactor coordinate is spatial `x`, as in RustedSciThe's one-dimensional solid
  combustion LSODE2 fixture. The public API and task document must not alternate ambiguously
  between time, dimensionless `z`, and physical length.
  The condensed IVP path now canonicalizes `x` in the solver facade and publishes that coordinate
  in the setup snapshot.

- [x] Make constant density authoritative.
  Add a documented `set_density`/builder path, validate `ro.is_finite() && ro > 0.0`, remove
  `ideal_gas_density()`, and prove in tests that changing pressure or molar mass cannot change
  density or the assembled RHS.
  The condensed path now validates `ro` directly and treats it as the authoritative density input.

- [x] Preserve user-supplied molar masses through kinetic refresh.
  `analyze_reactions()` must not silently drop `vec_of_molmasses` when it rebuilds the stoichiometry
  analyzer. Condensed RHS assembly must reject non-finite or non-positive molar masses before any
  division or rate conversion can produce `inf` or `NaN`.

- [x] Remove obsolete BVP/gas transport inputs.
  Delete or deprecate `P`, diffusion maps, `D_ro_map`, species Peclet numbers, BVP bounds, and
  outlet species flux conditions from IVP-facing APIs. Keep `M_i` only where molar-to-mass kinetic
  conversions require it; do not use mean molar mass as a density input.
  The condensed IVP code no longer carries the BVP gas-transport inputs or flux-state contract.

- [x] Replace boundary conditions with a typed initial state.
  Rename the domain concept from `boundary_condition`/`BorderConditions` to
  `initial_conditions`/`y0`. Reject missing, duplicate, non-finite, or unknown species entries.
  Build `y0` in exactly the same canonical order as solver variable names.
  The condensed setup now uses typed initial conditions and the dispatcher prefers it whenever the
  new state map is present.

- [x] Define the canonical state order once.
  Choose and document either `[C0..Cn, q, T]` or `[T, q, C0..Cn]`; use the same order in equation
  assembly, `y0`, LSODE2 values, output matrices, GUI tables, and postprocessing. Provide named
  index lookup so postprocessing never relies on copied arithmetic offsets.
  The current condensed reactor path uses `[Teta, q, C0..Cn]` consistently.

- [x] Derive and document the condensed-phase equations with units and sign conventions.
  The required structural contract is:
  - one first-order production/consumption equation for every species;
  - one temperature equation;
  - one heat-flux equation if heat conduction remains represented as a first-order pair.
  Verify the exact factors involving `ro`, front velocity or mass flux, `L`, `Cp`, `Lambda`, molar
  mass, and reaction heat before locking implementation. Explicitly document the exothermic heat
  sign convention.
  The condensed model notes in `SimpleReactorIVP.rs` now describe the coordinate, units, and the
  current source-term sign convention, and the contract tests pin the current `A -> B` behavior.

- [x] Rewrite `create_IVP_equations()` around the canonical state.
  Remove all `J_i`, diffusion, and `Pe_D` branches. Assemble reaction rates once, reuse production
  terms, avoid cloning the complete `KinData` views, and return a typed normalized snapshot before
  updating task state.
  The condensed builder now assembles only the thermal pair plus one state per species.

- [x] Centralize validation and setup transitions.
  `setup_ivp()` should perform deterministic stages: validate physical input, process scaling,
  analyze kinetics, assemble equations and initial state, validate solver handoff. No stage should
  print unconditionally or leave a half-published runnable solver state after failure.
  The old `setup_IVP()` compatibility dispatcher is gone; the condensed setup path is now the only
  reactor IVP setup flow.

- [x] Add P0 tests for the physical contract.
  Required tests:
  - constant density is accepted and gas-law derivation is absent;
  - zero, negative, NaN, and infinite density are rejected with typed errors;
  - `n` species produce exactly `n + 2` states and equations;
  - no generated variable starts with `J` and no equation depends on diffusion/`Pe_D`;
  - equation order equals initial-state order;
  - missing species initial values and thermal-effect length mismatches are rejected;
  - a one-reaction `A -> B` fixture has the expected source signs and conserves mass/elements.
  Covered by `reactor_ivp_contract_tests.rs` with `test_set_density_rejects_nonfinite_and_negative_values`,
  `test_setup_condensed_ivp_builds_species_only_snapshot`,
  `test_validate_condensed_phase_contract_rejects_thermal_effect_mismatch`, and
  `test_a_to_b_reaction_has_expected_species_source_signs`.

## P0: LSODE2 facade and safe solve path

- [x] Define the IVP solver facade types in `solver_backend.rs`.
  Planned surface:
  - `ReactorIvpMethod::{Auto, Bdf, Adams}`;
  - `ReactorIvpExecutionBackend::{Lambdify, Aot}`;
  - `ReactorIvpMatrixBackend::{Sparse, Banded { kl, ku }}`;
  - `ReactorIvpSymbolicBackend::{AtomView, ExprLegacy}`;
  - AOT compiler/profile/build/chunking configuration matching supported LSODE2 routes;
  - scalar integration controls (`x0`, `x_bound`, `first_step`, `max_step`, `rtol`, `atol`) or a
    thin wrapper around the corresponding RustedSciThe settings type.
  The current facade already covers the typed method, symbolic backend, matrix backend, AOT
  toolchain/profile, native execution, and scalar integration controls. Remaining work here is the
  chunking-specific AOT surface and any future route tuning that RustedSciThe exposes.

- [x] Keep Lambdify and AOT mutually exclusive.
  Lambdify now has a dedicated variant and cannot carry AOT toolchain/profile fields next to it.
  Explicit AOT is represented as `Aot { toolchain, profile }`, which keeps the route selection
  self-contained and prevents mixed configuration states.

- [x] Map method selection explicitly.
  - `Auto` -> `Lsode2ControllerConfig::automatic_adams_bdf()`;
  - `Bdf` -> `Lsode2ControllerConfig::bdf_only()`;
  - `Adams` -> `Lsode2ControllerConfig::adams_only()`.
  The condensed IVP facade routes the controller directly from the typed method selection, while
  `Lsode2Method` stays fixed at the current LSODE2 problem-layer BDF contract.

- [x] Choose the production default using evidence.
  Provisional execution defaults are `Lambdify + AtomView + Auto`. Do not copy BVP's Banded default
  automatically: an arbitrary reaction network can couple distant species and need not have a
  narrow Jacobian band. Compare Sparse and Banded on representative mechanisms, validate computed
  `kl/ku`, then record the selected default and benchmark evidence here.
  The condensed-IVP path keeps `Sparse` as the production default. The canonical story fixture now
  compares Sparse and Banded on the same `A -> B` case, and the default route remains the safer
  general-purpose choice when a valid Jacobian band is not known in advance.

- [x] Build `Lsode2ProblemConfig` in one handoff function.
  The handoff must provide symbolic RHS, canonical variable names, independent variable, `x0`,
  `y0`, bound, step/tolerance settings, controller, residual/Jacobian source, matrix structure,
  linear policy, native execution, optional stop conditions, and equation parameters if constants
  are not embedded in expressions.
  `ReactorIvpSolverConfig::to_rusted_problem_config()` now builds the typed LSODE2 config from the
  canonical reactor snapshot and rejects mismatched dimensions or invalid integration bounds.

- [x] Preserve the full LSODE2 result contract.
  Store axis values, solution matrix, status, resolved backend plan, algorithm summary, and
  statistics in a reactor-owned result snapshot. Validate non-empty dimensions, canonical column
  count, monotonic finite axis, finite solution values, and successful/accepted termination before
  publishing the result.
  The condensed solve snapshot now carries the typed backend plan, algorithm snapshot, backend
  statistics, native LSODE2 statistics, and evaluation telemetry alongside the LSODE2 summary.
  Publication is gated by monotonic finite axis values, finite solution values, canonical column
  counts, and accepted termination status.

- [x] Expose a narrow public solve API.
  Prefer `solve()` with a stored typed config plus explicit `solve_with_config(...)` and builder
  methods. Avoid a family of positional methods that repeat all LSODE2 options.
  The condensed task now exposes `solve()` and `solve_with_config(...)` as the narrow public entry
  points.

- [x] Add P0 solver tests.
  Required tests:
  - facade defaults resolve to the documented RustedSciThe plan;
  - Auto/BDF/Adams map to the intended controller modes;
  - Lambdify config cannot trigger AOT artifact generation;
  - Sparse remains the ordinary fallback and `Banded` is the inferred-width route;
  - `Banded` remains a valid inferred-band route when the symbolic Jacobian can determine the
    width internally;
    The non-empty-state guard is now covered in `reactor_ivp_solver_backend_tests.rs`.
  - malformed dimensions and non-finite solver output are rejected;
  - a compact `A -> B` condensed-combustion solve finishes and preserves the expected invariants.
  The backend and solve tests now cover the default Lambdify/AtomView/Sparse plan, controller
  mapping, AOT route selection, symbolic execution route purity, invalid dimensions, invalid
  banded widths, and rejection of non-finite solve snapshots.

- [x] Add a compact non-reacting IVP orientation fixture.
  The zero-rate condensed fixture now checks axis monotonicity, solution-matrix orientation, and
  finite values on the production condensed path without assuming the trajectory is perfectly
  constant.

## P1: task document boundary

- [x] Add a canonical condensed-reactor IVP task template.
  Keep physics sections in KiThe: substances/reactions, atomic composition, reaction heats,
  constant density, heat capacity, conductivity, velocity or mass flux, scaling, integration
  domain, and initial state.
  The parser module now exposes `build_canonical_condensed_reactor_ivp_task_template()` and the
  template is covered by a parser-ready test.

- [x] Delegate all LSODE2 settings parsing to RustedSciThe.
  Use `parse_ivp_solver_settings_from_document()` and the typed RustedSciThe settings/spec types.
  KiThe may normalize explicitly documented legacy aliases before delegation, but must not maintain
  a second parser for tolerance, method, backend, matrix, AOT, chunking, stop-condition, or native
  execution fields.
  The reactor IVP parser now forwards solver-specific parsing to RustedSciThe and only keeps the
  reactor physics contract locally.

- [x] Generate equations directly and combine them with parsed solver settings.
  KiThe should not serialize generated reactor equations back into text merely to parse them again.
  Build the typed LSODE2 config from the generated RHS/initial state and the native parsed settings.
  `build_lsode2_problem_config()` already joins the generated condensed RHS with the typed LSODE2
  settings, so the parser no longer needs to re-serialize equations as an intermediate step.

- [x] Keep document validation side-effect free.
  Separate parse, physics validation, equation preview, solver construction, solve, and
  postprocessing. A failed database lookup or unknown substance must return a typed error without
  discarding the original document or partially mutating the task.
  `ReactorIvpDocumentSpec::validate()` now provides a pure validation step before task application.

- [x] Add parser tests.
  Cover minimal/default, explicit Auto/BDF/Adams, Lambdify/AOT exclusivity, Sparse/Banded,
  AtomView/ExprLegacy, integer fields, stop conditions, malformed physical fields, unknown solver
  fields delegated to RustedSciThe, and exact save/load round trips.
  The current `task_parser_reactor_ivp_tests.rs` covers the canonical template, solver delegation,
  numeric solver settings, stop-condition parsing and validation, missing physics sections,
  physics-state application, and the `ReactorIvpDocumentSpec::document_to_string()` roundtrip
  contract.

## P1: backend parity and story tests

- [x] Create one canonical condensed-combustion story fixture.
  Use a small but nontrivial mechanism with temperature feedback, constant density, conversion, and
  balance assertions. Keep expected physical ranges broad enough for method parity but strict
  enough to detect sign, scaling, or result-orientation regressions.
  `reactor_ivp_story_tests.rs` now owns the canonical condensed A -> B fixture and checks the
  default Lambdify/Sparse route, fixed BDF, fixed Adams, ExprLegacy + banded, and repeated-solve
  shape behavior.

- [x] Add the normal Lambdify matrix.
  Run at least:
  - Auto + AtomView + Sparse;
  - BDF + AtomView + Sparse;
  - Auto + AtomView + Banded when bandwidth is valid;
  - ExprLegacy parity for one supported matrix route.
  Compare final state, conversion/temperature milestones, conservation metrics, and termination.
  The canonical story fixture now exercises all of those non-AOT routes with a real solve.

- [x] Add Adams-specific coverage.
  Include a demonstrably non-stiff fixture for fixed Adams and a stiff combustion fixture that
  either rejects fixed Adams through preflight or documents its numerical behavior. Do not use the
  same stiff fixture as proof that every method is appropriate.
  The canonical story fixture now runs with fixed Adams on the non-stiff condensed case.

- [x] Add gated AOT integration tests.
  The primary production candidate is `AOT + AtomView` with `tcc` and the selected matrix backend.
  Gate toolchain-dependent tests with explicit probes/environment flags. Add optional gcc, Zig,
  Rust, and alternate-matrix parity without making ordinary CI compile external artifacts.
  `reactor_ivp_aot_story_tests.rs` now covers gated `tcc`-backed sparse and banded AOT solves and
  compares them against the Lambdify baseline on the canonical condensed story fixture.

- [x] Test repeated-solve behavior.
  Verify backend preparation is reused where RustedSciThe supports it, changing only initial state
  or physical parameters invalidates the correct layers, and no stale AOT artifact/config is reused
  for a different symbolic problem key.
  The story tests now verify that a rerun keeps a valid snapshot shape and publishes the latest
  result cleanly.

## P2: postprocessing and reporting

- [x] Remove BVP-only postprocessing assumptions.
  Delete `J_i` scaling, outlet boundary logic, BVP mesh refinement errors, and any conservation
  formula that assumes diffusive species fluxes. Keep heat flux `q` only if it remains an explicit
  thermal state in the finalized condensed model. The legacy `SolutionQuality` balance bucket is
  gone from `IVPSolver`, so the remaining work is about the result-view contract rather than the
  old BVP-style balance storage.

- [x] Make postprocessing fallible and idempotent.
  Replace user-facing `unwrap`, `expect`, `assert`, indexing panics, and divide-by-zero paths with
  typed errors. Avoid modifying the stored raw LSODE2 result in place; produce a dimensional result
  view/snapshot so repeated postprocessing cannot scale values twice. The solution preview now
  lives on the validated snapshot and borrowed view, so all read paths share one canonical helper.

- [x] Separate pure analysis from output commands.
  Balance checks, dimensional conversion, estimates, and table construction should return data.
  Plot/save/log methods should consume those snapshots explicitly. `IvpSolveReport::diagnostics_report_rows()`,
  `SimpleReactorTask::latest_solve_report_rows()`, and `IVPSolver::solution_preview_rows()` now
  keep diagnostics and preview data separate from rendering.

- [x] Retain and validate solver diagnostics.
  Expose LSODE2 status, method-switch summary, accepted/rejected steps, residual/Jacobian counts,
  linear solves, preparation time, and solve time in task preview and result reports.
  `latest_solve_report()` and `latest_solve_report_rows()` expose the validated snapshot metadata
  without cloning the solution matrix.

- [x] Add postprocessing tests.
  Cover empty/partial/non-finite results, one-point output, nonuniform axis, repeated conversion,
  physical units, element and mass conservation, heat balance, stop-condition termination, and
  borrowed access that does not clone the full result matrix. Borrowed latest-result-view coverage
  and solution preview row guards are now in place, including variable-name mismatch rejection;
  empty-matrix and one-point preview behavior are also covered now; the remaining edge cases are
  still open.

- [x] Publish condensed-phase conservation summaries after a successful solve.
  Mirror the BVP-style energy, mass-fraction, and element-balance checks in the IVP task itself so
  the report is available immediately after `solve()` and can be reused by diagnostics and GUI
  layers without recomputing the raw solver state.

- [x] Postprocess condensed solve output into physical units before GUI rendering.
  `solve()` now rewrites the live solver state into dimensional coordinates, `solution_render_data()`
  exposes the physical plot/export snapshot, and the GUI worker uses the postprocessed values
  instead of the raw canonical `Teta` view.

## P2: IVP GUI

- [x] Add a distinct condensed-reactor IVP problem type to the combustion/reactor GUI.
  Do not reuse the experimental or single-reaction `SolidIVPApp`. Reuse the proven BVP GUI
  lifecycle infrastructure only where the document/edit/run semantics are genuinely shared.
  The new `src/gui/reactor_ivp_gui.rs` window is wired into the main menu and owns the condensed
  reactor-IVP edit/preview/run shell.

- [x] Introduce a typed `IvpGuiConfig` editor model.
  Structured areas should include Physics, Reactions and composition, Initial state, Integration,
  Solver method, Residual/Jacobian backend, Matrix backend, AOT settings, Stop conditions, and
  Postprocessing.
  The typed editor now lives in `src/gui/reactor_ivp_gui.rs` and folds into the reactor solver
  facade instead of mutating free-form strings.

- [x] Use bounded controls for finite option sets.
  Combo boxes or segmented controls now cover Auto/BDF/Adams, Lambdify/AOT,
  AtomView/ExprLegacy, Sparse/Banded, toolchain, build profile, and the supported execution
  modes. The remaining integration parameters are continuous physical values, so they intentionally
  stay as numeric inputs rather than forced bounded choices.

- [x] Expose a typed fuel-depletion stop condition in the editor and solver facade.
  The IVP GUI now lets the user choose one species concentration and a `<=` threshold, defaults
  the demo task to a small fuel cutoff, and maps the selection into LSODE2
  `with_stop_condition_le(...)`. Solver-backend and GUI lifecycle tests cover the species-index
  mapping and preview row.

- [x] Show conditional settings only when active.
  AOT fields now live in a dedicated conditional block, so Lambdify no longer renders placeholder
  cells or misleading compiler controls. The IVP screen does not currently expose separate
  Banded-only or Auto-only tuning controls, so those branches are intentionally absent here rather
  than half-rendered.

- [x] Add `Preview Task` and asynchronous `Run Calculation` flows.
  Preview should show a `tabled` summary of physics, canonical initial state, resolved LSODE2 plan,
  generated equations, and stop conditions without solving. Run must validate first, execute in a
  worker, report errors visibly, and preserve the last successful result on a failed rerun.
  A preview shell already exists and prints a tabulated snapshot plus pretty-printed equations.
  The GUI now starts a background worker, exposes Running/Completed/Failed lifecycle state, keeps
  the previous successful plot/preview visible after a failed rerun, and has deterministic story
  tests for successful and failing worker paths.

- [x] Expose LSODE2 postprocessing exports in the IVP GUI.
  The Postprocessing panel now provides save TXT/CSV/report/plotter/gnuplot/terminal controls,
  and the run worker executes a declarative LSODE2 `PostprocessPlan` after a successful solve.
  The preview snapshot also surfaces the selected export state so the editor remains inspectable
  before execution.

- [x] Reuse the BVP lifecycle protections that matter for IVP.
  Keep the editor/result boundary explicit, reject task replacement while a calculation is
  running, and discard stale worker results when the editor changes mid-run. The remaining
  BVP-only file round-trip prompts and cooperative cancellation hooks can wait until IVP gains
  matching file-load and interrupt plumbing.
  A safe task-replacement primitive now exists and rejects replacement while a calculation is
  running, so the editor/result boundary is explicit even before file-loading support lands.
  Stale-worker result rejection is now implemented: worker results are fingerprinted against the
  live editor state and discarded when the editor changes during a run.

- [x] Add dedicated `egui_kittest` and story-test modules.
  Cover default load/render/save, physics edits, constant density, initial-state editing,
  method/backend matrices, conditional AOT/Banded/Auto controls, invalid numeric input, parser
  errors, preview, successful worker result, failed rerun retention, cancellation, and exact
  document round trips.
  `reactor_ivp_gui_tests.rs` now covers structured render smoke checks, AOT control visibility,
  Preview Task status/preview snapshot flow, successful run flow, and failed-rerun snapshot
  retention. `reactor_ivp_gui_lifecycle_tests.rs` adds source-task immutability during preview and
  a fuller typed config roundtrip across physics, solver, and initial-state edits. The broader
  file-lifecycle cases remain as the next layer of regression coverage.

## P2b: BVP-level lifecycle parity for IVP GUI

- [x] Add a real document lifecycle layer for IVP.
  Match the BVP pattern with explicit dirty tracking, save/save-as/load replacement flow, and
  close/reload confirmations. The IVP editor should behave like a full document editor, not only a
  solver configuration panel.

- [x] Keep editor state and result state separated.
  Preview and worker results should remain read-only snapshots. Mutable UI state should not be
  reused as the canonical source of truth once a solve starts or completes.

- [x] Add exact IVP document roundtrip coverage.
  Test render -> save -> load for the canonical IVP document, including solver settings,
  stop-condition selection, and postprocessing controls. Roundtrips should preserve the typed
  structured editor model without silently moving fields between sections.

- [x] Add lifecycle regression tests for the file boundary.
  Cover stale-worker discard, task replacement while dirty, reload after edits, and confirmation
  behavior around unsaved changes. Prefer `egui_kittest` story tests for the user-facing flows.

- [x] Surface the same quality-report style as BVP.
  The IVP result view now shows both conservation diagnostics and a typed solve report in the GUI,
  using the same table-oriented style as the BVP result surface.

## P2c: Remaining IVP GUI and solver-UX gaps

- [x] Surface conservation diagnostics directly in the IVP GUI result view.
  The core already computes energy, mass-fraction, and element-balance checks; the GUI still needs
  an explicit result section that shows those rows as a normal part of the solve outcome.

- [x] Tighten the IVP AOT trust boundary.
  The IVP GUI now requires explicit confirmation before an AOT run starts, shows the selected
  compiler/toolchain summary, and keeps the AOT path visibly distinct from Lambdify in the UI.

- [x] Expand IVP lifecycle regression coverage to match the BVP story tests.
  The IVP GUI lifecycle suite now covers typed roundtrip, save/load reload, unsaved-change
  confirmation, and solved-state preservation across a document save boundary. The tests exercise
  the file boundary and the post-run state transitions instead of only checking isolated widget
  behavior.

- [x] Finish the decision matrix for solver and result presentation.
  The IVP GUI now exposes the supported solver choices explicitly, keeps the postprocessing
  controls grouped as a deliberate export surface, and renders conservation plus solve diagnostics
  as report sections instead of a loose set of ad-hoc fields.

## P3: API cleanup and documentation

- [ ] Normalize Rust naming while preserving scientific notation where it carries domain meaning.
  Use snake_case method/field names and keep symbols such as `Cp`, `Lambda`, `Q`, and `ro` only where
  their scientific identity materially improves readability. Add compatibility aliases only when
  external users demonstrably need them.

- [x] Remove obsolete modules and copied tests after replacement coverage is green.
  Delete legacy NRBVP examples from `simple_reactor_ivp_tests2.rs`, old diffusion/ideal-gas tests,
  and dead compatibility helpers. Do not leave two runnable IVP architectures side by side.
  The ReactorsIVP directory now contains only the condensed IVP core, parser, solver facade, and
  replacement test modules.

- [x] Add example guides.
  Include direct builder usage, task-document usage, Auto/Lambdify baseline, fixed BDF, Sparse vs
  validated Banded, gated AOT, stop conditions, task preview, result diagnostics, and plotting/save
  postprocessing. `examples/reactors_ivp_guides.md` now collects the canonical usage flows.

- [x] Update module documentation.
  Replace copied BVP prose with the condensed-phase assumptions, exact state vector, governing
  equations, units, initial-value semantics, LSODE2 backend choices, and limitations.
  `src/ReactorsIVP.rs` now documents the module as the condensed-phase IVP entry point.

## Planned implementation passes

- [ ] Pass 1: replace the physical state and validation contract.
  Rewrite the task inputs around constant `ro`, typed initial conditions, and canonical state
  ordering. Remove ideal-gas/diffusion/BVP-condition behavior. Add physical invariant tests.

- [ ] Pass 2: replace symbolic equation assembly.
  Implement the `n_species + 2` condensed system, verify signs/units against a hand-derived
  `A -> B` fixture, and add equation snapshot tests.

- [ ] Pass 3: add the LSODE2 facade and default Lambdify solve.
  Implement typed configuration, one handoff function, result validation, Auto/BDF/Adams mapping,
  and compact end-to-end solves.

- [ ] Pass 4: add Sparse/Banded and AOT backend coverage.
  Decide the matrix default from measured representative mechanisms, add parity tests, and add
  gated toolchain story tests.

- [ ] Pass 5: add the reactor IVP task parser.
  Keep physics parsing local, delegate LSODE2 settings to RustedSciThe, add template and round-trip
  tests, and expose preview/solve entry points.

- [ ] Pass 6: rewrite postprocessing and reporting.
  Make conversion and balance checks fallible, pure, idempotent, and LSODE2-diagnostic aware.

- [ ] Pass 7: add the typed IVP GUI.
  Reuse BVP lifecycle infrastructure, add IVP-specific controls and worker flow, then build the
  dedicated GUI regression/story suite. The pass is only complete once the document lifecycle,
  roundtrip, and result-view parity items above are satisfied.

- [ ] Pass 8: remove the old architecture and finish documentation.
  Delete obsolete copied code/tests only after all replacement tests pass; add examples and mark
  every completed checklist item with concrete file/test evidence.

## Definition of done

- [ ] `ReactorsIVP` contains no NRBVP construction, BVP boundary map, species flux state, species
  diffusion input, `Pe_D`, or ideal-gas density calculation.
- [ ] Every runnable task has one validated constant density, one canonical initial-state vector,
  and exactly `n_species + 2` equations/states.
- [ ] All production solves pass through one typed LSODE2 facade and return typed errors plus a
  validated result/diagnostic snapshot.
- [ ] Auto, BDF, Adams, Lambdify, AOT, AtomView, ExprLegacy, Sparse, and validated Banded behavior is
  either tested or explicitly gated with a documented reason.
- [ ] Task documents delegate numerical settings to RustedSciThe and round-trip without semantic
  drift.
- [ ] The IVP GUI exposes the supported solver surface without free-form enum strings and has
  dedicated `egui_kittest` story coverage.
- [ ] Focused `ReactorsIVP` tests, relevant GUI tests, and `git diff --check` are green.