FDI bidirectional loop (parent depletion ↔ child growth)
Research-grade — validation in progress.
Sprint 1b — pure analytical timestep loop `runFdiBidirectionalLoop` in `src/lib/fdi/bidirectionalLoop.ts` couples parent depletion into child fracture propagation each step. Depletion → Δσ_h via analytical Geertsma `α·(1−2ν)/(1−ν)·Δp` (ν clamped [0.01, 0.49]); effective σ_h floored at 0; per-step half-length grows as `L += base·(1 + κ·relief)` where `relief = Δσ_h/σh0` ∈ [0, 1]; optional per-step SWPM residual sequence inverts to a `−rateGain·residual` bpm advisory (positive residual → cut rate). Standalone workspace route at `/fdi-loop` (κ / base growth / depletion rate / σh0 / net-p / α / ν sliders + per-step history table + `Download history CSV` button via `buildFdiLoopCsv`). MethodChip on the route links back to §Parent-child interference for the shared poroelastic vocabulary. Drift-guards: `bidirectionalLoop.test.ts` (8) + `buildFdiLoopCsv.test.ts` (4 — header lock, row count, delimiter, em-dash on non-finite).
Analytical primer only — the growth kernel is an empirical `L·(1 + κ·relief)` scalar and the SWPM inversion is a linear advisory, not a solved control problem. Promotion path: (a) replace the scalar Δσ_h with the full-tensor `poroelasticDepletion.ts` result (already available for /parent-child) so azimuth rotation feeds the child kernel; (b) upgrade the growth step to invoke `runNonPlanar3DPipeline` per timestep on the child mesh using the depletion-perturbed σh field via `stressFieldSampler`; (c) close the SWPM residual → pump-rate advisory into a receding-horizon controller once a field-pilot dataset is loaded through the shared `/projects/$p/workspaces/$w/field-validation` ingest path.
No phase markers extracted from this row's prose yet.
- No published error band yet — use with engineering judgment.