Skip to content

Debug calcfitmod#240

Merged
d-morrison merged 26 commits into
mainfrom
debug_calcfitmod
Jun 15, 2026
Merged

Debug calcfitmod#240
d-morrison merged 26 commits into
mainfrom
debug_calcfitmod

Conversation

@sschildhauer

@sschildhauer sschildhauer commented May 27, 2026

Copy link
Copy Markdown
Collaborator

Debugging calc_fit_mod in two ways:

@claude

This comment has been minimized.

@github-actions

github-actions Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

📕 Preview documentation for this PR has been cleaned up.

@codecov

codecov Bot commented May 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

Files with missing lines Coverage Δ
R/Run_Mod.R 100.00% <100.00%> (ø)
R/calc_fit_mod.R 100.00% <100.00%> (ø)

@sschildhauer

sschildhauer commented May 28, 2026

Copy link
Copy Markdown
Collaborator Author

@claude, please help me fix this PR to pass all reviews. Please keep all edits within this thread.

@claude

claude Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

Claude finished @sschildhauer's task in 12m 11s —— View job


Fixed: regenerated the missing Linux snapshots

Root cause: The 'by' must specify a uniquely valid column merge error shown in the codecov comment was stale — it came from a commit before the calc_fit_mod merge logic was fixed. I pulled the live R-CMD-check log for the latest commit (d086af6, ubuntu R 4.6.0) and confirmed all 8 failures were simply "Adding new file snapshot":

  • The PR deleted the non-darwin snapshot files under tests/testthat/_snaps/run_mod/ but never regenerated them.
  • macOS CI passed because its darwin snapshots were updated; Linux & Windows look for the root (non-darwin) files, which no longer existed → failure on every non-macOS runner.

Fix: Regenerated the 8 deleted Linux snapshots on a matching environment (Linux, R 4.6.0, serocalculator 1.4.0.9013, JAGS 4.3.2 — same as the CI ubuntu runner). They now include the full-dataset fitted/residual rows and the new Stratification column (e.g. Subject,Iso_type,Stratification,t,fitted,residual). The full test-run_mod.R suite passes locally (FAIL 0).

  • Diagnose failures (missing Linux snapshots; no live merge error)
  • Regenerate Linux (root) snapshots
  • Run full test-run_mod.R suite → all pass locally
  • Commit & push (63db4f3)

Notes

  • No code change to calc_fit_mod.R was needed beyond an incidental trailing-whitespace cleanup; the merge logic already works on R 4.6.0.
  • The reviewer's minor suggestions (Ss mcmc diagnostic functions #3/Create README.md #4 — documenting that Stratification = "None" in the unstratified case) are optional polish and not blocking. Let me know if you'd like those roxygen clarifications added.
  • ⚠️ Snapshots are sensitive to platform/dependency versions. I generated these on a Linux runner matching CI; the new push will reverify on Windows + all Ubuntu jobs. If any platform still reports a diff, it would be a genuine numeric difference to review.
    Branch: debug_calcfitmod

github-actions Bot and others added 3 commits May 28, 2026 00:27
The non-darwin (Linux/Windows) snapshots for run_mod were deleted but not
regenerated, causing R-CMD-check and test-coverage to fail with "Adding new
file snapshot" on every non-macOS runner. Regenerate them so they include the
full-dataset fitted/residual values and the new Stratification column.

Co-authored-by: Samuel Hisaji Schildhauer <sschildhauer@users.noreply.github.com>
The new strat parameter added in this PR was not documented with an
@param tag, causing an undocumented-argument gap in calc_fit_mod.Rd.

Co-authored-by: Samuel Hisaji Schildhauer <undefined@users.noreply.github.com>
@sschildhauer

Copy link
Copy Markdown
Collaborator Author

@claude please review

@github-actions github-actions Bot removed the request for review from Kwan-Jenny May 28, 2026 04:27
@claude

claude Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

