Variation / Morris Sensitivity Suite: consolidate 34 draft PRs (#4142, #4433, #4120, #4206) - #4447
Open
dieterolson wants to merge 334 commits into
Open
Variation / Morris Sensitivity Suite: consolidate 34 draft PRs (#4142, #4433, #4120, #4206)#4447dieterolson wants to merge 334 commits into
dieterolson wants to merge 334 commits into
Conversation
# Conflicts: # SPEC.md # src/rate_of_closure/ui/pyqt6/simulation_view.py
# Conflicts: # SPEC.md
# Conflicts: # SPEC.md
…r-analytics feat(rate-of-closure): add launch monitor analytics tabs
…y' into feat/4193-launch-direction-registry-integration
…ion-registry-integration feat(rate-of-closure): add launch direction conventions
The web build was broken and two React tests failed once the whole family was integrated. Both are genuine cross-slice defects that no individual PR could expose, because each slice only ever ran against its own parent. 1. `npm run build` (tsc) failed, which is why "Rate web production Worker E2E" could not even start its preview server. #4431 made `executionMetadata` required on `VariationExecutionRequest`/`VariationExecutionResult`, but four test fixtures introduced by the #4444 chain construct those objects without it. Supplied it the way the already-updated fixtures in the same file do -- from the request under test, which also satisfies `validateResult`'s request/result metadata equality check. For the two unsupported-flight-model cases the request is now spread from `jointRequest()` with only the plan overridden; `validateExecutionRequest` runs `validatePlan` before the metadata comparison, so the assertion still exercises the flight-model rejection it was written for. 2. A real behavioural regression. `importPlan` sets the plan, clears results, then reports provenance -- either "resolves against the current variable registry ... not evidence of historical reproducibility" for a raw plan, or "Execution sidecar verified against the current registry" for a signed document. The #4444 chain added an effect that calls `invalidateResults` on every configuration-identity change. Changing the plan changes that identity, so the effect ran after commit and overwrote the provenance message with the generic "Ready: configuration changed; run again." The user was silently denied the one message that tells them a loaded plan was re-resolved against today's registry rather than its recorded one. `invalidateResults` now announces only a discard that actually happened, decided from refs so the callback identity stays stable and the effect cannot re-trigger itself. Nothing else references that string, and the invalidation tests assert visual state and heading removal rather than status text, so they are unaffected -- they invalidate with results present, where the message still appears. Verified in the web workspace: tsc clean, eslint clean (--max-warnings 0), vite build succeeds, and vitest is 1084/1084 across 126 files (was 1082/1084).
dieterolson
disabled auto-merge
August 14, 2026 06:09
dieterolson
enabled auto-merge (squash)
August 14, 2026 06:09
added 3 commits
August 13, 2026 23:36
…esign seam Two slices in this family carry contracts that are mutually exclusive as written, and neither branch contained both, so both slices' tests passed in isolation and the contradiction only appears once they are integrated: - #4426 added `build_simulation_ensemble_request_from_samples`, whose entire purpose is deterministic experimental designs "whose rows are the scientific authority (for example, planted baseline/perturbation pairs), rather than pseudorandom Monte Carlo draws". - #4428/#4431 made `SimulationEnsembleRequest.__post_init__` require unconditionally that `sampled_inputs` equal `sample_inputs(plan)` -- the plan-derived RNG stream. Together, the request contract rejects exactly the designs the seam exists to carry. Measured: 7 tests in test_localized_attribution_producer.py failed with "sampled_inputs must exactly match the plan-derived RNG stream and order", which is the whole paired-attribution producer being non-functional. Reconciled by making the provenance explicit rather than implied. `SimulationEnsembleRequest.sample_provenance` defaults to `plan_rng`, so every existing caller and test keeps the reproducibility guarantee unchanged, and the RNG-stream equality check is enforced exactly as before. The explicit seam passes `explicit_design`, which skips only that one check; shape, finiteness, and crucially `_require_config_sample_binding` -- the check that actually proves each row was executed as written -- all still apply. The Monte Carlo seam now passes `plan_rng` explicitly, because it delegates through the explicit builder and must not inherit its default. Verified with the pinned toolchain: the 7 producer tests pass, and 626 tests across the variation, reference, flight, solver and impact suites pass with no new failures. Confirmed the 5 unrelated failures in this area are pre-existing on the pushed branch by re-running them with these two files reverted to HEAD.
The repo-wide tooltip-completeness contract (test_tooltips.py) failed on eight widgets, all of them paired-attribution controls added by #4426/#4427: Cancel Paired Study, the two export buttons, and the save/load authority buttons. The tooltip contract comes from a different slice, so neither branch contained both and the gap only appears once they are integrated. Hints state what each control does and, where it matters, what it does not: cancelling publishes nothing but retains prior authority, the view export records what is displayed rather than the authority, and loading is accepted only if the archived design and request identities still validate.
…ding contracts The family's Python suite had never run in CI -- `pick-runner` never granted any of the 34 drafts a fleet slot, so `tests (3.11)` was never even created on them. Running it locally against CI's interpreter (3.11) and pinned dependency set surfaced five real failures, none caused by the merge itself: each is a place where one slice's contract rejects another slice's usage, and no branch contained both halves. All five are the same two contracts meeting code written before them: - `scripts/benchmark_rate_ensemble_archive.py` builds a synthetic all-zero sample matrix, which the RNG-stream guard rejected. It now declares `explicit_design`. Its noise variable also moved from `face_angle_deg` to `impact_offset_toe_mm` because the per-row config binding can only verify trace-capable keys; the benchmark measures archive RSS scaling, not any particular variable. - `test_variation_ensemble_archive.py` asserted request identity by mutating sampled inputs in place. That is now unconstructable twice over, so the sample-bytes case rebinds each config to the row it is executed with and declares `explicit_design`, and the config-order case asserts the stronger property the binding actually provides: a misordered request is rejected outright rather than merely hashing differently. - `test_morris_rate_adapter.py` injected pre-computed runs built from other configs. `capture_simulation` now requires a run to carry the exact config it was asked for -- a correct safety property, so the test was what needed changing. Rate Morris execution also requires the double_pendulum source, which misses, so the hit-availability case is asserted against `project_simulation_outcome`, which owns that rule, while the miss goes through the real evaluator end to end. - `launch_monitor_import.py` returned NaN where an empty CSV cell should be null. From pandas 3 a bare DataFrame construction coerces None in an object column to NaN; the test's own name says this import mirrors browser policy, which yields null, so the frame is now built with `dtype=object`. An absent value stays absent instead of silently becoming a floating-point quantity. - The RSS test's remaining failure was a missing local `psutil`, not a defect. One further failure, in `test_variation_ensemble_io_reader.py`, reproduced only on Python 3.13 and passes on 3.11, so it is left alone; it is a JSON nesting-depth error-taxonomy difference, not a defect in the required lane. Verified: `tests/rate_of_closure/` is 1451 passed, 0 failed on Python 3.11 with CI's pinned numpy/scipy/pandas/PyQt6, plus ruff check, ruff format, and mypy clean over CI's exact file lists.
dieterolson
disabled auto-merge
August 14, 2026 07:15
dieterolson
enabled auto-merge (squash)
August 14, 2026 07:15
Only two conflicts, both additive appends: - scripts/test_assertion_allowlist.txt: kept this branch's swing_sim package markers alongside CONS-A1's pdf_renamer conftest entry. - SPEC.md change log: union of both dated blocks. Verified LF line endings survived on both files.
This was referenced Aug 14, 2026
added 2 commits
August 14, 2026 12:42
…mplete
`tests (3.11)` failed at COLLECTION, which aborts the whole run before any test
executes -- hence all three matrix lanes failing identically:
ERROR collecting tests/rate_of_closure/test_morris_authority_child.py
ModuleNotFoundError: No module named 'uvicorn'
Declared the dependency rather than restructuring the test or adding a skip
guard. A `pytest.importorskip` here would make the Morris authority tests
silently vanish in CI, which is the same "check that reports success while
checking nothing" pattern filed as #4460; fixing a red gate must not create
another one. It is also not an option here: the test monkeypatches
`child.uvicorn` directly, so the module attribute has to exist.
`uvicorn` is already declared in the `rate-morris-authority` and `all` extras in
pyproject.toml, but neither job installs those extras -- both install
`requirements-ci.txt` plus an explicit `fastapi python-multipart` line, which is
where `fastapi` is effectively declared for CI. Added `uvicorn` there, in both
the quality-gate and tests jobs, since both build the same environment.
Auditing the same class across the branch found one more, which would have
failed as soon as collection got past the first: `psutil` is imported at module
scope by `scripts/benchmark_rate_ensemble_archive.py`, which
`test_variation_ensemble_archive_memory.py` runs as a subprocess with the same
interpreter. It is declared in NO requirements file, pyproject extra, or
workflow anywhere in the repo, and the test has no guard, so a missing psutil
fails it rather than skipping. Declared alongside uvicorn.
Everything else the audit flagged is safe: `build123d` is guarded by
`pytest.importorskip` in both wedge tests, `swing_core` by try/except in
`_rust_facade.py`, `starlette` ships with fastapi, `mpl_toolkits` with
matplotlib, `jax`/`pendulum_core` live in the pendulum lane CI excludes from
changed-tests, and the rest are first-party packages.
Chose the workflow install line over `requirements.txt` deliberately: it matches
how fastapi, pymodbus, sqlmodel and httpx are already handled, and avoids making
`requirements-lock.txt` stale and widening pip-audit's scope.
Two conflicts, one of them a genuine divergent refactor of the same file. **src/movement_optimizer/gui/motion_tabs.py** — both branches split this module to satisfy the module-size budget, but differently. This branch extracted `motion_helpers.py` (`build_motion_colors`, `chain_path_length`); #4438 extracted `motion_view.py` (`MotionViewMixin`) and kept a local `_build_motion_colors`. Took main's version wholesale and deleted the now-orphaned `motion_helpers.py`, which nothing else imported. That reproduces main's exact, reviewed, green state for a vendored sub-app that CI excludes from every ruff, mypy and changed-test lane -- i.e. a place where a mis-resolution would not have been caught. Worth recording: git presented the third hunk as main *deleting* the "Playback speed" control, and it does not. Main keeps it at line 682 as a single-line `_add_control` call while this branch had it line-wrapped. Both branches' `test_motion_tabs.py` are byte-identical and both reference `chain._controls["speed"]`, so dropping it would have broken the sub-app silently. Verified before resolving rather than trusting the conflict markers. **torque_utils.py** — rerere replayed this branch's resolution, which routes polynomial evaluation through the shared `TorquePolynomial` instead of `np.polyval` on reversed coefficients. Since the two use opposite coefficient orders, I checked equivalence numerically rather than by reading: ascending `TorquePolynomial(coeffs).evaluate(t)` matches `np.polyval(coeffs[::-1], t)` to 1e-12 across t in {0, 0.13, 0.5, 1.0, 2.5}. Re-verified on the new base: mypy clean over CI's 418 files, ruff check and format clean over 596, module size budget, changed-test assertion and minimum test contract gates all pass, no conflict markers, no gitlinks, and CI's exact 210 changed-test files now collect cleanly -- 2572 tests, exit 0.
dieterolson
pushed a commit
that referenced
this pull request
Aug 14, 2026
rate_of_closure.web_companion.runtime and web_authority.child both do a plain module-level 'import uvicorn', and tests/rate_of_closure imports them, so the whole pytest lane aborts at collection without it. uvicorn was declared only in pyproject's optional rate-of-closure-web extra, which CI does not install; CI installs from requirements.txt. Same class as the filelock gap, and the same failure that just took #4447 red. Found by walking the import graph from tests/ through first-party modules and diffing the unguarded external roots against requirements.txt plus the explicit pip lines in ci-standard.yml. The only other new-in-this-branch hits were starlette (a fastapi dependency CI installs) and mpl_toolkits (part of matplotlib), both already satisfied.
added 2 commits
August 14, 2026 14:51
…4475) `.github/workflows/ci-standard.yml` auto-merged cleanly -- #4475 changes the `pick-runner` job's placement while this branch's change is in the dependency install lines, so the two do not overlap. Verified both survived: the hosted dispatcher routing is at line 83 and `uvicorn psutil` at lines 246 and 607. This is a welcome merge rather than just a required one: #4475 moves `pick-runner` off `d-sorg-fleet` onto a hosted runner for public repos, so the dispatcher no longer burns a fleet slot purely to decide placement while every job with `needs: pick-runner` queues behind it. That is precisely what has been holding this PR's `tests (3.11)`. One conflict, and it was not a content conflict. `.github/workflows/cross-repo-python-integration.yml` came through as a whole-file conflict because **main's copy is CRLF (256 lines) while this branch's -- and the repo convention, `core.eol=lf` -- is LF (252 lines)**. Git could not align a single line, so it presented both copies in full. Normalizing for comparison shows the real change is 11 insertions and 7 deletions: #4475's `CI_RUNNER_MODE`/`REPOSITORY_PRIVATE` plumbing, the public-repo hosted fallback, and the removal of `vendor/ud-tools` from the sparse checkout. Took main's version verbatim, CRLF included. Normalizing it to LF here would be the correct convention but would add a 252-line line-ending diff to a consolidation that does not otherwise touch this file, and the regression is main's rather than this family's. Flagged for a separate one-line fix instead -- left as is, every other in-flight consolidation branch will hit this same unalignable whole-file conflict. Re-verified on the new base: mypy clean over 374 files, ruff check and format clean over 584, assertion and module-size gates pass, both workflows parse as valid YAML, no conflict markers, no gitlinks.
…step I resolved the previous merge wrong. Taking main's `cross-repo-python-integration.yml` wholesale to avoid a line-ending diff also discarded two of this branch's own changes, because the file's content had genuinely diverged and not only in #4475's hunks: - `vendor/ud-tools` in UpstreamDrift's sparse-checkout scope - the whole `Initialize pinned Tools submodule` step This branch's `tests/ops/test_cross_repo_python_integration.py` asserts both (it adds 27 lines main does not have, including a dedicated test that the submodule step runs before dependency install), so I kept the tests while dropping the thing they test. `tests (3.12)` caught it. Rebuilt as the actual union: started from this branch's version and applied #4475's two hunks (`CI_RUNNER_MODE || LOCAL_RUNNER_MODE` plus `REPOSITORY_PRIVATE`, and the public-repo hosted-runner fallback). Written with CRLF to match main so the diff against main is the 8 lines of real content rather than a whole-file line-ending rewrite. Verified all three are present and the submodule test passes again. Two failures remain in this file's tests, and they are NOT from this branch: `origin/main` fails the identical two. Proven by running them in a detached worktree at edfeae6 -- `2 failed, 3 passed`. Main's own REQUIRED_SPARSE_PATHS expects `shared`, `sidekick`, `python/src/utils`, `contracts.py` while main's workflow declares the `src/`-prefixed forms. Main is green only because this test file is not in main's changed-file set, so its delta-CI never runs it -- the same blindness filed as #4460. This branch merely touches the file and so inherits the failure. Not fixing main's two here, per the standing rule that a consolidation is the wrong vehicle for pre-existing defects. Reported for routing instead.
This was referenced Aug 15, 2026
…nst recurrence
`tests (3.10)` aborted at COLLECTION with 18 errors, so the whole lane never ran
a single test. Two 3.11+ stdlib features were imported at module scope:
- `enum.StrEnum` in `club_camera.py` and `variation_visual_state.py` -- 17 of the
18 errors, since every module transitively importing them failed too.
- `tomllib` in `tests/ops/test_rate_web_playwright_workflow.py` -- the 18th.
Both already have an established repo pattern that these bypassed. Of the 17
`StrEnum` imports in the tree, 15 are correctly version-guarded; only these two
were bare. This is the same defect class as the `from datetime import UTC`
regression fixed earlier on this branch: a 3.11+ feature taken directly instead
of through `shared.python.compatibility`.
Used the exact pattern the other modules use, after getting it wrong once:
if TYPE_CHECKING:
from enum import StrEnum
else:
from shared.python.compatibility import StrEnum
My first attempt imported the shim unconditionally, which fixed 3.10 but broke
Mypy -- 16 new errors, because the shim's `class StrEnum(str, Enum)` fallback
loses StrEnum member typing, so every `ClubCameraAction` and
`VariationVisualEvent` member degraded to `str`. The `TYPE_CHECKING` guard gives
the checker the real `enum.StrEnum` and the 3.10 runtime the shim, which is
precisely why the other modules are written that way.
`tomllib` uses the `try/except ImportError -> tomli` fallback already present in
three other test modules.
Also extended `test_python_310_datetime_boundaries.py`, which previously guarded
only `datetime.UTC`, with an AST check for module-scope `enum.StrEnum` plus a
self-test proving it accepts the guarded and shimmed forms and rejects only the
bare one. An unguarded import here is not a style question: it fails collection
and hides every other result on the lane.
Verified on a real Python 3.10.20 interpreter: `club_camera` imports and resolves
StrEnum from the shim. Mypy back to `Success: no issues found in 374 source
files`; 20 tests pass on 3.11; ruff check and format clean.
Left alone deliberately: `tests/test_pendulum_provider_manifest.py` and
`tests/video_analyzer/test_video_analyzer_packaging.py` also import `tomllib`
unguarded, but neither is in this branch's changed set. Fixing them would pull
them into CI's changed-test selection and could surface unrelated failures for no
benefit here.
dieterolson
added a commit
that referenced
this pull request
Aug 15, 2026
…ta CI (#4480) Three tests were failing on `main` itself, invisible because Tools selects tests from changed files — so `main`'s own delta CI never put these files in its changed set. Any branch that merely touched them inherited the failures and appeared to have caused them. - `test_each_downstream_declares_its_required_sparse_scope` - `test_upstream_scope_includes_every_release_build_package_root` - `test_refresh_user_functions_system_exit_propagates` Fixes, per side-of-truth rather than to make the mirror agree: - **Workflow was wrong -> fixed the workflow.** `src/chat`, `src/contracts.py`, `src/python/src/utils` and `src/sidekick` exist in neither form on UpstreamDrift's default branch (verified via the API, not a local clone). Removed rather than replaced with a guess — a test asserting a nonexistent path is a vacuous gate (see #4477). - **Test expectation was stale -> fixed the test.** `REQUIRED_SPARSE_PATHS` becomes `{src/shared, tests/shared_contracts, tests/support}`, and the release-build-roots assertion becomes `{"src/shared"} <= scope`. Deliberately NOT bare `src`: the test asserts `"src" not in upstream_scope`, so narrowness is a design constraint, not drift. Declaring `src` would have satisfied the mirror while violating an explicit assertion. - **`raise SystemExit(1)`** replaces `import sys; sys.exit(1)` in the rotation-converter test. The scripting sandbox now blocks `import sys`, so the old form never reached `sys.exit` and `SystemExit` was never raised — a stale test defeated by a correct security change. Verified: 15 passed across both files on 3.11 (was 3 failed); ruff check and format clean; assertion gate passes; YAML valid; all three files keep their existing line endings, so the CRLF workflow file shows a content-only diff (see #4479 for the underlying `.gitattributes` gap). Reviewer context: the Cross-Repo workflow's last *completed* run on `main` was a failure (2026-08-06). This PR makes the *declaration* honest; it does not claim the job is green end to end. `vendor/ud-tools` and the submodule-init step are owned by #4447 and deliberately excluded. `tests/fixtures` does exist and is seeded onto `sys.path` by UpstreamDrift's vendoring test — flagged as a possible further gap, not folded in here. Unblocks #4447 and #4446, which inherited these failures by touching the same files. Filed as #4481.
added 2 commits
August 14, 2026 19:20
#4480 landed the three fixes for tests that failed on `main` but were never selected by its delta CI. Re-syncing clears the last known cause of this branch's `tests (3.11)` failure. One conflict, in the release-build-package-root assertion, resolved as the union: #4480's corrected `{"src/shared"}` plus this branch's `vendor/ud-tools`, which is the pinned Tools gitlink UpstreamDrift's own test_tools_vendoring.py resolves against. I checked the auto-merged regions on content rather than trusting them, since this is the exact file pair I mis-resolved two merges ago. Both are correct: the workflow's UpstreamDrift scope is #4480's cleaned list plus `vendor/ud-tools` with the submodule-init step intact, and REQUIRED_SPARSE_PATHS carries the same four entries -- so the mirror and the workflow agree, which is the property the test exists to enforce. Verified: the three formerly-failing tests now pass (16 passed on 3.11), mypy clean over CI's 374 files, ruff check and format clean over 584, changed-test assertion and module-size gates pass, no conflict markers, no gitlinks.
…n-morris-2026-08-13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Consolidates the variation / Morris-sensitivity draft family (34 open draft PRs) into one branch against
main.Supersedes
Every PR below has been verified by ancestry check to be a true ancestor of this branch, so closing it drops nothing. Verified with
verify_coverage.sh:covered=34 NOT-covered=0 SAFE, and independently against each PR's currentheadRefOidfrom the API (not from a cached branch table).Supersedes #4393, Supersedes #4394, Supersedes #4395, Supersedes #4396, Supersedes #4397, Supersedes #4398, Supersedes #4399, Supersedes #4400, Supersedes #4401, Supersedes #4403, Supersedes #4404, Supersedes #4405, Supersedes #4407, Supersedes #4412, Supersedes #4413, Supersedes #4414, Supersedes #4415, Supersedes #4416, Supersedes #4417, Supersedes #4422, Supersedes #4423, Supersedes #4424, Supersedes #4425, Supersedes #4426, Supersedes #4427, Supersedes #4428, Supersedes #4431, Supersedes #4432, Supersedes #4435, Supersedes #4440, Supersedes #4441, Supersedes #4442, Supersedes #4443, Supersedes #4444
Epics
This family closes no leaf issues. It advances epics only:
Part of #4142
Part of #4433
Part of #4120
Part of #4206
(#4206 arrives via #4417, which had absorbed the already-merged #4436.)
Why merging the 7 chain tips was not sufficient
The brief assumed a chain tip contains everything below it. That is false here.
#4417's branch head advanced after its six children branched off it: it now carries89563be74+87719a266(Sasho rotational AoA) via a merge of #4436, which is itself already MERGED into that feature branch and exists on no other branch and not onmain. Those two commits are absent from all seven tips. They are merged here explicitly, so #4417 can be closed without stranding #4436's work.#4424and#4423reportedAlready up to date— they were genuinely contained by the other tips. Confirmed by ancestry, not by assumption.Blocking defects fixed
Unreachable gitlinks (the repo-wide blocker). Removed the six mode-
160000entries under.codex-worktrees/. They are not declared submodules (no.gitmodulesanywhere) and the commits they point at exist only in one local clone, on no remote.mainhas zero of them. Verified:git ls-tree -r HEAD --name-only | grep '^\.codex-worktrees'is empty, and no160000mode remains anywhere in the tree. The.gitignoreline that prevents recurrence is owned by the CI/infra consolidation, not this branch.quality-gateFormat Check would have failed on 91 files. Slices in this stack reformatted files with an older ruff, reverting them to the pre-0.9 wrapping style (assert hasattr(\n a, b\n), "msg"instead ofassert hasattr(a, b), (\n "msg"\n)). I confirmedorigin/mainis format-clean under the CI-pinned ruff 0.14.10 while this branch was not, so the regression is the family's. Only 1 of the 91 files israte_of_closure/variation code — the other 90 are collateral churn in unrelated trees. Reformatted with 0.14.10. The CI-excluded prefixes were deliberately left untouched.ruff checkwould have failed with 9 × F841. A slice wrapped nineapp = QtWidgets.QApplication…statements across three lines intests/unit/sidekick/test_sidekick_ux_hardening.py, moving# noqa: F841off the line ruff reports the diagnostic on. Restored main's single-line form.tests (3.10)would have failed at collection.tests/unit/sidekick/agent/test_action_audit.pyhad been rewritten tofrom datetime import UTC, which does not exist on Python 3.10 — a regression of the fix SPEC 1.1.352 recorded for this exact file. Restored main'stimezone.utcform. Root cause worth a follow-up: the repo's AST guardtests/rate_of_closure/test_python_310_datetime_boundaries.pyonly walkssrc/rate_of_closure, so it structurally cannot catch this class of regression intests/or in any othersrctree.No raw conflict markers:
git grep "<<<<<<< HEAD"is empty.quality-gateType Check (Mypy) failed with 70 errors in 27 files — and every one of those 27 files is a file that does not exist onmainat all. 428 of the 537 changed source files here are new. Because each source PR was based on its parent's branch, its changed-file delta only ever contained its own slice; once a file was introduced in slice N, no later slice re-checked it, and no PR in the family ever type-checked it againstmain. That is why all 34 sources show a green Mypy step while the consolidation did not. Fixed all 70 — 16 numpyno-any-return/var-annotated(annotated locals), 16arg-typein_kinetics_dynamics.py(explicitfloat()at scalar-indexing boundaries), 16arg-typefromdict[str, object]inference being**-unpacked into typed constructors, 5attr-defined/indexinlauncher.py(root cause: the unannotatedGUI_INFOliteral), 4redundant-cast, plus one each ofhas-type, Literal narrowing,FrozenJsonValue, and an untyped QtcurrentData(). All behaviour-preserving; the one public signature I briefly tightened was reverted in favour of a call-site fix.quality-gateChanged Test Assertion Check failed on sixsrc/shared/python/swing_sim/**/tests/__init__.pypackage markers (five docstring-only, one empty). Added them toscripts/test_assertion_allowlist.txt, following the check's own guidance and the existingsrc/movement_optimizer/tests/**precedent.pyproject.tomlandtool_manifest.yamlhad been converted from LF to CRLF by this family, so both rendered as near-total rewrites. Restored LF: their real change is 35 added lines, not 802 changed ones. These were the only two files in the 1249-file diff with a newly introduced CRLF conversion.The web build was broken, and a real behavioural regression was hiding behind it.
npm run build(i.e.tsc) failed, which is why "Rate web production Worker E2E" could not even start its preview server — that check passes on all four source PRs that carry it, so the breakage is the integration, not any one slice. Two distinct cross-slice defects:(a) Type error. feat(variation): bind runtime replay identity #4431 made
executionMetadatarequired onVariationExecutionRequest/VariationExecutionResult, but four test fixtures introduced by the feat(rate): add bounded club explorer camera #4444 chain construct those objects without it. Supplied it the way the already-updated fixtures in the same file do — from the request under test, which also satisfiesvalidateResult's request/result metadata equality check.(b) A user-visible regression, and the most consequential thing I found.
importPlanreports provenance after loading a plan — either "resolves against the current variable registry … not evidence of historical reproducibility" for a raw plan, or "Execution sidecar verified against the current registry" for a signed document. The feat(rate): add bounded club explorer camera #4444 chain added an effect that callsinvalidateResultson every configuration-identity change; loading a plan changes that identity, so the effect ran after commit and overwrote the provenance message with the generic "Ready: configuration changed; run again." The user was silently denied the one message that tells them a loaded plan was re-resolved against today's registry rather than its recorded one — an honesty regression in a suite whose whole theme is honest provenance.invalidateResultsnow announces only a discard that actually happened, decided from refs so the callback identity stays stable and the effect cannot re-trigger itself. Nothing else references that string, and the invalidation tests assert visual state and heading removal rather than status text.Two React tests (from feat(variation): bind runtime replay identity #4431's side) correctly detected (b) and were failing; they now pass. Web workspace:
tscclean,eslint --max-warnings 0clean,vite buildsucceeds, vitest 1084/1084 across 126 files (was 1082/1084).The family's Python test suite had never run in CI at all, and once run it revealed five more cross-slice contract contradictions.
pick-runnernever granted any of the 34 drafts a fleet slot, sotests (3.11)was never even created on a single one of them — every "green" source PR was green onquality-gatealone. I built a Python 3.11 environment with CI's pinned numpy/scipy/pandas/PyQt6 and ran the suite. Five real failures, none caused by the merge; each is one slice's contract rejecting another slice's code, where no branch contained both halves:(a) The RNG-replay contract vs the explicit-design seam — the most serious. feat(rate-of-closure): produce paired localized attribution #4426 added
build_simulation_ensemble_request_from_samplesfor "deterministic experimental designs whose rows are the scientific authority … rather than pseudorandom Monte Carlo draws". feat(variation): bind resolved execution metadata #4428/feat(variation): bind runtime replay identity #4431 then madeSimulationEnsembleRequestrequire unconditionally thatsampled_inputsequalsample_inputs(plan). Together the request contract rejects exactly the designs the seam exists to carry: 7 tests failed and the entire paired-attribution producer was non-functional. Reconciled by making the provenance explicit —sample_provenancedefaults toplan_rngso every existing caller keeps the reproducibility guarantee bit-for-bit, and the explicit seam declaresexplicit_design, which skips only the RNG-equality check. Shape, finiteness, and_require_config_sample_binding— the check that actually proves each row was executed as written — all still apply. The same contradiction also broke a benchmark script and two archive tests.(b) A run may no longer be attributed to a config it did not come from.
capture_simulationgained a config-identity guard; a Morris test injected pre-computed runs built from other configs. The guard is correct, so the test changed: the hit-availability case now asserts againstproject_simulation_outcome, which owns that rule, and the miss goes through the real evaluator end to end.(c) NaN where a null belongs.
launch_monitor_importreturnedNaNfor an empty CSV cell, because from pandas 3 a bare DataFrame construction coercesNonein an object column. The test's own name says this import mirrors browser policy, which yieldsnull. Built withdtype=objectso an absent value stays absent instead of silently becoming a floating-point quantity.(d) Eight paired-study controls had no tooltips, failing the repo-wide tooltip-completeness contract that a different slice owns.
(e) A request-identity test asserted identity by mutating sampled inputs in place, which is now unconstructable twice over. The sample-bytes case rebinds each config to its row; the config-order case now asserts the stronger property the binding provides — a misordered request is rejected outright rather than merely hashing differently.
Result:
tests/rate_of_closure/is 1451 passed, 0 failed on Python 3.11. One further failure reproduced only on 3.13 (a JSON nesting-depth error-taxonomy difference) and passes on 3.11, so it is untouched.Local reproduction note
Reproducing
quality-gateon Windows requiresMYPYPATH=src;src/python/srcwith a semicolon. CI is Linux and uses:; on Windows that colon string parses as one nonexistent directory, every first-party import silently degrades toAnyunder--ignore-missing-imports, and mypy reports a fabricated result. I measured both on this branch's exact 418-file list: semicolon givesSuccess, colon gives 109 errors in 13 files — a different, bogus set. Cross-module resolution also requires passing all 418 files to a single invocation via mypy's@listfileform (notxargs, which splits on Windows), numpy<2.4, and mypy pinned to 1.13.0. My initial semicolon run reproduced CI exactly: the same 27 files and 70 errors.Substantive conflict resolutions
Two conflicts were more than textual, and both were resolved against the incoming side.
request_builder.py— a mis-merge that would have silently destroyed the paired-attribution design. Git aligned #4431's Monte Carlo function body against the #4444 chain's new explicit-sample seam, so the incoming side insertedinside
build_simulation_ensemble_request_from_samples— the function whose whole contract is that its caller-supplied rows are the scientific authority (planted baseline/perturbed pairs). Taking that side would have replaced an explicit design matrix with pseudorandom draws while every test still passed. Rejected. Execution metadata is now supplied by the sampling caller and staysNoneon the explicit seam: the metadata carries an RNG replay identity, and rows never drawn from that stream cannot be replayed from it, so claiming it would be a false provenance assertion.simulation_adapter.py—assert execution_metadata is not Nonebecame aNone-tolerant identity override for the same reason. An injected executor still can never be reported as the pinned production implementation.Remaining resolutions, all union-of-both-sides: attribution wiring re-homed from the eager
_on_ensemble_succeededinto_apply_prepared_resultso it publishes only for an accepted result (guarded byauthority() is Noneper #4427, and not cleared by_clear_result_widgets, so explicit paired authority keeps its own lifecycle);EnsembleStreamHeaderfields and validations; the TS execution-metadata contract (the prepared request now feeds bothvalidateExecutionRequestandvalidateResult); #4425's flight-model check kept alongside the stricterisSafeIntegernRuns check; #4427's value-based scenario comparison (strictly narrower than the identity check it replaced); and the dated sections in SPEC/handoff docs.Correctness findings — read before merging
These are defects in the consolidated work, not in the consolidation. None is a merge error. I am reporting them rather than fixing them because each is a design decision for the epic owner.
1. There is no TypeScript Morris implementation, despite a branch named
codex/4142-morris-typescript-parity. The Morris numerics exist in exactly one place:src/shared/python/swing_sim/variation/global_sensitivity.py. The TypeScript side is a wire parser plus an algebraic invariant checker.src/rate_of_closure/variation/morris_rate_adapter.pyandmorris_execution.pycontain zero effect arithmetic. So the recurring Python/TS algorithm divergence cannot occur here — but the "parity" framing overstates what exists, and there is no second implementation to cross-check against.The TS check that does exist is genuine, not decorative:
morrisMetricValidation.ts:39-63enforcessigma² − n·SE² − c·muStar² + c·mu² ≈ 0withc = n/(n−1), which is an exact identity given Python'sddof=1estimators, and would fire if Python switched toddof=0. Zero-clamp thresholds match exactly (64 * eps * max(1, muStar)on both sides). Its limitation is structural: it validates a relation among metrics, so a uniformly wrong scale factor passes.2. The Morris estimator has exactly one genuine numeric validation, and it is scale-blind.
test_global_sensitivity.py:89-114uses response2·x₀ + 3·x₁over bounds[0,1], so closed-form elementary effects are exactly 2 and 3. That is real ground truth. But every numericmu_starassertion in the repo runs on factors withlower=0.0, upper=1.0, where normalized and physical coordinates coincide. Elementary effects are computed per normalized factor range (global_sensitivity.py:173divides bysigned_steps, which are in[0,1]units), and no test can currently distinguish "per normalized range" from "per physical unit."test_morris_rate_adapter.pydoes use non-unit bounds but contains zeromu_starassertions. This is the highest-value gap I found.3. Parity-only tests (agreement asserted, correctness not).
morrisUiParity.test.ts(both tests),test_morris_ui_contract.py::test_python_generated_ui_fixture_is_exact_and_shared,test_web_parity_fixture.py(both tests),variation.test.ts::"matches the fixture dispersion within the loose band",morrisGlobalSensitivityContract.test.ts::"parses the Python golden fixture…",morrisPresentation.test.ts::"ranks finite effects…"(itsmuStar3 and 2 are read from the fixture), and themorris_workspace_v1.jsonconsumers. One test is mislabeled as parity and checks nothing cross-runtime:morrisAuthorityRequest.test.ts::"matches Python R13.6 base-centered suggestions…"reads no Python artifact — its ten expected bound pairs are hardcoded TS literals, so Python drift cannot fail it.To be fair to the fixtures:
morris_ui_parity_v1.jsonandmorris_global_sensitivity_golden_v1.jsonare genuinely two-sided (each is pinned by a Python test and a TS test, so a one-sided change fails exactly one), and no regeneration script exists for any fixture, so none is auto-derived from one side. The golden fixture'smu_starvalues coincide with the analytically-asserted 2.0/3.0, making it the one fixture transitively anchored to closed-form truth.4.
variation_parity.jsonis effectively vacuous as a correctness gate. The TS side acceptsmean_abs_toleranceof 8.0 m on a 216.73 m mean (3.7%) andstd_rel_toleranceof 0.4 (40%). A browser engine with a 39% dispersion error passes. The Python test's own docstring concedes exact RNG parity is not attempted.5. #4425's flight-model pin contradicts the Morris slices in this same stack. Three policies now coexist:
VariationPlan(spec.py:283)FlightModelTypemembersvariationSchema.tsvalidatePlanwaterloo_penner)morrisAuthorityRequest.tsAUTHORITY_FLIGHT_MODELSA plan with
flight_modelin {macdonald_hanzely,nathan,ballantyne,jcole,rospie_dl,charry_l3} is valid in Python, round-trips throughto_json_dict, and is rejected by the browser — and accepted by the Morris path in that same browser. The reverse cannot happen. #4425's error message ("unsupported for browser variation") makes this honest rather than silent, and #4425's Python-side change is sound (it requires plan and config to agree, without restricting the set). But the browser is now internally inconsistent, andSUPPORTED_VARIATION_FLIGHT_MODELhas no test asserting the rejection or documenting the asymmetry.6.
normalized_stepcan be reported inaccurately and neither runtime can detect it._validate_design_pathsnever requires|signed_steps| == delta, nor that points lie on thek/(levels−1)lattice. TSparseDesignre-deriveslevels/(2·(levels−1))fromlevels— validating the field against itself, not against the divisor actually used.MorrisResults.tsxthen displays that number to the user.7. Smaller divergences, all currently latent but not guarded: the Morris workspace CSV export has 39 Python columns vs 35 TS, with different order and different names for the same data (
source_time_window_start_svssource_time_start_s,design_levelsvslevels, …) and four Python-only columns — each side asserts only its own header, and nothing compares the two.OUTPUT_LABELSis duplicated (23 Python entries vs 17 TS) and already out of sync.variationRegistry.tsis a hand-mirror ofregistry.py, including thetypicalScalevalues that drive every Morris suggested bound, with no test pinning the two together (I compared the 10 Morris entries by hand — they agree today; nothing keeps them agreeing). Presentation tie-breaks differ (Python codepointspec_idvs TSlocaleCompare), as do fallback labels (str.title()vs first-char capitalization:"carry_2m"→"Carry 2M"vs"Carry 2m"). Finally,application/morris/router.py:238"verifies" a result by callinganalyze_morrison the same inputs and comparing — tautological; it can catch transport corruption but never an algorithm error.What I could not verify
tests/rate_of_closure/, the Rust wheel build, or the Playwright PyQt-DPI lane.execution_metadata=Noneon the explicit-sample seam is a judgement call, not something a test forced. It is the honest reading (no RNG was used, so no RNG replay identity should be claimed) and it is consistent with the stack's own "model identity honesty" theme, but if the epic owner intends explicit designs to carry metadata, it needs a non-RNG provenance variant rather than reusingmake_execution_metadata.src/data_processing/are changed by this family and are not ruff-format-clean under 0.14.10. They sit under a CI-excluded prefix, so the gate does not see them, and I left them untouched per the exclusion rule. Flagging so it is not mistaken for clean.Gates run locally
Reproduced with CI's own pinned tools, commands, and file lists:
ruff check(pinned 0.14.10), 596 in-scope changed files and full-repo: clean.ruff format --check(pinned 0.14.10): clean.mypy(pinned 1.13.0, CI's exact 418-file list and flags): Success, no issues.scripts/check_test_assertions.py --changed-files: passed.scripts/check_minimum_test_contract.py: passed.scripts/check_module_size_budget.py --max-lines 1200 --include src: passed.bandit -ll -iiover the 372 changed src files: 0 medium, 0 high.git grep "<<<<<<< HEAD": empty.git ls-tree -r HEAD | grep '^160000': empty.verify_coverage.sh: safe=34, NOT-covered=0, SAFE.requirements.txtis untouched, so pip-audit is unchanged frommain.file-size-budgetis not a required check here, and I have not refactored any module to satisfy it.Merge note
mainrequires linear history, so this must land via squash, not a merge commit. Squashing collapses 34 PRs' worth of slice history, so the provenance above is the only surviving record — please keep it in the squash message.🤖 Generated with Claude Code