Skip to content

test(totlib): fp→tr equivalence test (L-7a Phase 2)#179

Merged
k-yoshimi merged 6 commits into
chore/pre-push-hook-worktree-compatfrom
feat/totlib-pipeline-phase2
Apr 28, 2026
Merged

test(totlib): fp→tr equivalence test (L-7a Phase 2)#179
k-yoshimi merged 6 commits into
chore/pre-push-hook-worktree-compatfrom
feat/totlib-pipeline-phase2

Conversation

@k-yoshimi
Copy link
Copy Markdown
Owner

@k-yoshimi k-yoshimi commented Apr 28, 2026

Summary

Phase 2 of L-7a cross-module coupling. Adds the equivalence verification: TotPipeline.run_pipeline and a hand-written fp → compute_rjt_volint → tr.set_param('PLHCD', ...) produce identical scalars at 1e-10 relative tolerance. Stacked on PR #178 (Phase 1 Foundation).

  • compute_rjt_volint(state, *, R0, a) -> float helper in python/totlib/pipeline.py (per spec §8 R2 — area integral of RJT[ns][i] MA/m² over the uniform rho-grid, returns A)
  • COUPLING_RULES[('fp','tr')] populated with one rule (callable src_state_key, dst_param='PLHCD', transform=v*1e-6). PLHCD is dimensionless per R3 — skeleton coupling, see L-7b for EXTERNAL_DRIVEN_I follow-up
  • _extract_source split so callable-rule failures (e.g. missing tr:RR) get accurate error messages instead of being routed through the string-key branch
  • test_pipeline_equiv.py (3 lib-required tests): equivalence at 1e-10, coupling-doc recording, active-drive sanity guard (compute_rjt_volint >= 1e3 A to prevent vacuous 0 == 0 passes)

CLAUDE.md non-negotiables

  • ✅ 1e-10 equivalence test PASSES (no SKIP, no relaxed tolerance, no xfail)
  • pytest.mark.skipif(not _libs_present(), ...) keyed on env build state (allowed: gates the test on the build environment, not on broken-test masking)
  • ✅ Legacy Tot class (python/totlib/totlib.py) untouched — test_totlib.py 31/31 still pass

Pre-push gate (CLAUDE.md)

  • superpowers:code-reviewer (HIGH 0, MED 0, 7 Minor — non-blocking; reviewer concluded "ready to push")
  • codex:codex-rescue independent review (APPROVE — no HIGH/MED/LOW findings)
  • REVIEW_OK_fd28c3c1... marker placed
  • ✅ No --no-verify, no pytest.mark.skip, no --ignore-glob

Test plan

  • PYTHONPATH=python pytest --forked --timeout=120 --timeout-method=signal python/totlib/tests/test_pipeline*.py python/totlib/tests/test_totlib.py102 passed in 2.82s (Phase 1 mock 64 + helpers 4 + equivalence 3 + legacy regression 31)
  • pytest python/totlib/tests/test_pipeline_equiv.py -v3 passed, 0 skipped with lib*.so present
  • CI verifies Phase 2 mock suite on Linux (no Fortran touched, no lib*.so required for the mock subset)
  • CI verifies the equivalence test on a Linux env with lib*.so built

Commits (6)

SHA Title
81fbef7e feat(totlib): add compute_rjt_volint helper
22863d78 test(totlib): clean up test_pipeline_helpers + add nr=0 case
b53e7d40 feat(totlib): populate COUPLING_RULES[('fp','tr')]
ffb6a185 fix(totlib): drop COUPLING_RULES lambda short-circuit; fix pre-existing test
e597a4bd fix(totlib): split _extract_source error paths + add lambda regression tests
fd28c3c1 test(totlib): add fp→tr equivalence test at 1e-10 tolerance

Plan deviation (documented)

tr_set_param rejects PN1/PN2/PT1/PT2 (the registry requires PN[1]/PN[2]/PT[1]/PT[2] bracket syntax — see python/trlib/trlib.py:209-230 and python/trlib/examples/quickstart.py:33-38). The equiv test splits the plan-template fixture into TR_SCALAR_PARAMS (set via set_params(**...)) and TR_ARRAY_PARAMS (set individually via set_param('PN[1]', ...)). Pattern X and Pattern Y use the same split, preserving equivalence. Plan template should be synced in a follow-up commit.

