Skip to content

Fix three broadcast defects found by post-merge audit; harden the generator#1581

Open
sbryngelson wants to merge 4 commits into
MFlowCode:masterfrom
sbryngelson:fix-broadcast-audit
Open

Fix three broadcast defects found by post-merge audit; harden the generator#1581
sbryngelson wants to merge 4 commits into
MFlowCode:masterfrom
sbryngelson:fix-broadcast-audit

Conversation

@sbryngelson

Copy link
Copy Markdown
Member

Post-merge audit of the #1550-#1572 refactoring series: four independent verification passes over merged master (squash-tree integrity, end-to-end NFC equivalence, first-principles broadcast re-derivation, hostile fresh-eyes review of the riskiest artifacts). Zero regressions from the series itself; the audit instead surfaced three pre-existing defects and two hardening gaps, all fixed here.

Fixes #1579 (hcid integer broadcast as mpi_p in pre_process — moved to the MPI_INTEGER group).
Fixes #1580 (post_process never broadcasts recon_type/igr_order consumed by the all-ranks domain decomposition; igr_order additionally gains its missing default — found independently by two audit passes).

Hardening (second commit): _mpi_type_for now consults storage_precision (a future real(stp) namelist parameter would have broadcast with mpi_p — silently wrong under --mixed), and an unregistered namelist entry now raises instead of silently skipping (the missing-broadcast class the generator exists to prevent), with the one verified-dead exception (post's G) allowlisted explicitly. The four surviving _POST_BCAST_EXCLUDE entries were each verified benign with consumer-level evidence during the audit.

Full golden suite (4-way sharded) running on the fix commit; toolchain pytest green; precheck green.

hcid (integer) was broadcast with mpi_p in pre_process's patch loop - the same type-mismatch class as the bc%beg/end fix, moved to the MPI_INTEGER group. post_process never broadcast recon_type and igr_order despite both being consumed on all ranks by s_mpi_decompose_computational_domain (rank-divergent decomposition for MUSCL/IGR post runs); removed from _POST_BCAST_EXCLUDE, and igr_order gains the missing default alongside its case-opt siblings. All pre-existing on master.
…try gaps

Audit follow-ups: _mpi_type_for now consults storage_precision (a future real(stp) namelist parameter would have broadcast with mpi_p - silently wrong under --mixed), and an unregistered namelist entry now raises instead of silently skipping (the missing-broadcast class this generator exists to prevent), with an explicit allowlist for post's dead G.
Copilot AI review requested due to automatic review settings June 12, 2026 04:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Fixes three pre-existing MPI broadcast defects discovered during post-merge audit and hardens the Fortran broadcast generator to prevent silent omissions/mixed-precision mismatches.

Changes:

  • Correct hcid broadcast type in pre-process (MPI integer broadcast instead of real/mpi_p).
  • Add missing default initialization for igr_order.
  • Harden generator: _mpi_type_for now accounts for storage_precision, and missing-registry namelist entries now raise unless explicitly allowlisted.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
toolchain/mfc/params/generators/fortran_gen.py Adds storage-precision-aware MPI type mapping and prevents silent skips for unregistered namelist variables (with an explicit allowlist).
src/pre_process/m_mpi_proxy.fpp Broadcasts hcid with MPI_INTEGER and removes it from the mpi_p real broadcast list.
src/common/m_global_parameters_common.fpp Initializes igr_order to a default value to avoid undefined behavior.

continue # no registry entry — skip (e.g. 'G' in post is rank-0-only)
if name in _NO_REGISTRY_ALLOWLIST:
continue
raise ValueError(f"namelist var {name!r} ({target}) has no registry entry - " "register it or allowlist it; a silent skip here means a " "silently missing broadcast")
@sbryngelson

Copy link
Copy Markdown
Member Author

Addressed - the message is now one explicit multi-line f-string (the implicit concatenation was a formatter artifact). Thanks.

@sbryngelson

Copy link
Copy Markdown
Member Author

Follow-up hardening on the generator/manual-residue boundary, from the other side: a new precheck/CI source-lint rule (check_manual_registry_bcasts in toolchain/mfc/lint_source.py, commit f2e661e on fix-broadcast-audit) now forbids hand-written MPI_BCASTs of registry-bound namelist scalars in the three m_mpi_proxy.fpp files. It extracts every broadcast's first-argument root — direct calls and Fypp #:for loop lists, including &-continuations and nested loops — and checks it against the per-target auto-broadcast set derived from the generator's own _classify_scalar_vars, so the lint and generated_bcast.fpp can never disagree. Struct members and computed variables (m_glb, cfl_dt, bc_io, ...) remain legitimate manual residue and are skipped. Combined with the generator's existing unregistered-namelist error, the boundary is now policed from both directions: the current tree scans clean, and any future duplicate broadcast or generator bypass fails precheck.

@github-actions

Copy link
Copy Markdown

Claude Code Review

Head SHA: f2e661e

Files changed:

  • 5
  • src/common/m_global_parameters_common.fpp
  • src/pre_process/m_mpi_proxy.fpp
  • toolchain/mfc/lint_source.py
  • toolchain/mfc/params/generators/fortran_gen.py
  • toolchain/mfc/test_lint_source.py

Findings

Precision bug: stp scalar params land in real_vars and are broadcast with hardcoded mpi_p

toolchain/mfc/params/generators/fortran_gen.py

The PR correctly teaches _mpi_type_for to return "mpi_io_p" for storage_precision=True params, and updates the call site in _classify_scalar_vars:

# changed line
mpi_type = _mpi_type_for(pdef.param_type, getattr(pdef, "storage_precision", False))
if mpi_type == "MPI_INTEGER":
    int_vars.append(name)
elif mpi_type == "MPI_LOGICAL":
    log_vars.append(name)
else:
    real_vars.append(name)   # ← mpi_io_p params fall here too

The unchanged else: clause buckets mpi_io_p params into real_vars. Downstream in generate_bcast_fpp (unchanged line ~456):

_emit_bcast_group(lines, real_vars, "mpi_p")   # ← hardcoded mpi_p for the whole list

Any namelist-bound scalar with storage_precision=True will be broadcast with mpi_p instead of mpi_io_p. Under --mixed precision (wp=double, stp=half) this is a silent type mismatch: CLAUDE.md requires mpi_p ↔ wp, mpi_io_p ↔ stp.

The array-dim path is fixed correctly (_emit_fortran_array_dims uses the returned mpi_type directly), so only the scalar path has this gap.

Fix: split real_vars into wp_vars/stp_vars by testing mpi_type == "mpi_io_p", then emit a separate _emit_bcast_group(lines, stp_vars, "mpi_io_p") in generate_bcast_fpp.

@codecov

codecov Bot commented Jun 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.94%. Comparing base (ac5774e) to head (f2e661e).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1581   +/-   ##
=======================================
  Coverage   60.94%   60.94%           
=======================================
  Files          82       82           
  Lines       19922    19923    +1     
  Branches     2924     2924           
=======================================
+ Hits        12141    12142    +1     
  Misses       5805     5805           
  Partials     1976     1976           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants