Regression - BUGFIX - Fix two silent failure modes: PATH julia resolution and single-sample result caching
Maintainers usually reply within 3 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 42/100
Research direction
Read regression-harness/src/env.jl:66 and regression-harness/src/runner.jl:278, :480, and :597 to trace Julia resolution and subprocess launches; then inspect regression-harness/src/database.jl:24 and regress.jl:196 for cache and repeated-ref behavior. The issue offers several remedies rather than selecting one, so first decide the intended behavior for both failure modes. Done means probes cannot hang silently and reports or sampling make cached results distinguishable from fresh measurements.
Written by the indexing model from the issue text.
Description
The regression harness has two independent ways of misleading a reader silently. Both were hit on 2026-08-21, in two separate sessions, and both produced output that would have gone into a pull request body as evidence.
Provenance: the PATH hang was found by the layer-overlap (#298) investigation; the cache-propagation mechanism was diagnosed by the Δ' reference-length (#403) investigation (shared-cached-row observation and the UNIQUE schema read) and confirmed by the layer-overlap investigation's forced experiment. Related but distinct from #338 (Manifest drift across refs), which is a third way the same comparison can mislead.
1. A bare julia from PATH can hang forever
The harness resolves julia from PATH in four places: the version probe at regression-harness/src/env.jl:66, and the three GPEC subprocess launches at regression-harness/src/runner.jl:278, :480 and :597.
Where julia on PATH is the juliaup shim (~/.juliaup/bin/julialauncher), the probe hangs indefinitely rather than returning. Two consecutive runs sat for ~18 min and ~4 min producing no output, indistinguishable from a long precompile. The process tree is the only tell — parent at 0% CPU with a stuck child:
3997 julia --project=regression-harness regression-harness/regress.jl ... 0.0% CPU
4024 /bin/sh /Users/.../.juliaup/bin/julialauncher --version 0.0% CPU
subprocess_julia_version() already wraps the probe in try/catch returning "unknown", so graceful degradation was intended. A hang is not an exception, so that guard never fires.
Remedies:
- Resolve the interpreter from the running process rather than
PATH—Base.julia_cmd()orjoinpath(Sys.BINDIR, "julia"). The harness is already running under a working Julia, so the correct binary is known and need not be rediscovered. Fixes all four sites. - Put a timeout on the
--versionprobe so it errors instead of wedging if ever spawned externally."unknown"was the right answer and should be reachable.
Workaround: export PATH="$HOME/.julia/juliaup/julia-<version>/bin:$PATH" before invoking. Passing an absolute path to regress.jl is not sufficient — the hang is in the child it spawns.
2. One cached sample per commit becomes that commit's canonical value
runs is declared UNIQUE(commit_hash, case_name) (regression-harness/src/database.jl:24), so exactly one row exists per (SHA, case). Whichever sample is taken first becomes that SHA's value until someone passes --force, and every later comparison against that SHA inherits it.
For a deterministic case that is a pure win. For one with any run-to-run variation it silently propagates a fixed offset into unrelated comparisons. Measured on diiid_slayer_n1, same case, same two refs, cached versus both sides forced:
| quantity | vs. cached row | both sides forced | ratio |
|---|---|---|---|
| Q_root | 5.6e-06 | 5.0e-10 | 11,000x |
| omega_Hz | 1.9e-01 | 1.1e-05 | 17,000x |
| gamma_Hz | 7.6e-02 | 1.5e-05 | 5,000x |
All 16 layer-input quantities were bit-identical in both runs, so no source effect was involved. The residual after forcing is four orders below the cached figure.
The cross-session evidence is the clearest part: two different branches, compared by two different people against the same cached 06be78884 row, both reported omega_Hz = 1.9e-01. An identical figure from two unrelated source deltas is the cache, not physics. Both were on course to be quoted in PR bodies as real movement.
Remedies, in increasing order of ambition:
- Print provenance per side in the report — the
runstable already carries a timestamp, so marking each column cached or fresh makes a poisoned comparison visible rather than invisible. - Imply
--forcefor the ref that equals the working tree's HEAD when producing a stamp for a pull request, since that is the side a reviewer is being asked to trust. - Consider allowing more than one sample per (SHA, case) so a repeat run measures the reproducibility floor instead of overwriting it. Today
--refs X,Xcannot measure it: the ref list is not deduplicated (regress.jl:196), but theUNIQUEkey means both sides read the same surviving row and the report prints exactly0.0.
The artifact selectively poisons the comparisons that matter most
Measured across four comparisons on the same case, the cached sample's jitter is only visible where the genuine source effect is at or below sample scale:
| comparison | genuine mechanism | cache artifact visible? |
|---|---|---|
| K^(2mu) reference-length conversion (#403) | 42% gamma | no — reproduces to 2 digits under --force |
| Delta' shift from the shooting tolerance (#413) | 0.02% gamma | no — reproduces to 4 digits under --force |
| analytic-derivative swap only | ~nil | yes — omega 1.9e-01, collapses to 1.8e-03 forced |
| layer-width additions (no SLAYER path, #298) | nil | yes — omega 1.9e-01, collapses to 1.1e-05 forced |
Large real effects punch straight through the artifact. Null and near-null results are dominated by it. That is the worst possible selectivity, because "did anything change?" is the question the harness exists to answer, and a null result is the answer most often taken at face value.
Why these belong together
Both fail silently in a tool whose entire purpose is producing a numerical claim a reviewer will trust. Neither produces an error, a warning, or a visible anomaly. The first costs time; the second costs correctness, and did so in two sessions on the same day without either noticing until the same number appeared twice.
- Dominant language
- Julia
- Stars
- 11
- Forks
- 7
- Avg merge
- 4d 3h
- Merged PRs (30d)
- 70
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- No contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from OpenFUSIONToolkit/GPEC
-
Difficulty 1/5 Under an hour Newbie friendliness 82/100
OpenFUSIONToolkit/GPEC#644 ·
Maintainers usually reply within 3 days
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
OpenFUSIONToolkit/GPEC#643 ·
Maintainers usually reply within 3 days
-
PerturbedEquilibrium - FEATURE - Complete the resistive perturbed-equilibrium workflow from Galerkin and matched resultsPossibly taken @matt-pharr claimed this 1 day ago. Openfeature
OpenFUSIONToolkit/GPEC#635 · 1 comment · 1 assignee ·
Maintainers usually reply within 3 days
-
test
Difficulty 4/5 3-5 days Newbie friendliness 25/100
OpenFUSIONToolkit/GPEC#633 · 2 comments ·
Maintainers usually reply within 3 days
-
Tearing - FEATURE - Add a general modified Rutherford equation for island evolutionPossibly taken @StuartBenjamin claimed this 1 day ago. Openfeature
OpenFUSIONToolkit/GPEC#630 · 1 assignee ·
Maintainers usually reply within 3 days
All issues in OpenFUSIONToolkit/GPEC
Similar issues
-
`ShallowWaterModel` allocates ~9 KiB per grid point per RK3 stage on the CPUPossibly taken @ali-ramadhan claimed this today. Openperformance 🏍️
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
CliMA/Oceananigans.jl#6421 · 1 reaction ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
NCAR/musica#1118 · 1 comment · 1 reaction ·
Maintainers usually reply within 1 day
-
`AMSGrad` state starts at `epsilon` instead of zero, so zero gradients move parameters and small gradients are dampedPossibly taken @parth-patel010 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
FluxML/Optimisers.jl#247 · 1 comment ·
-
README should say that row and column order must matchPossibly taken @SAUMYARSH claimed this today. Open
Difficulty 1/5 Under an hour Newbie friendliness 84/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day