Skip to content

docs(sampling): auto-derived sampling limits + Sobol' ensemble copy + wire contract lock - #740

Open
JavierGOrdonnez wants to merge 3 commits into
developfrom
jgo/sampling-limits-docs-84
Open

JavierGOrdonnez wants to merge 3 commits into
developfrom
jgo/sampling-limits-docs-84

Conversation

@JavierGOrdonnez

@JavierGOrdonnez JavierGOrdonnez commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

What

Implements the remaining acceptance criteria of JavierGOrdonnez/mmux_vite#84 (parent: #63 DOMAIN ⊥ DISTRIBUTION): the communication + wire-lock half. FE domain only (README + node/; flaskapi/ + engine untouched). Rebased onto develop@d764875b; the former stacked base (e2e-launch-quiescence commits) was dropped — it is byte-identical to the #752 squash already on develop.

1. Docs — README "Sampling limits (auto-derived)"

  • Convention table: uniform → [min, max], normal → mean ± 2.5σ (≈98.8% mass; the ≈1.2% normal tail lies OUTSIDE the sampled/validated domain = surrogate extrapolation), constant → pinned.
  • The Sobol' domain box is auto-derived backend-side in itis-sumo (observed sample bounds; constant column → fixed factor; uniform draws, log-uniform on the log flag; Saltelli count fixed inside the engine) — no editable UI; honest note that the LHS/grid forms seed from the distributions and stay adjustable before launch.
  • Sobol' ensemble ⊥ the modeller distribution: indices describe the surrogate's uniform sweep over its box, not the user's distributions pushed through the surrogate (Correlation is the distribution-shaped view).
  • Two different boxes (Sobol' observed-bounds box vs LHS/grid mean ± 2.5σ) documented as different boxes, reconciliation tracked in itis-sumo#55. No docs/ dir created — that decision belongs to Increase version number #61.

2. In-app copy (node)

The UQ Sobol' step carries the header info tooltip (UQPlotsSteps): indices = the surrogate's uniform ensemble over its auto-derived domain box (log-uniform where flagged — Copilot review), limits not editable, Correlation named as the distribution-shaped view.

3. Contract test (wire lock, node V50)

fetchSobolIndices body reduced to the live contract keys {inputVars, output, FunctionJobs, seed, inputLogScales, outputLogScales}; the new key-set test locks the FULL set so domains/fixed/distributions/numSamples can never regrow onto the wire. Still needed after the Oct-26 refactor: 54a179ec had already dropped numSamples but left distributions sending, while SobolIndicesRequest documents both as GONE from the contract — so the V46sc cache-key pollution (node B60vw) is live on develop until this lands. SobolIndicesPlot.test.tsx's wire-shape pin (from #744/#633) asserted distributions ON the wire — inverted to the negative in the fix commit, resolving the merge-order coupling alexpargon flagged (their "Meaningful" item is now moot: #744 already landed).

4. Engine-pin caveat verified on the pin itself

pyproject pins itis-sumo==0.1.0a10 while #84 quotes a11 docstrings. Inspected the published a10 wheel: auto-infer implemented (api/_session.py: optional domains/fixed, observed min/max inference, constant column → fixed factor, uniform/log-uniform draws) and both docstring quotes present in a10 ⇒ the contract holds for the shipped pin. (alexpargon independently re-verified against the wheel.)

Review round 2 (this push)

  • alexpargon minor fixed: the Saltelli fixed-base fact is flaskapi/SPEC.md V40, not V36 — cites corrected in node V50 (develop-side copies of the mis-cite, incl. the dakota_models docstring, are outside this PR's §C FE domain).
  • ponytail pass: banned-key not.toHaveProperty loop deleted (the exact-set toEqual already REDs on any added key); duplicated description comments thinned across sobolIndices.ts/.test.ts, UQPlotsSteps.tsx, README (−20 lines net; ledger rows untouched — the SPEC §B/§T rows are the canonical home of the narrative).

Verification

  • vitest 720/720 passed (develop baseline + this PR's test), coverage 94.96% lines (≥80 ratchet); tsc -b, knip, eslint (0 errors), uvx prek green.
  • e2e green in CI incl. the 3 split lanes: uq-readonly-sobol-indices.png regenerated inside the pinned playwright:v1.64.0-noble image (info icon lands in the step header, V10/V12) and passes there.
  • SPEC rows (next-free after the Oct 21–26 merges): root T48jk; node V50 (invariant), T52wd, B60vw.

Commits

Refs JavierGOrdonnez/mmux_vite#84 (does not close it — recommend checking its acceptance boxes on merge).

@codecov

codecov Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.93%. Comparing base (ccf2617) to head (419b1be).
⚠️ Report is 8 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #740      +/-   ##
===========================================
+ Coverage    88.46%   88.93%   +0.47%     
===========================================
  Files          115      115              
  Lines        14703    14887     +184     
  Branches      1619     1638      +19     
===========================================
+ Hits         13007    13240     +233     
+ Misses        1609     1558      -51     
- Partials        87       89       +2     
Flag Coverage Δ
e2e 80.05% <100.00%> (+0.74%) ⬆️
flaskapi 93.58% <ø> (+0.04%) ⬆️
node 91.70% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed

codspeed Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

1 warning, 1 note

⚠️ 1 benchmark is dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

ℹ️ 18 benchmarks have no flamegraph

The flamegraph wasn't generated: the symbols of the profiling trace could not be resolved, because no information about the language frames was collected.

See affected benchmarks

✅ 27 untouched benchmarks


Comparing jgo/sampling-limits-docs-84 (419b1be) with develop (d764875)

Open in CodSpeed

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.

🟢 Approval recommended

The focused changes have no blocking findings; only a minor tooltip clarification remains.

1 open finding
What changed in this PR

Documents auto-derived sampling limits and aligns frontend Sobol' requests with the backend contract.

Changes:

  • Explains sampling boxes and Sobol' ensemble semantics.
  • Adds an in-app Sobol' information tooltip.
  • Removes unused request fields and locks the wire format with a contract test.
File Description
SPEC.md Records documentation and contract work.
README.md Explains sampling limits and engine behavior.
node/​src/​utils/​sobolIndices.ts Removes unused request parameters.
node/​src/​utils/​sobolIndices.test.ts Locks the allowed request keys.
node/​src/​components/​plots/​UQPlotsSteps.tsx Adds Sobol' explanatory copy.
node/​src/​components/​plots/​SobolIndicesPlot.tsx Updates the request call.
node/​SPEC.md Records frontend contract and cache changes.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@JavierGOrdonnez

Copy link
Copy Markdown
Collaborator Author

Stacking prep: branch rebased onto current develop tip (6b50d900) and force-pushed — content unchanged apart from the earlier Copilot fix (a9315945, log-uniform tooltip, resolved thread). This PR is now the base of the three-PR stack #740 → #741 → #742 (all touch node/SPEC.md, Sobol/MOGA plot files and shared e2e baselines; the stack pre-resolves those overlaps so Monday's merges are sequential no-conflict). Merging this first auto-retargets #741's base to develop.

@JavierGOrdonnez

Copy link
Copy Markdown
Collaborator Author

/ponytail-review (over-engineering pass, diff-only)

  • node/src/utils/sobolIndices.test.ts:L115-117: shrink: per-banned-key not.toHaveProperty loop after the full key-set toEqual (L107-114). Exact-set toEqual already REDs on any added key — the loop can only fire where the test already failed; the banned names as human documentation are already in the L84-89 comment.

Net diff also shrinks product code (dead domains/numSamples params out). Otherwise lean.

@alexpargon alexpargon left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Review — the wire actually goes quiet: contract verified at all three layers

Reviewed the full diff (+89/−25, 8 files) plus the backend contract on develop, the published itis-sumo==0.1.0a10 wheel (downloaded and grepped, not taken on faith), the SPEC id ledger, and the test deltas.

Good / no action needed

  • sobolIndices.ts + SobolIndicesPlot.tsx — the removal is true at the source, not just plausible: develop's SobolIndicesRequest (dakota_models.py:1235) says it in its own docstring — distributions/numSamples are "GONE from this contract", domains/fixed optional with absent → observed-bounds auto-infer. The FE was the only side still humming the dead keys.
  • sobolIndices.test.ts — this is the right shape of lock: sorted-key-set equality against exactly {FunctionJobs, inputLogScales, inputVars, output, outputLogScales, seed} plus an explicit banned-keys loop. A subset assertion would let the next contributor re-add a key through the side door; an equality lock can't. Existing tests updated consistently (seed pin survives, as it should — seed is a genuine wire key).
  • The engine claims check out at the pin. Pulled the a10 wheel from test-pypi: api/workflows.py:205-207 carries "Modeller distributions are NOT an input here; they drive evaluate_uncertainty" and evaluate/funs_evaluate.py:1288-1289 carries "no box is ever re-derived from a distribution's mean ± 3σ" — the README quotes are verbatim. And api/_session.py sobol() really does the auto-infer: absent box → lo, hi = column.min(), column.max(), and lo == hi → fixed factor with a comment that inventing a box around a constant "would fabricate sensitivity." The constant→pinned README row is engine fact at this pin, not aspiration.
  • README two-box table — the normal→mean±2.5σ ⇒ ≈98.8% math is right, and the framing (the ≈1.2% normal tail is outside the sampled domain = surrogate extrapolation) is the honest version of that sentence.
  • Ledger discipline — V49/T51wd/B59vw are all next-free (develop tops out at V48hz/T50ab/B58rs), root T47jk follows T46cs, uniq -d clean on every SPEC at head. B59vw is a model cause row: tolerated extra keys → V46sc derives the cache key from the sent body → guaranteed MISS + full recompute for a response that cannot depend on either. Naming the failure direction (inverse of B37rv) is exactly the register §B is for.
  • UQPlotsSteps.tsx copy is engine-accurate — the ensemble is uniform draws over the exploration box, log-uniform where a scale override says so (workflows.py:205), ⊥ the modeller distributions; naming Correlation as the distribution-shaped view sends users to the right panel. PNG regenerated for the new info-icon, correlation baseline left alone — the only binary in the diff is uq-readonly-sobol-indices.png (76.9→77.5 KB).

Meaningful

  • Merge-order coupling with #744. #744's new SobolIndicesPlot.test.tsx pins the as-is wire (body.numSamples = 4321, body.distributions present) — exactly the keys this PR deletes. The diffs don't touch a shared file, so git will merge them cheerfully; whichever lands second goes RED in node-tests until those assertions are flipped to the V49 key-set. Worth a line in either PR's merge notes so the second merger isn't debugging a phantom.

Minor (optional)

  • Mis-cite inherited, don't propagate it. The new V49 row (and T47jk's summary line) point the Saltelli fixed-count fact at ../flaskapi/SPEC.md V36 — but flaskapi V36 is the sanitize_varnames char-class row. The fixed-Saltelli-base fact is flaskapi V40. The error is inherited from develop's dakota_models.py docstring (which cites (V36) for the same fact), but new SPEC text is the one place it's cheap to fix: point V49 at V40, and maybe weep on the backend docstring while you're there.

  • Footnote on the body: "522 passed" doesn't reconcile with #744's develop baseline of 518 (+1 contract test would be 519). Raw it(/it.each( line counts read develop 440 → here 441 (+1 ✓), so the delta is right; one of the two absolute counts is a stale re-measure. Re-run and correct the number, the delta survives either way.

Verdict: Approving on the merits — the reduction matches the backend model verbatim, the wheel claims are real at the pin, and the key-set equality test is the strongest form of lock available. Fix the V36→V40 cite when convenient (nothing depends on it), and coordinate merge order with #744 so the second landing reconciles the Sobol test instead of tripping over it.

@JavierGOrdonnez
JavierGOrdonnez force-pushed the jgo/sampling-limits-docs-84 branch from 49bd44d to f19d086 Compare October 20, 2026 13:43
JavierGOrdonnez pushed a commit that referenced this pull request Oct 20, 2026
…y change — regen inside pinned Playwright image on the stacked tree
JavierGOrdonnez pushed a commit that referenced this pull request Oct 20, 2026
…ee (chip, B59wp front, #740 values) — regen inside pinned Playwright image
@JavierGOrdonnez
JavierGOrdonnez force-pushed the jgo/sampling-limits-docs-84 branch from f19d086 to 270f220 Compare October 27, 2026 17:13
@JavierGOrdonnez

Copy link
Copy Markdown
Collaborator Author

Rebased onto develop@d764875b (2026-10-26 tip). Content review outcome: the PR's substance is still valid — one piece became more urgent.

Dropped commits (already on develop). Commits 1–3 (e2e-launch-quiescence) were the stacked base branch, squash-merged via #752: the tree at ca6c963e is byte-identical to 5434da8d. test_e2e_launch_quiescence.py, helpers.ts/sumo-write.spec.ts changes and root §V.47rv/§B.31rv are consequently gone from this PR's footprint. Remaining scope: fix(sobol) wire lock + docs(sampling) + tooltip fixup.

Wire fix — still needed, half-done on develop. 54a179ec (uqSettingsFor) dropped numSamples from fetchSobolIndices but still sends distributions, while SobolIndicesRequest (flaskapi) documents both keys as GONE from the contract — so the V46sc cache-key pollution (B60vw below) is live on develop. Resolution kept develop's seed: configured.seed and applies the PR's removal of distributions + the key-set contract test.

SPEC renumber (numbers squat after the Oct 21–26 merges): T47jk→T48jk (T47fl/T47sl/T47mx landed), V49→V50 (V49ub), T51wd→T52wd (T51ub), B59vw→B60vw (B59mx) — cross-refs updated throughout.

Develop-side test flipped: SobolIndicesPlot.test.tsx (54a179e wire-shape suite) asserted distributions on the wire — inverted to not.toHaveProperty("distributions") (the inputLogScales assertion still proves scale-carrying); folded into the fix commit.

Verified: vitest 720/720, coverage 94.96% lines (≥80 ratchet), tsc -b / knip / eslint (0 errors) / prek green. uq-readonly-sobol-indices.png applies unchanged on develop's untouched baseline; pinned-image e2e lanes will confirm pixels.

Refs JavierGOrdonnez#84 (does not close it).

Javier Garcia Ordonez added 3 commits October 27, 2026 18:47
fetchSobolIndices still sent distributions/numSamples although the backend
SobolIndicesRequest dropped both with the bounds-editor removal: pydantic
tolerates the extras, but V46sc keys the session cache off the SENT body, so
every distribution/numSamples edit was a guaranteed cache miss + full recompute
of a response that cannot depend on them (node B59vw). The Sobol' box is the
engine's auto-inferred DOMAIN (observed bounds, constant column -> fixed;
root JavierGOrdonnez#84) - domains/fixed must also never appear.
Full key-set contract test locks node V49.
…le copy

Fork #84 (docs + copy PR): README gains 'Sampling limits (auto-derived)' —
LHS/grid box seeded uniform->/[min,max], normal->mean +/- 2.5 sigma (~98.8%
mass, the ~1.2% normal tail sits outside the sampled domain = extrapolation),
constant->pinned; the Sobol' box is auto-inferred backend-side in itis-sumo
from observed training bounds (uniform draws, count fixed in the engine);
the two boxes differ (cross-ref itis-sumo#55). Engine-pin caveat closed by
inspecting the published itis-sumo==0.1.0a10 wheel: the auto-infer + both
docstring quotes #84 cites from a11 are already in a10. The UQ Sobol' step
now carries header info copy stating the indices describe the surrogate's
uniform ensemble over its domain box, not the user's distributions (the
Correlation panel is the distribution-shaped view). Sobol baseline
regenerated IN the pinned Playwright image (info icon lands in the header;
verify-only pass green against the shipped baseline set, V10/V12).
SPEC: root T47jk, node V49/T51wd/B59vw.
@JavierGOrdonnez
JavierGOrdonnez force-pushed the jgo/sampling-limits-docs-84 branch from 270f220 to 419b1be Compare October 27, 2026 17:47
@JavierGOrdonnez

Copy link
Copy Markdown
Collaborator Author

Review-round status — all Copilot and @alexpargon items addressed on 419b1be6:

  • Copilot (log-uniform tooltip): fixed earlier (270f2202), thread resolved — unchanged by the rebase.
  • alexpargon "Meaningful" — test(node): adopt 80/80/80/80 coverage ratchet (V27ku) via focused branch-gap sweep (#633) #744 merge-order coupling: mooted by the rebase itself. test(node): adopt 80/80/80/80 coverage ratchet (V27ku) via focused branch-gap sweep (#633) #744 landed on develop first; its SobolIndicesPlot.test.tsx wire-shape pin (asserting distributions present) was inverted to not.toHaveProperty("distributions") in the fix commit — the second-landing reconciliation is already in this branch.
  • alexpargon minor — mis-cite: fixed. Node V50 now cites ../flaskapi/SPEC.md V40 (fixed Saltelli base), as do the new code comments. Develop-side copies of the inherited mis-cite (V49ub/T51ub, dakota_models.py docstring) stay untouched — outside this PR's §C FE domain.
  • alexpargon footnote — stale test count: corrected. Body now states the rebase-measured 720/720 (develop baseline + this PR), replacing "522".
  • Ponytail pass (second round, applied): sobolIndices.test.ts banned-key loop deleted (exact-set toEqual already REDs on any added key); duplicate narration thinned out of sobolIndices.ts doc block, test comment, UQPlotsSteps rationale and the README bullet list — the §B/§T ledger rows + README remain the single canonical home of the story. Net −20 lines; ledger rows untouched. Verified: 40/40 on touched suites, tsc, eslint, prek green.

JavierGOrdonnez pushed a commit that referenced this pull request Oct 27, 2026
…y change — regen inside pinned Playwright image on the stacked tree
JavierGOrdonnez pushed a commit that referenced this pull request Oct 27, 2026
…e a base a sibling claimed)

base@d764875b + rebased #740 consumed 49 (V49ub), 50 (V50), 52 (T52wd), 59 (B59mx)
and 60 (B60vw) while #741 was drafted, so: V51ij→V51ij, V52kl→V52kl, T53ij→T53ij,
T54pq→T54pq, T55st→T55st, T56vw→T56vw, B61uv→B61uv — files + cross-refs.
JavierGOrdonnez pushed a commit that referenced this pull request Oct 27, 2026
…ee (chip, B62wp front, #740 values) — regen inside pinned Playwright image
JavierGOrdonnez pushed a commit that referenced this pull request Oct 27, 2026
…y change — regen inside pinned Playwright image on the stacked tree

Rebase round 2 (new base @ develop): three more baselines had aged past the base itself
and were regenerated + cross-boot-verified inside the pinned image:
- moga-readonly-pareto.png / moga-readonly-settings-modal.png: develop #633 added the
  Performance column to the Pareto table (settings-modal was masked behind the pareto
  assertion in CI run 1).
- sobol-highdim-second-order-heatmap.png: the base's T47mx container shot
  (mmux-testid="sobol-indices-plot") now includes the sweep's download chip seated in
  that plot container — the established V36ez chip-in-baseline precedent.
JavierGOrdonnez pushed a commit that referenced this pull request Oct 27, 2026
…e a base a sibling claimed)

base@d764875b + rebased #740 consumed 49 (V49ub), 50 (V50), 52 (T52wd), 59 (B59mx)
and 60 (B60vw) while #741 was drafted, so: V51ij→V51ij, V52kl→V52kl, T53ij→T53ij,
T54pq→T54pq, T55st→T55st, T56vw→T56vw, B61uv→B61uv — files + cross-refs.
JavierGOrdonnez pushed a commit that referenced this pull request Oct 27, 2026
…ee (chip, B62wp front, #740 values) — regen inside pinned Playwright image

Base-move refresh (onto re-based #741 @ 4384982): the three MOGA read-only baselines re-
aged again — the base moved in develop's Pareto-table Performance column (#633) on top of
this tree's full-front envelope render. Re-gen disciplined per LANE context: monolithic
update-mode runs leak shared-backend state (a continued-past-failure spec mutates the job
collections the SuMo/UQ views read), so only the MOGA lane's own files were taken from the
pinned-image regen; SuMo/UQ baselines stay at the lane-verified bytes the base ships.
JavierGOrdonnez pushed a commit that referenced this pull request Oct 27, 2026
…main (B63px)

The column was the terminal frame of three async writes in arbitrary order:
- the table's [weights] effect overwrote row.performance with a naive
  direction-blind raw sum (empty e2e-seeded weights -> 0.00)
- the parent's [weights] recalc wrote the normalized score into a
  capital-Performance key the grid never reads (dead write)
- runMOGA's own commit normalized over ALL evaluations while the recalc
  re-derived min/max from the front rows; a single-objective front is all
  rows tied at the optimum -> min==max -> norm=0 fallback -> whole column
  0.0, and the runMOGA closure could hold empty weights -> all cells NaN
  (the '-' placeholder)
Pixels settled on '-', 0.00, 0.0 or the resolved 1.0 by write order
(proven: pinned-image regens of one commit -> resolved/-/resolved; post
single-writer verifies -> 0.0/0.0/1.0/1.0).

The parent recalc is now a pure projection of (tableData, weights,
outputTargets): it fires on every tableData commit and every
weights/direction edit, writes only the lowercase rendered field, always
normalizes against raw (the same all-evaluations domain runMOGA uses), and
bailouts via functional update when every row already agrees, so terminal
pixels are write-order independent instead of a coin flip.

- regression test MOGAParetoTable.test.tsx: given scores render verbatim
  (red on the old child code, green on the fix)
- e2e: expectMogaPerformanceComputed gate (cells exist, then no '-'
  placeholder) before every full-page MOGA baseline guards the transient
  window; baselines regenerate in the pinned image in a follow-up commit

Refs JavierGOrdonnez#83, node V49wp/B59wp/T51ic

Re-base adaptations (base moved to develop d764875 + re-based #740-#742):
- the projection effect now falls back to {} for a function with no outputTargets
  entry (same idiom as the scale-detection guard) — the develop #678 lifecycle test
  "falls back to an empty objective set" caught the un-guarded Object.keys crash.
- #633's parent-matrix test read the DEAD capital-Performance key the convergence
  deletes: reads re-targeted to the lowercase rendered field (values identical —
  the raw all-evaluations domain contains the front rows).
- #633's table test pinned the retired child recomputation: re-titled to assert the
  GIVEN scores stand, no realign fires on a weights-only edit (realign is keyed to
  [data] now) and the raw-sum override never appears.
JavierGOrdonnez pushed a commit that referenced this pull request Oct 27, 2026
base@d764875b + rebased #740/#741/#742 consumed 59-62 while #745 was drafted;
B63px was the next free base. Cross-refs (SPEC row, code comments, specs) remapped
together.
JavierGOrdonnez pushed a commit that referenced this pull request Oct 27, 2026
…main (B63px)

The column was the terminal frame of three async writes in arbitrary order:
- the table's [weights] effect overwrote row.performance with a naive
  direction-blind raw sum (empty e2e-seeded weights -> 0.00)
- the parent's [weights] recalc wrote the normalized score into a
  capital-Performance key the grid never reads (dead write)
- runMOGA's own commit normalized over ALL evaluations while the recalc
  re-derived min/max from the front rows; a single-objective front is all
  rows tied at the optimum -> min==max -> norm=0 fallback -> whole column
  0.0, and the runMOGA closure could hold empty weights -> all cells NaN
  (the '-' placeholder)
Pixels settled on '-', 0.00, 0.0 or the resolved 1.0 by write order
(proven: pinned-image regens of one commit -> resolved/-/resolved; post
single-writer verifies -> 0.0/0.0/1.0/1.0).

The parent recalc is now a pure projection of (tableData, weights,
outputTargets): it fires on every tableData commit and every
weights/direction edit, writes only the lowercase rendered field, always
normalizes against raw (the same all-evaluations domain runMOGA uses), and
bailouts via functional update when every row already agrees, so terminal
pixels are write-order independent instead of a coin flip.

- regression test MOGAParetoTable.test.tsx: given scores render verbatim
  (red on the old child code, green on the fix)
- e2e: expectMogaPerformanceComputed gate (cells exist, then no '-'
  placeholder) before every full-page MOGA baseline guards the transient
  window; baselines regenerate in the pinned image in a follow-up commit

Refs JavierGOrdonnez#83, node V49wp/B59wp/T51ic

Re-base adaptations (base moved to develop d764875 + re-based #740-#742):
- the projection effect now falls back to {} for a function with no outputTargets
  entry (same idiom as the scale-detection guard) — the develop #678 lifecycle test
  "falls back to an empty objective set" caught the un-guarded Object.keys crash.
- #633's parent-matrix test read the DEAD capital-Performance key the convergence
  deletes: reads re-targeted to the lowercase rendered field (values identical —
  the raw all-evaluations domain contains the front rows).
- #633's table test pinned the retired child recomputation: re-titled to assert the
  GIVEN scores stand, no realign fires on a weights-only edit (realign is keyed to
  [data] now) and the raw-sum override never appears.
JavierGOrdonnez pushed a commit that referenced this pull request Oct 27, 2026
base@d764875b + rebased #740/#741/#742 consumed 59-62 while #745 was drafted;
B63px was the next free base. Cross-refs (SPEC row, code comments, specs) remapped
together.
// ROOT #84: the Sobol' box is auto-derived engine-side and ⊥ editable — the
// copy must name whose ensemble the indices describe (README "Sampling limits").
"Sobol' Indices":
"Sobol' indices describe the surrogate's own exploration ensemble: itis-sumo draws uniformly over the surrogate's domain box (log-uniform for variables flagged log-scale, matching the README \"Sampling limits\" contract), auto-derived from the observed training-sample bounds (a constant column stays fixed). These sampling limits are not editable. To see your input distributions pushed through the surrogate, use the Correlation panel.",

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

this reads verbose; pls use the humanizer skill.

Remove the comment lines as well.

This could be something like:
Sobol: "Sobol' indices describe the importance of each parameter for the output QoI over the full surrogate domain, infered from training samples."

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.

3 participants