Context
Phase 2a (PR #206) and Phase 2b (PR #207) shipped the L-7b-ii monolithic image foundation:
libtotapi_mono.so is dlopen-loadable and 1e-10 equivalent to default libtotapi.so on existing fixtures.
tot_is_mono() C ABI distinguishes the two builds at runtime.
TotPipeline._detect_mono + _active_rules + _MONO_ONLY_RULES overlay infrastructure is in place.
- Layer-C smoke test proves the broker IS shared in the mono image when called via direct
ctypes (eq_run(1) → eq_bpsd_put → tr_check_bpsd_pull = 1).
What is still missing for production-ready monolithic BPSD coupling:
Eqlib / Trlib / Fplib / Tilib / Wrxlib each load their OWN per-module lib<mod>api.so via EQLIB_PATH / TRLIB_PATH / etc.
- A
TotPipeline user setting TOTLIB_PATH=...mono.so gets tot_is_mono() == 1, but the wrapper instances inside the pipeline (Eqlib, Trlib, ...) still each load THEIR per-module .so.
- Consequence: even though the
_MONO_ONLY_RULES overlay is in place, populating ("eq","tr") would cause run_pipeline to fire the verify rule against a Trlib instance reading from libtrapi.so's PRIVATE bpsd, not from the mono image's shared bpsd. Verify would deterministically fail.
_MONO_ONLY_RULES is intentionally empty in Phase 2b (Codex pre-push review HOLD on PR #207 caught this). Phase 2c closes the gap.
Scope: short chain of 2 PRs (per Codex retrospective 2026-05-18)
PR-A — Wrapper mono routing contract
Single authoritative routing rule, NOT ad-hoc per-wrapper env handling.
PR-B — Behavioral activation
Acceptance criteria (combined)
Eqlib(...) / Trlib(...) / etc. constructed inside a TotPipeline whose tot_is_mono() returns 1 ALSO load the mono image (not their per-module .so).
TotPipeline().run_pipeline([("eq",...),("tr",...)]) with mono routing populated runs ("eq","tr") verify rule and PASSES (broker round-trip succeeds).
- Same call with default
libtotapi.so selected: rule NOT activated (or activated but fails cleanly with a clear "mono image required" error).
- CLAUDE.md: 1e-10 equivalence preserved.
- Default per-module path: untouched.
Out of scope
- Restructuring any Fortran source (
feedback_fortran_refactor_needs_lead_signoff.md).
- Cross-module coupling rules other than
("eq","tr").
- Changing the existing per-module
_ffi.py path-resolution priority for non-mono users.
References
Codex's specific guidance for this PR chain
"Make Phase 2c a short chain, not one wide PR. First PR adds a shared mono-path loading contract and updates the 5+ module _ffi.py loaders without activating eq -> tr; second PR flips _MONO_ONLY_RULES and adds a true TotPipeline.run_pipeline([eq, tr]) integration test."
"The other cross-cutting risk is loader semantics — current _ffi.py loaders resolve environment/default paths independently, so Phase 2c needs a single authoritative mono routing rule, not ad hoc env handling in each wrapper."
Context
Phase 2a (PR #206) and Phase 2b (PR #207) shipped the L-7b-ii monolithic image foundation:
libtotapi_mono.sois dlopen-loadable and 1e-10 equivalent to defaultlibtotapi.soon existing fixtures.tot_is_mono()C ABI distinguishes the two builds at runtime.TotPipeline._detect_mono+_active_rules+_MONO_ONLY_RULESoverlay infrastructure is in place.ctypes(eq_run(1) → eq_bpsd_put → tr_check_bpsd_pull = 1).What is still missing for production-ready monolithic BPSD coupling:
Eqlib/Trlib/Fplib/Tilib/Wrxlibeach load their OWN per-modulelib<mod>api.soviaEQLIB_PATH/TRLIB_PATH/ etc.TotPipelineuser settingTOTLIB_PATH=...mono.sogetstot_is_mono() == 1, but the wrapper instances inside the pipeline (Eqlib, Trlib, ...) still each load THEIR per-module.so._MONO_ONLY_RULESoverlay is in place, populating("eq","tr")would causerun_pipelineto fire the verify rule against aTrlibinstance reading fromlibtrapi.so's PRIVATE bpsd, not from the mono image's shared bpsd. Verify would deterministically fail._MONO_ONLY_RULESis intentionally empty in Phase 2b (Codex pre-push review HOLD on PR #207 caught this). Phase 2c closes the gap.Scope: short chain of 2 PRs (per Codex retrospective 2026-05-18)
PR-A — Wrapper mono routing contract
Single authoritative routing rule, NOT ad-hoc per-wrapper env handling.
MONO_LIB_PATHenv var honored by all 5+ wrappers'_ffi.py, OR apython/_runtime_mode.pymodule that each wrapper consults).python/eqlib/_ffi.py,python/trlib/_ffi.py,python/fplib/_ffi.py,python/tilib/_ffi.py,python/wrxlib/_ffi.pyto honor the shared mechanism.("eq","tr")in this PR — keep_MONO_ONLY_RULESempty so the wrapper plumbing can ship without behavioral side-effect.PR-B — Behavioral activation
_MONO_ONLY_RULESwith the("eq","tr")verify rule.TotPipelineintegration test:pipeline.run_pipeline([("eq", ...), ("tr", ...)])withMONO_LIB_PATHset; verify rule fires andcheck_bpsd_pullreturns True on mono, False on default.--forkedenforced (Codex retrospective 2026-05-15 item 5).Acceptance criteria (combined)
Eqlib(...)/Trlib(...)/ etc. constructed inside aTotPipelinewhosetot_is_mono()returns 1 ALSO load the mono image (not their per-module .so).TotPipeline().run_pipeline([("eq",...),("tr",...)])with mono routing populated runs("eq","tr")verify rule and PASSES (broker round-trip succeeds).libtotapi.soselected: rule NOT activated (or activated but fails cleanly with a clear "mono image required" error).Out of scope
feedback_fortran_refactor_needs_lead_signoff.md).("eq","tr")._ffi.pypath-resolution priority for non-mono users.References
python/totlib/tests/test_mono_bpsd_smoke.py(PR feat(tot+totlib): mono detection ABI + Layer-C smoke (#201 Phase 2b) #207)docs/superpowers/specs/2026-05-03-l7b-ii-bpsd-broker-coupling-design.md(§0 corrected in PR feat(tot): unified tot_graphics_stubs_mono.f90 — mono is now loadable (#201 Phase 2a) #206)docs/superpowers/specs/2026-05-18-l7b-ii-phase-2b-design.mdCodex's specific guidance for this PR chain