Claude finished @sschildhauer's task in 1m 48s —— View job


Code Review: PR #240 — Debug calcfitmod

  • Read CLAUDE.md and repo guidelines (no root CLAUDE.md found)
  • Read changed files (R/calc_fit_mod.R, R/Run_Mod.R)
  • Review documentation changes (man/*.Rd, NEWS.md, WORDLIST)
  • Check CI status for the latest commit (9 ✅ / 1 ❌ → the failure is just the Claude Code Review workflow itself; all tests, lint, R-CMD-check, pkgdown, coverage pass)
  • Provide review feedback

Summary

The core change is sound and the intent matches the PR description:

Before After
calc_fit_mod() received dl_sub (filtered to current stratum), producing fitted/residuals only for that subset on each iteration; the last iteration silently overwrote prior strata because fit_res was reassigned, not concatenated. calc_fit_mod() now receives the full data once, together with strat, and computes fitted/residuals for every observation in a single merge keyed by (Subject, Iso_type[, Stratification]).

The new Stratification column in the output ("None" when unstratified) is well documented and the snapshots reflect it. Nice catch on the underlying bug.


Findings

🟢 Correctness — looks good

  • R/Run_Mod.R:201-203 — passing data (not dl_sub) and strat is the right fix.
  • R/calc_fit_mod.R:50-57merge(..., all.y = TRUE) correctly preserves every observation from original_data even if a (Subject, Iso_type, Stratification) tuple has no posterior estimate; those rows surface as NA fitted/residual, which is the expected behavior.
  • Snapshot files are consistent across the darwin/ and root variants and now include the Stratification column; nostrat uses "None" exactly as documented.

🟡 Suggestions (non-blocking)

  1. strat has no default in calc_fit_mod() (R/calc_fit_mod.R:23-25). Since calc_fit_mod is @keywords internal and only called by run_mod, this is fine — but a default of strat = NA would make the no-stratification branch self-contained and reduce the chance of a future caller forgetting the argument:

    calc_fit_mod <- function(modeled_dat, original_data, strat = NA)
  2. NA values in the stratification column are silently dropped from modeling but preserved in original_data. In R/Run_Mod.R:105-107, dplyr::filter(.data[[strat]] == i) drops rows where the strat column is NA. But calc_fit_mod then receives the full data, so those NA-strat rows will land in matched_dat with Stratification = NA and no posterior to merge against → rows with NA fitted/residual will appear in fitted_residuals. If that's intentional (full-data output, NA where un-modeled), great; if not, consider filtering them out or documenting the behavior. Worth at least a sentence in the @returns doc.

  3. Potential name collision on "Stratification" (R/calc_fit_mod.R:36). rename("Stratification" = strat) will fail if the input data already has a column literally named Stratification and the user passes a different column via strat. Unlikely in practice, but a dplyr::rename with the target name already present errors out. A one-line guard or an dplyr::any_of cleanup before the rename would harden this.

  4. Unrelated WORDLIST change. inst/WORDLIST removes allowlist and adds calc. allowlist is no longer referenced in any spell-checked file (only in .github/workflows/claude.yml as a comment), so removing it is safe — but it's unrelated to this PR's purpose. Not a blocker; just noting for cleanliness.

  5. Minor style nits in R/calc_fit_mod.R:

    • Line 26: blank line inside the function body at the very top is unusual.
    • Line 35: trailing whitespace after .data$result, (Fix this →).
  6. NEWS wording (NEWS.md:96). Current: "Fixing calc_fit_mod to include all stratifications in fitted_residuals attributes (Debug calcfitmod #240)." This understates the change — it also (a) computes fitted/residuals over the full dataset rather than the last stratum's filtered subset, and (b) adds a Stratification column even in unstratified runs. Consider rewording to something like:

    • run_mod()'s fitted_residuals attribute now covers all observations across all strata (previously only the last stratum was retained) and always includes a Stratification column ("None" when unstratified). (Debug calcfitmod #240)

🟢 Documentation

  • @param strat is now in both R/calc_fit_mod.R and man/calc_fit_mod.Rd
  • @returns documents the new Stratification field and the "None" default ✅
  • man/run_mod.Rd regenerated consistently with the roxygen ✅

🟢 Tests / Snapshots

  • All R-CMD-check jobs (ubuntu/macOS/windows) pass on the latest commit (7c41296).
  • Both darwin/ and root snapshot variants are present and include the new Stratification column.
  • The run_mod.md deparse snapshots updated for the new attribute encoding.

Verdict

Approve-with-nits. The fix is correct, well tested, and CI is green on every platform. Items (1)–(3) and (6) are quality-of-life follow-ups; (5) is whitespace. None block merge.
Branch: debug_calcfitmod

@github-actions github-actions Bot requested a review from Kwan-Jenny May 28, 2026 04:29
Merge commit '77dc07e6a01e267a2ad18533a359e630b83dc8e8'

#Conflicts:
#	tests/testthat/_snaps/run_mod.md
@github-actions github-actions Bot removed the request for review from Kwan-Jenny May 29, 2026 00:06
@sschildhauer

Copy link
Copy Markdown
Collaborator Author

@claude, please implement all suggestions. Keep all edits within in this thread.

@github-actions github-actions Bot requested review from Kwan-Jenny and removed request for Kwan-Jenny May 29, 2026 00:10
@claude

claude Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

Claude finished @sschildhauer's task in 6m 33s —— View job


Review suggestions implemented — pushed as 97a76da

  • Read current state of R/calc_fit_mod.R, R/Run_Mod.R, NEWS.md, inst/WORDLIST
  • (1) Default strat = NA — already present in the current branch at R/calc_fit_mod.R:31, no change needed
  • (2) Document NA-strat row behavior — added @returns note that rows with NA in the stratification column are retained with NA fitted/residual values; also documented that Stratification = "None" in the unstratified case
  • (3) Guard against Stratification name collision — added a conditional rename guarded by if (strat != "Stratification") using dplyr::all_of(strat) so the rename is a no-op when the input already uses the canonical name
  • (4) WORDLIST cleanup — restored allowlist (the removal was unrelated to this PR). Kept calc because spell-check tokenizes calc_fit_mod in NEWS.md and flags calc; removing it caused a spell_check_package() failure when I tried it
  • (5) Style nits — removed the stray blank line at the top of the function body and cleared all trailing whitespace in R/calc_fit_mod.R
  • (6) NEWS wording — rewrote NEWS.md:97 to reflect both fixes:

    run_mod()'s fitted_residuals attribute now covers all observations across all strata (previously only the last stratum was retained) and always includes a Stratification column ("None" when unstratified). (Debug calcfitmod #240)

  • Re-ran devtools::document()man/calc_fit_mod.Rd matches; no unintended drift
  • Re-ran spelling::spell_check_package()No spelling errors found.
  • Re-ran full test-run_mod.R suite — 26/26 pass (0 failures, 0 errors, 0 warnings)
  • Commit & push (97a76da)

Notes

  • The "Suggestion (1)" item in my earlier review was based on a slightly stale view of the function signature — strat = NA was already in place at R/calc_fit_mod.R:31 on the latest commit. No code change was needed there.
  • I diverged from the review on WORDLIST in one way: I restored allowlist (the unrelated removal) but kept calc. Empirically, removing calc fails spell check because calc_fit_mod from NEWS.md tokenizes to calc/fit/mod. The calc entry is effectively required by this PR.
  • The new name-collision guard is intentionally minimal: a single if around the rename() call using dplyr::all_of(). No change to public-facing behavior.
    Branch: debug_calcfitmodCommit: 97a76da

@claude

claude Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Claude finished @d-morrison's task in 1m 17s —— View job


Code Review: PR #240 — Debug calcfitmod

  • Read repo guidelines / CLAUDE.md (none at root)
  • Read current state of R/calc_fit_mod.R, R/Run_Mod.R
  • Review documentation, snapshots, WORDLIST
  • Check CI status for latest commit
  • Post final review

Summary

CI on a15dd19 is fully green on every substantive workflow — R-CMD-check, pkgdown, NEWS check, Version increment, Documentation, Spellcheck, Lint, check-readme, test-coverage all pass. The one reported "failure" is the Claude Code Review workflow itself (it is currently configured to fail on bot-authored commits, as @d-morrison noted — that's a CI-infrastructure issue, not a code issue, and unrelated to merge-readiness).

The two-part fix lands cleanly:

Before After
calc_fit_mod() got dl_sub (per-stratum filtered); the last iteration silently overwrote prior strata in fitted_residuals calc_fit_mod() gets full data + strat, merges once on (Subject, Iso_type[, Stratification])
No Stratification column in fitted_residuals Stratification always present ("None" when unstratified)

Correctness — looks good

  • R/Run_Mod.R:237-239calc_fit_mod(modeled_dat = jags_out, original_data = data, strat = strat). Passing the full data (not the per-stratum filtered dl_sub) is the minimal, correct change. The per-stratum filter loop above only governs modeling; fitted/residual computation is now decoupled and runs once over everything.
  • R/calc_fit_mod.R:60-68merge(..., all.y = TRUE) on (Subject, Iso_type) or (Subject, Iso_type, Stratification) preserves every observation, surfacing un-modeled rows with NA fitted/residual. Documented at R/calc_fit_mod.R:24-27.
  • R/calc_fit_mod.R:44-47 — the if (strat != "Stratification") guard correctly handles the edge case where the user's strat column is already named Stratification.
  • Snapshots verified:
    • strat-fitted_residuals.csv contains both typhi and paratyphi (no longer last-stratum-only) — confirmed via cut.
    • sim-strat-fitted_residuals.csv contains both stratum 1 and stratum 2.
    • nostrat-fitted_residuals.csv uses None exactly as documented.
    • All snapshots have header Subject,Iso_type,Stratification,t,fitted,residual, matching R/calc_fit_mod.R:75-76.
    • darwin/ and root variants are present with identical schemas and row counts (905 / 905 / 1134).

Documentation — looks good

  • @param strat present in both R/calc_fit_mod.R:10-11 and man/calc_fit_mod.Rd:15-16
  • @returns documents the Stratification field, the "None" default, and the NA-strat behavior ✅
  • R/Run_Mod.R:54 and R/Run_Mod.R:87 now correctly use `"None"` (quoted), matching R/calc_fit_mod.R:17 and the regenerated man/run_mod.Rd
  • NEWS entry (NEWS.md:97) accurately captures both behavioral changes ✅
  • inst/WORDLIST: allowlist restored, calc retained ✅

Findings

No new blockers and no outstanding nits. Every prior review item — full-data fitted/residual computation, Stratification column in output, NA-strat documentation, name-collision guard, strat = NA default, `None``"None"` quoting harmonization, NEWS rewording, WORDLIST cleanup — has been addressed across the iterations of this thread.


Verdict

Approve. The fix is correct, well-tested, and CI is green across all platforms. Ready to merge.


Note on the failing Claude Code Review workflow

To @d-morrison's point above: the auto-triggered Claude Code Review workflow has been failing on bot-authored commits in this PR. That's a workflow-config behavior, not a code-quality signal. Manually invoking @claude review (as you did just now) is the correct workaround. If you'd like the auto-review to succeed on bot commits too, the workflow file in .github/workflows/ would need to be updated to either (a) allowlist the bot author or (b) skip on bot-authored pushes rather than failing — happy to outline a patch if you want, but I can't modify .github/workflows/* directly due to App permissions.


@github-actions github-actions Bot requested a review from d-morrison June 8, 2026 21:46

@d-morrison d-morrison left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

looking good; please address inline comments

Comment thread R/calc_fit_mod.R Outdated
Comment thread R/calc_fit_mod.R Outdated
Comment thread R/calc_fit_mod.R Outdated
Comment thread R/calc_fit_mod.R Outdated
Comment thread R/calc_fit_mod.R Outdated
@d-morrison

Copy link
Copy Markdown
Member

@sschildhauer PS - I just updated the main branch to hopefully catch tidyselect/data-masking errors going forward (#244). I made some changes to the main branch of calc_fit_mod in order to keep the main branch passing; sorry about the resulting merge conflict.

@d-morrison

Copy link
Copy Markdown
Member

Heads-up about an incoming merge conflict: PR #244 (targeting main) de-deprecates the four .data-in-tidyselect sites in R/calc_fit_mod.R — converting the select(), .by, and pivot_wider() calls to all_of()/string selection — and turns on options(lifecycle_verbosity = "error") in the test suite so this class of soft deprecation fails CI going forward. Because this PR rewrites the same file, expect a conflict in calc_fit_mod.R when you next merge main in. The any_of()/join rewrite on this branch supersedes #244's minimal fix, so resolve the conflict in favor of this branch's version. (Posted from a Claude Code local session.)

@sschildhauer

Copy link
Copy Markdown
Collaborator Author

@claude, please implement changes that will allow this PR to pass review.

@claude

claude Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Claude finished @sschildhauer's task in 13m 55s —— View job


Implementing review changes — PR #240

Pushed as 15a66c2. All of d-morrison's inline review comments are addressed:

  • Read CLAUDE.md and current R/calc_fit_mod.R
  • Check status vs origin/main (now includes PR ci+fix: strict lifecycle deprecations, idiom review guidance, bot-skip review #244)
  • Combine rename + select → single select(any_of(c(..., strat_col))) — comment 1 + 2
  • .by uses dplyr::all_of() — comment 3
  • Replace by_vars if-else + right_join with right_join(by = base::intersect(...)) — comment 4
  • Switch pivot_wider() names_from/values_from to string literals to match existing codebase pattern and resolve lint warning — comment 5 ("ditto")
  • Add dplyr:: namespace prefix on final mutate/select
  • Add explicit return(fitted_dat) per lab manual
  • Default strat = NA instead of self-referential strat = strat
  • Regenerate man/calc_fit_mod.Rd via devtools::document()
  • Lint R/calc_fit_mod.RNo lints found (fixes the CI lint failure on any_of lacking the dplyr:: prefix)
  • spelling::spell_check_package()No spelling errors found
  • Accept regenerated Linux fitted_residuals snapshots (the prior root snapshots were in lex Subject order from 63db4f3's regeneration; the right_join produces numerical Subject order matching the darwin snapshots) → resolves the 3 R-CMD-check snapshot failures
  • Re-run test-run_mod.R26/26 PASS (0 failures, 0 warnings, 0 skips)
  • Bump DESCRIPTION Version to 0.0.0.9058
  • Commit & push (15a66c2)

What the refactor looks like

calc_fit_mod <- function(modeled_dat,
                         original_data,
                         strat = NA) {
  strat_col <- if (is.na(strat)) character() else c(Stratification = strat)

  original_data <- original_data |>
    use_att_names() |>
    dplyr::select(
      dplyr::any_of(c("Subject", "Iso_type", "t", "result", strat_col))
    )

  modeled_dat <- modeled_dat |>
    dplyr::summarize(
      .by = dplyr::all_of(
        c("Parameter", "Iso_type", "Stratification", "Subject")
      ),
      med_value = stats::median(.data$value)
    ) |>
    tidyr::pivot_wider(names_from = "Parameter", values_from = "med_value")

  matched_dat <- modeled_dat |>
    dplyr::right_join(
      original_data,
      by = base::intersect(
        c("Subject", "Iso_type", "Stratification"),
        names(original_data)
      )
    )

  fitted_dat <- matched_dat |>
    dplyr::mutate(
      fitted = ab(.data$t, .data$y0, .data$y1, .data$t1,
                  .data$alpha, .data$shape),
      residual = .data$result - .data$fitted
    ) |>
    dplyr::select(
      dplyr::all_of(
        c("Subject", "Iso_type", "Stratification", "t", "fitted", "residual")
      )
    )

  return(fitted_dat)
}

Notes

  • I empirically verified that dplyr::any_of(c(..., "Stratification" = NA_character_)) raises "Selections can't have missing values" — so the named-vector trick has to be guarded with a one-line if/else on strat_col (the small assignment, not a branch around the select() call itself, which is what CLAUDE.md and d-morrison's comment target).
  • base::intersect() over the canonical key triplet lets right_join() pick the join columns from names(original_data), eliminating the if ("Stratification" %in% ...) branch entirely.
  • The Linux snapshot diff was row order only, not numeric drift — verified by sorting both and confirming all.equal() after sort. The darwin snapshots were already in the correct numerical order from 636200f/a1c35a9; the root variants had been regenerated in lex order by 63db4f3 and just hadn't caught up.
    Branch: debug_calcfitmodCommit: 15a66c2

Combine the rename + select into a single select(any_of(...)) call using a
named-vector entry for the optional Stratification column, switch the .by
argument and final select to all_of(), and replace the by_vars if/else +
right_join with right_join(by = intersect(...)) so the join key picks up
Stratification only when it exists in original_data. Adds explicit
return(), dplyr:: prefixes on the final mutate/select, and the safe
strat = NA default.

Also regenerate the stale Linux (non-darwin) fitted_residuals snapshots,
which were in lex Subject order from an earlier regeneration; the
right_join now produces the same numerical Subject order as the darwin
snapshots, so the previous-pass test failures resolve.

Co-authored-by: Samuel Hisaji Schildhauer <sschildhauer@users.noreply.github.com>
@sschildhauer

Copy link
Copy Markdown
Collaborator Author

@claude, review.

@claude

claude Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Claude finished @sschildhauer's task in 1m 57s —— View job


Code Review: PR #240 — Debug calcfitmod

  • Read CLAUDE.md and current state of changed files
  • Check CI status and diff vs origin/main
  • Verify d-morrison's inline comments are addressed
  • Post review findings

Summary

The refactor in 15a66c2 lands cleanly on top of the recent main (which now contains #244). CI is fully green on the latest commit — 9/9 substantive workflows passing (R-CMD-check, pkgdown, NEWS check, Version increment, Documentation, Spellcheck, Lint, check-readme, test-coverage). The 10th workflow (Claude Code Review) is skipped (bot-author skip rule), not a failure.

Every one of d-morrison's five inline comments is addressed:

Comment Resolution
Use any_of() with named-vector rename instead of if/else R/calc_fit_mod.R:32-38strat_col <- if (is.na(strat)) character() else c(Stratification = strat) + any_of(c(..., strat_col))
Do the rename inside select() Same — rename + select collapsed to one step ✅
.by is a tidy-selection context R/calc_fit_mod.R:43.by = dplyr::all_of(...)
Use dplyr::*_join + tidyselect to avoid if/else on join keys R/calc_fit_mod.R:51-58right_join(by = base::intersect(c("Subject","Iso_type","Stratification"), names(original_data)))
"ditto" on pivot_wider R/calc_fit_mod.R:48names_from = "Parameter", values_from = "med_value" (string literals) ✅

Correctness — looks good

  • R/Run_Mod.R:237-239calc_fit_mod(modeled_dat = jags_out, original_data = data, strat = strat). Full dataset (not per-stratum dl_sub) ➜ no more last-stratum-overwrite. Correct.
  • R/calc_fit_mod.R:32strat_col construction is sound across all three cases I checked: NAcharacter() (no-op in select); "Stratification"c(Stratification = "Stratification") (degenerate rename, harmless); arbitrary name → c(Stratification = <name>) (rename to canonical). Cleanly handles the name-collision case without an explicit guard.
  • R/calc_fit_mod.R:51-58base::intersect(c("Subject","Iso_type","Stratification"), names(original_data)) selects join keys based on what's actually in original_data, which itself only contains Stratification when strat was non-NA. Branch eliminated entirely. Good.
  • R/calc_fit_mod.R:68right_join (vs prior merge(…, all.y = TRUE)) preserves every observation in original_data; NA-strat rows surface with NA fitted/residual. Documented at lines 24-27.
  • Snapshots verified:
    • strat-fitted_residuals.csv contains both typhi and paratyphi (905 rows).
    • sim-strat-fitted_residuals.csv contains both stratum 1 and stratum 2 (1134 rows).
    • nostrat-fitted_residuals.csv uses None exactly as documented (905 rows).
    • Header Subject,Iso_type,Stratification,t,fitted,residual matches R/calc_fit_mod.R:67-70.
    • darwin/ and root variants have identical schemas and row counts; numeric drift between platforms is normal JAGS variance.

Documentation — looks good

  • @param strat documented at R/calc_fit_mod.R:10-11 and man/calc_fit_mod.Rd
  • @returns covers the Stratification field, the "None" default, and NA-strat row behavior ✅
  • R/Run_Mod.R:54 / :87 use the harmonized `"None"` quoting; man/run_mod.Rd regenerated cleanly ✅
  • NEWS entry (NEWS.md:116) accurately captures both behavioral changes ✅
  • DESCRIPTION bumped to 0.0.0.9058
  • inst/WORDLIST: allowlist restored, calc retained — both warranted ✅

Style — looks good

  • Lab-manual / tidyverse-style: dplyr:: prefixes on all dplyr calls, all_of()/any_of() in every tidy-selection context, no .data pronoun in selection contexts, explicit return(fitted_dat), no if/else whose sole purpose is to vary columns.
  • The refactor exactly matches the patterns required by CLAUDE.md (data-masking in tidy-selection, branching-that-only-varies-columns, base merge() → dplyr joins, near-duplicate stratified/unstratified paths).

Findings

No blockers and no nits. All prior items across the review thread are now resolved.


Verdict

Approve. The fix is correct, well-documented, well-tested, and CI is green across every substantive workflow. d-morrison's inline comments are all addressed in the most recent refactor. Ready to merge.


@sschildhauer

Copy link
Copy Markdown
Collaborator Author

@d-morrison , Thank you for calling out those changes. I will keep track of the new dplyr features in the future.

@sschildhauer sschildhauer requested a review from d-morrison June 9, 2026 23:07
@github-actions github-actions Bot removed the request for review from d-morrison June 14, 2026 01:18
@claude

claude Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Claude finished @d-morrison's task in 2m 5s —— View job


Code Review: PR #240 — Debug calcfitmod

  • Read CLAUDE.md and copilot-instructions.md
  • Read current state of R/calc_fit_mod.R and R/Run_Mod.R
  • Diff vs origin/main
  • Review documentation and snapshots
  • Post review findings

Summary

The two-part fix lands correctly and the refactor is now fully idiomatic per CLAUDE.md and d-morrison's inline review:

Before After
calc_fit_mod() got dl_sub (per-stratum filtered); last iteration silently overwrote prior strata in fitted_residuals calc_fit_mod() gets full data + strat, merges once on (Subject, Iso_type[, Stratification])
No Stratification column in fitted_residuals Stratification always present ("None" when unstratified)

CI is 5/5 complete workflows passing (NEWS check, Documentation check, Spellcheck, check-readme, lint-changed-files); 4 workflows still in progress (R-CMD-check, test-coverage, version-check, pkgdown).


Correctness — looks good

R/Run_Mod.R:237-239calc_fit_mod(modeled_dat = jags_out, original_data = data, strat = strat) passes the full dataset, decoupling fitted/residual computation from the per-stratum modeling loop. The core bug fix is correct.

R/calc_fit_mod.R:32strat_col construction handles all three cases cleanly:

  • strat = NAcharacter() → no rename in any_of(), no Stratification key in the join
  • strat = "Stratification"c(Stratification = "Stratification") → degenerate rename, harmless
  • strat = "foo"c(Stratification = "foo") → renames fooStratification in one step

R/calc_fit_mod.R:51-58base::intersect(c("Subject", "Iso_type", "Stratification"), names(original_data)) cleanly eliminates the if ("Stratification" %in% ...) branch. Since original_data only gains a Stratification column when strat is non-NA (controlled by any_of(strat_col) on line 37), intersect() does exactly the right thing in both cases.

R/calc_fit_mod.R:67-71dplyr::select(dplyr::all_of(c("Subject", "Iso_type", "Stratification", "t", "fitted", "residual"))) works for both stratified and unstratified cases: in the unstratified path, Stratification = "None" comes from modeled_dat via the right join. Correct.


CLAUDE.md idioms — all addressed

CLAUDE.md requirement Status
.by uses all_of() (tidy-selection context) R/calc_fit_mod.R:43.by = dplyr::all_of(...)
any_of() with named vector for rename-in-select R/calc_fit_mod.R:36-38any_of(c(..., strat_col))
No if/else whose sole purpose is to vary columns strat_col named-vector + intersect() eliminates both branches ✅
dplyr:: joins over base::merge() dplyr::right_join()
Consistent dplyr:: namespace prefixes All dplyr calls prefixed ✅
Explicit return() return(fitted_dat) at R/calc_fit_mod.R:73
strat = NA default (not self-referential) R/calc_fit_mod.R:31

Documentation — looks good

  • @param strat documented at R/calc_fit_mod.R:10-11 and man/calc_fit_mod.Rd:15-16
  • @returns covers the Stratification field, the "None" default, and NA-strat row behavior ✅
  • R/Run_Mod.R:54 / :87 use harmonized `"None"` quoting; man/run_mod.Rd regenerated cleanly ✅
  • NEWS entry (NEWS.md:116) accurately captures both behavioral changes ✅
  • DESCRIPTION bumped to 0.0.0.9058
  • inst/WORDLIST: allowlist restored, calc retained (both warranted) ✅

Findings

🟡 Minor — unstratified unmatched rows get Stratification = NA, not "None" (edge case, non-blocking)

In the unstratified path, modeled_dat carries Stratification = "None". After the right_join, rows that are in original_data but have no matching posterior estimate (if any) will get Stratification = NA (from the missing left-side value) rather than "None". In practice this cannot happen when run_mod() runs successfully — every subject is modeled — so this is a theoretical edge case. The documented behavior at R/calc_fit_mod.R:24-27 covers NA-strat rows, and the snapshots confirm correct output. Not a blocker.


Verdict

Approve. The fix is correct, well-documented, and fully idiomatic per CLAUDE.md. All d-morrison's inline review comments from the previous round are resolved. Lint, spellcheck, docs, and NEWS all pass; R-CMD-check is still running but the code is clean. Ready to merge once CI completes.


Branch: debug_calcfitmod

@d-morrison d-morrison merged commit 89b70c6 into main Jun 15, 2026
17 checks passed
@d-morrison d-morrison deleted the debug_calcfitmod branch June 15, 2026 07:12
@claude claude Bot mentioned this pull request Jun 16, 2026
15 tasks
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.

Fix comments on calc_fit_mod Bug: calc_fit_mod uses only the last stratum's data (R/Run_Mod.R:268–271)

3 participants