Spec / plan

  • Spec: docs/superpowers/specs/2026-04-28-l7a-cross-module-coupling-design.md §8 R2 (compute_rjt_volint formula) + R3 (PLHCD as skeleton sink, RA-not-RB choice)
  • Plan: docs/superpowers/plans/2026-04-28-l7a-cross-module-coupling.md §"Phase 2"

Depends on

Follow-ups (separate PRs)

  • PR 3 (Phase 3, MCP): run_pipeline MCP tool + force-close gate + docs (totlib README, tot_mcp README, applications.md ja/en)
  • L-7b: tr-side EXTERNAL_DRIVEN_I proper scalar param to replace the PLHCD skeleton

Notes (skeleton coupling caveat)

R3 confirmed PNBCD is not in tr/tr_param_registry.f90. L-7a uses PLHCD (a dimensionless multiplier) as the L-7a sink param — this is API plumbing, not physical fidelity. Spec §3 Non-goals + §12 follow-up "tr に proper EXTERNAL_DRIVEN_I_MA scalar 追加" track the L-7b path. The equivalence test verifies that pattern X and pattern Y compute identical PLHCD inputs and identical tr final scalars; physical fidelity is L-7b scope.

🤖 Generated with Claude Code


Note

Medium Risk
Introduces new fp→tr scalar coupling logic (including a numeric RJT integral) that affects run_pipeline behavior and error surfacing when required tr:* params are missing. Risk is mitigated by new unit tests plus lib-backed equivalence tests, but failures could change cross-module parameter injection.

Overview
Adds concrete fp→tr coupling in TotPipeline. Introduces compute_rjt_volint() to integrate fp’s RJT profile (MA/m^2 over rho) into a driven-current scalar (A), then populates COUPLING_RULES[("fp","tr")] to inject PLHCD in tr via an A→MA-scale transform.

Improves coupling error routing. Splits _extract_source handling so callable-based rules raise TotPipelineCouplingError with clearer exception type/message (e.g., missing tr:RR/tr:RA) instead of falling through to the string-key path.

Expands test coverage. Updates existing pipeline tests for the now-populated rule set, adds targeted rule-regression tests (presence, lambda behavior, missing-param error), adds standalone compute_rjt_volint unit tests, and adds a skip-gated lib-backed equivalence suite asserting hand-wired fp→tr matches run_pipeline at 1e-10 relative tolerance.

Reviewed by Cursor Bugbot for commit fd28c3c. Bugbot is set up for automated code reviews on this repo. Configure here.

@k-yoshimi
Copy link
Copy Markdown
Owner Author

@cursor review

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit fd28c3c. Configure here.

@k-yoshimi k-yoshimi changed the base branch from feat/totlib-pipeline-phase1 to chore/pre-push-hook-worktree-compat April 28, 2026 08:45
k-yoshimi and others added 6 commits April 28, 2026 18:01
Computes the fp driven-current volume integral as a scalar in Amperes.
Implementation derived from spec §8 R2 outcome. No fplib changes —
helper operates on Python-side state attributes only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drops the duplicate MagicMock and unused pytest imports inherited
from the plan template, fixes the unit label in the uniform-single-
species docstring (3.14159 MA -> 3.14159e6 A), and adds a regression
test that exercises the compute_rjt_volint nr<1 short-circuit branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Single rule wires fp's compute_rjt_volint to tr's PLHCD param (per
spec §8 R2/R3 outcomes). The src_state_key is a callable that pulls
tr:RR/tr:RA from TotPipeline._params. PLHCD is dimensionless, so this
is a skeleton coupling — L-7b adds a proper EXTERNAL_DRIVEN_I scalar.

The callable short-circuits to 0.0 when tr:RR/tr:RA are absent from
params; real pipelines always set these before run_pipeline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ng test

The fp→tr rule's src_state_key lambda was masking missing tr:RR/tr:RA
params with a silent 0.0 fallback. This violates "trust internal code"
policy — a missing required param should surface as a coupling error,
not be papered over.

Revert the lambda to the plan-exact form (raw params["tr:RR"]/["tr:RA"])
and instead update test_run_pipeline_typeerror_from_bad_kwargs_is_wrapped
to set tr:RR/tr:RA before invoking run_pipeline. That test is about
TypeError wrapping at module.run(), not coupling-rule validation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…n tests

Phase 2 introduced the first callable src_state_key in production
COUPLING_RULES. _extract_source's combined except-block was routing
the lambda's KeyError("tr:RR") through the string-key branch, which
rendered the rule.src_state_key as <function <lambda>> and claimed
the key was missing from prev_state.scalars (it's in self._params).

Split the callable and string paths so each gets an accurate error
message. Add two regression tests: one pins the fp→tr lambda's
behaviour against argument-swap regressions, the other guards the
new error-routing path by asserting "tr:RR" appears in the surfaced
message.

Also refresh the stale registry header comment ("filled in Phase 2"
was true at write-time but is wrong now that the rule is populated).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Compares pattern X (hand-written Fplib + compute_rjt_volint + Trlib
+ tr.set_param('PLHCD', ...)) vs pattern Y (TotPipeline.run_pipeline).
Per CLAUDE.md, equivalence tests at 1e-10 must pass — no SKIP allowed.
Uses E0=0.001 active-drive fixture (R3 outcome) to ensure the integral
is non-trivial (>= 1e3 A sanity guard). Requires libfpapi.so + libtrapi.so.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@k-yoshimi k-yoshimi force-pushed the feat/totlib-pipeline-phase2 branch from fd28c3c to d35f3cf Compare April 28, 2026 09:02
@k-yoshimi k-yoshimi merged commit 05d7ce9 into chore/pre-push-hook-worktree-compat Apr 28, 2026
k-yoshimi added a commit that referenced this pull request Apr 28, 2026
… gate

Two doc-only follow-ups discovered during L-7a Phase 2 (PR #179):

1. docs/superpowers/plans/2026-04-28-l7a-cross-module-coupling.md
   - Drop duplicate `from unittest.mock import MagicMock` import and the
     unused `import pytest` from the test_pipeline_helpers.py snippet
     (lines 1701-1704).
   - Fix the unit label in the uniform-single-species docstring
     (~3.14159 MA → ~3.14159e6 A; the function returns Amperes).
   - Replace the Phase 2 equiv-test fixture's PN1/PN2/PT1/PT2 keys
     with PN[1]/PN[2]/PT[1]/PT[2] bracket syntax (tr_set_param rejects
     the underscore-style keys per python/trlib/trlib.py and
     python/trlib/examples/quickstart.py). Split TR_PARAMS into
     TR_SCALAR_PARAMS (set_params) and TR_ARRAY_PARAMS (set_param).
   - Drop the now-incompatible pipeline_params dict-merge pattern in
     _through_pipeline; use the same scalar/array split.

   These are the four bugs surfaced by the Phase 2 code-quality review
   (PR #179 Minor M2). The actual Phase 2 code already has the correct
   forms — this commit brings the plan template back in sync so future
   re-executions don't re-introduce the bugs.

2. CLAUDE.md "Pre-push gate"
   - Add a 3rd numbered step requiring an independent codex:codex-rescue
     review alongside the in-house code-reviewer. Phase 1 and Phase 2
     both saw cases where one reviewer caught an issue the other missed
     (Phase 1: Codex flagged a narrow except-tuple letting TypeError
     escape unwrapped; Phase 2: in-house reviewer caught the
     _extract_source error-routing bug Codex didn't surface).
   - Renumber the marker step from 3 to 4. No other step references
     exist in CLAUDE.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
k-yoshimi added a commit that referenced this pull request Apr 28, 2026
… gate (#180)

Two doc-only follow-ups discovered during L-7a Phase 2 (PR #179):

1. docs/superpowers/plans/2026-04-28-l7a-cross-module-coupling.md
   - Drop duplicate `from unittest.mock import MagicMock` import and the
     unused `import pytest` from the test_pipeline_helpers.py snippet
     (lines 1701-1704).
   - Fix the unit label in the uniform-single-species docstring
     (~3.14159 MA → ~3.14159e6 A; the function returns Amperes).
   - Replace the Phase 2 equiv-test fixture's PN1/PN2/PT1/PT2 keys
     with PN[1]/PN[2]/PT[1]/PT[2] bracket syntax (tr_set_param rejects
     the underscore-style keys per python/trlib/trlib.py and
     python/trlib/examples/quickstart.py). Split TR_PARAMS into
     TR_SCALAR_PARAMS (set_params) and TR_ARRAY_PARAMS (set_param).
   - Drop the now-incompatible pipeline_params dict-merge pattern in
     _through_pipeline; use the same scalar/array split.

   These are the four bugs surfaced by the Phase 2 code-quality review
   (PR #179 Minor M2). The actual Phase 2 code already has the correct
   forms — this commit brings the plan template back in sync so future
   re-executions don't re-introduce the bugs.

2. CLAUDE.md "Pre-push gate"
   - Add a 3rd numbered step requiring an independent codex:codex-rescue
     review alongside the in-house code-reviewer. Phase 1 and Phase 2
     both saw cases where one reviewer caught an issue the other missed
     (Phase 1: Codex flagged a narrow except-tuple letting TypeError
     escape unwrapped; Phase 2: in-house reviewer caught the
     _extract_source error-routing bug Codex didn't surface).
   - Renumber the marker step from 3 to 4. No other step references
     exist in CLAUDE.md.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
k-yoshimi added a commit that referenced this pull request Apr 28, 2026
Summary of the L-7a series and ancillary doc cleanup that landed
during this session:

- #178 (5a79b5d): Phase 1 — TotPipeline foundation + Bugbot 7-item
  fixes (LOW 3 + LOW 3 + MED 1)
- #179 (05d7ce9): Phase 2 — compute_rjt_volint helper + populated
  COUPLING_RULES + 1e-10 equivalence test (lib*.so)
- #181 (eee67a7): Phase 3 — run_pipeline MCP tool + 4 docs
  (totlib README, tot_mcp README, applications.md ja+en)
- #180 (5b99421): plan template sync + CLAUDE.md Codex review step
- #182 (caa57ad): portal:common-architecture {ref} cleanup
  (30 occurrences → relative-path Markdown links + narrow
  suppress_warnings on module conf files)

The L-7a skeleton coupling (fp driven current → tr.PLHCD via
compute_rjt_volint) is verified end-to-end at 1e-10 tolerance and
exposed as the run_pipeline MCP tool. L-7b (profile coupling +
EXTERNAL_DRIVEN_I scalar) is the next milestone and is documented
as a future scope item in this handoff.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
k-yoshimi added a commit that referenced this pull request Apr 28, 2026
…rge)

Continuation of handoff-2026-04-28-night.md. Documents the L-6 plan-
gaps closure work that landed as PR #183 (squash commit adf7e64):

- README outdated cleanup (rc=4 NOT_IMPL claims removed across 4
  README sections + module/wrapper docstrings + __init__ example)
- Layer 3 prefix coverage gap closed via new
  python/totlib/tests/test_class_full.py (7 tests: ti/fp/wr/wrx
  positive set_param round-trips + 6-prefix sanity test +
  context-manager exception-propagation tests)

Layer 1 (test_equivalence.py 2 SKIPs) and Layer 2 (test_full_cycle.c,
test_negative.c) deferred to a follow-up — both blocked on the same
.mod-cascade issue in `make -C tot tot_api_check_all` (tot → tr
libtr2.a → eq/equnit.mod chain). The handoff documents the suspected
unblock procedure (clean .mod tree + dependency-order rebuild) as
the highest-priority next-session task.

Important correction recorded: my initial framing to the user that
"L-6 fan-out is undone" was wrong — Fortran-side fan-out has been
live for some time, only the README was stale. The night handoff
inherited this misframing and is corrected here.

Session totals: 6 PRs merged today (#178/#179/#180/#181/#182/#183),
all on origin/chore/pre-push-hook-worktree-compat.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@k-yoshimi k-yoshimi deleted the feat/totlib-pipeline-phase2 branch May 27, 2026 23:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant