Rate of Closure Suite: Camera Tracking, Playback, File I/O & Static Web Distribution (consolidated 11 PRs) - #4410
Rate of Closure Suite: Camera Tracking, Playback, File I/O & Static Web Distribution (consolidated 11 PRs)#4410dieterolson wants to merge 387 commits into
Conversation
…n workspaces Expose the qualified Waterloo/Penner capability optimizer as a primary Shot Optimizer module in both clients: strict cross-runtime capability-optimization-workflow/v1 authoring and persistence, off-UI-thread execution with truthful progress and cooperative cancellation, complete scalar-ensemble/v1 cohort retention, ranked alternatives, stage-qualified scatter axes, bounded raw-row paging, spreadsheet-safe CSV, and stable JSON. The React panel is lazy-loaded so the main Vite chunk stays under the 500 kB warning threshold, and saved v1 layouts reveal newly registered modules. Handoff documents are updated in this implementation commit per fleet policy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…t reveal Add PyQt workflow/worker/GUI suites and React workflow, worker-client, run, panel, and results tests for the Shot Optimizer slice; extend primary-navigation coverage so saved layouts reveal newly registered modules and the new tab registers exactly once in both clients. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… gates Add the SPEC 1.14.6 change-log row, document the end-user workflow in the capability optimization spec, and update the campaign handoff with the recovered slice and its verified gate evidence. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
No material source change; handoff pointer update only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cess The dict-splat construction of CapabilityWorkflowInputs failed the hosted delta-mypy gate because **dict[str, float] cannot be proven against the integer fields. Build the snapshot with explicit typed keyword arguments instead; behavior is unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Handoff update for implementation commit 101020b per fleet policy; no source change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The prior note wrongly framed the 3.10 StrEnum ImportError as a stack-wide defect to fix in source. requires-python is >=3.11 and only quality-gate and tests (3.11) are required checks, so the 3.10 lane is a stale-matrix artifact. No source change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The observation contract has only complete/no_impact/failed members, so a horizon nonconvergence is normalized into failed. Reporting a bare "failed N" reads as numerical breakage when the retained reason says the flight simply did not reach the ground inside the configured horizon. Both clients now append the retained reason codes with counts, which is data the adapter already carries per row. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A descending launch starts at z=0 and is already below ground once the t > dt guard permits the crossing check, so the interpolation ratio went negative and extrapolated the crossing to a negative sample time. That raised RangeError: timeS must be nonnegative, which the observation layer absorbed as an untyped evaluator_exception on 12 of 96 samples of a default driver search while Python reported none. Clamping the ratio to [0, 1] keeps the crossing inside the detecting step, so these samples report nonconverged and match the Python runtime. Also builds _lerp_vector's 3-tuple explicitly instead of carrying an unused type: ignore, and coerces _curve to float, clearing the hosted delta-mypy gate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Brings in the evaluator branch descending-launch and delta-mypy repairs. Resolves the two documentation conflicts by keeping both slices: SPEC.md retains the 1.14.6 workspace row above the amended 1.14.5 evaluator row at header version 1.14.6, and the tool handoff keeps the workspace completion record ahead of the evaluator repair entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(rate-of-closure): matched PyQt6/React capability optimization workspaces
feat(rate-of-closure): bind optimizer to full flight
feat(rate-of-closure): stream capability optimizer samples
The per-slice stacked-branch cautions described the stack while it was open and now read as active constraints, so state plainly that #4283, #4289, and #4294 are merged onto this branch, how they were folded, what was verified here (1426 Python, 624 React), and that the incomplete CI matrix reflects 25 of 28 org runners being offline rather than failures. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # AGENT_HANDOFF.md
# Conflicts: # AGENT_HANDOFF.md # SPEC.md # src/rate_of_closure/web/src/model/flight.ts # src/shared/python/swing_sim/flight/tests/test_contract_api.py
# Conflicts: # SPEC.md
Performance Benchmark ResultsNo benchmark results available. |
…baseline, and fix lint
|
Closing as superseded by #4446 ( Why, with evidence. #4409 and #4410 shared ~360 commits, diverged by 49, and neither was an Nothing is lost. This branch still exists on Why now rather than after #4446 merges. Auto-merge (SQUASH) keeps being re-armed on this PR by Also fixed on the way into #4446: this branch carried raw Part of the 2026-08-13 consolidation drive: 103 open Tools PRs -> ~8 consolidated PRs. |
Pull request was closed
The "Reject Raw Merge Conflict Markers" failure on #4409 and #4410 short-circuited `quality-gate` before its Type Check step, so this type debt was never gated. With the markers fixed, mypy reported 138 errors across 42 files -- all 42 of them NEW files added by the consolidated work, none pre-existing on `main`. These are typing fixes only; no runtime behaviour changes. Notably none of them came from the merge: exactly 5 files needed hand resolution (`SPEC.md`, `.secrets.baseline` and three handoff documents) and NOT ONE was Python, so no call site was resolved differently between the two branches. By error code: * `arg-type` (84) -- mostly two patterns. Indexing a 2-D array (`theta[i, 1]`, `y[0]`) yields a scalar at runtime but numpy's stubs type it as `ndarray`, while the callee genuinely needs a scalar because it calls `math.cos`; those sites now hoist `float(...)` locals. The rest are dict literals inferred as `dict[str, object]` and then splatted with `**kwargs`, which defeats keyword type-checking entirely -- fixed with `TypedDict` annotations on the literals (`_StatusCommon`, `_CommonSpecFields`) rather than by loosening any callee signature. Also `tuple(genexpr for i in range(3))` typing as `tuple[float, ...]` instead of `tuple[float, float, float]`, fixed by writing the three elements explicitly. * `no-any-return` (26) -- bound to an annotated local and returned, rather than cast. * `redundant-cast` (18) -- dead `cast(...)` wrappers removed where narrowing already applied, each replaced with an annotated local so the fix also holds where the inner expression degrades to `Any`, and the now-unused `typing.cast` imports pruned so ruff's F401 stays clean. * `var-annotated` (8) -- explicit annotations at the assignment. * `has-type` (1) -- a declaration-only class annotation for a matplotlib base-class attribute that `--follow-imports=skip` cannot see. Verified no class attribute is actually created. * `return-value` (1) -- a documented `cast` where the parameter must stay `object` to remain contravariant with the `CompleteBatchExecution.validator` signature. A cast is a runtime no-op, so the golden-fixture-pinned output bytes are untouched. Two narrowly-scoped `cast`s to `Literal["green", "fairway"]` remain where `TargetDefinition.kind` is declared `str` but `TargetRegion.kind` is a literal union; both carry comments noting `__post_init__` already restricts the domain. Verification, reproducing CI's own file selection (465 files, the changed non-test Python set minus the gate's excluded prefixes) under the pinned `ruff==0.14.10` / `mypy==1.13.0` on Python 3.12 with numpy pinned <2.4 as `requirements.txt` requires: mypy -> Success: no issues found in 465 source files ruff check -> clean (731 gate files) ruff format --check -> clean (731 gate files) `tests/rate_of_closure`: 1167 passed, including the pinned canonical golden-bytes fixture. The two remaining failures are load-induced flakes on this workstation, both passing in isolation -- a loopback-authority readiness timeout that the campaign handoff already documents as happening on a loaded box, and a web-launcher smoke test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…can import it
`tests (3.12)` failed with **9 collection errors, every one of them
`ModuleNotFoundError: No module named 'filelock'`**, which aborted the whole lane
before a single test ran:
tests/rate_of_closure/test_app_toolstrip.py
tests/rate_of_closure/test_regional_ground_authority_api.py
tests/rate_of_closure/test_regional_ground_authority_jobs.py
tests/rate_of_closure/test_regional_ground_authority_store.py
tests/rate_of_closure/test_regional_ground_authority_transport.py
tests/rate_of_closure/test_regional_ground_execution_presentation.py
tests/rate_of_closure/test_regional_ground_loopback_submitter.py
tests/rate_of_closure/test_regional_ground_production_runner.py
tests/rate_of_closure/test_regional_ground_real_loopback.py
`src/rate_of_closure/web_authority/job_store.py` imports `filelock` at module
scope -- it is the process-lifetime lock guarding the durable authority's
SQLite/WAL store, so it is a genuine runtime dependency of shipped `src/` code,
not a test-only helper. But `pyproject.toml` declares it **only** under the
`rate-of-closure-web` and `full` extras, and the `tests` job installs
`requirements.txt` (as `requirements-ci.txt`, which is that file minus the mypy
pin) plus a hand-listed set of packages that does not include it. So nothing in
the test lanes ever installed it.
Declaring it in `requirements.txt` is the right layer: that file is the manifest
CI actually installs, and this matches how the other runtime imports of shipped
code (numpy, scipy, pydantic, fastapi's siblings) are handled there. The line
starts with `filelock>=` so it survives the workflow's `grep -v '^mypy=='`
filter. Verified the file still parses as valid pip requirements.
This is a latent packaging gap in the consolidated work rather than a merge
artifact -- it was invisible on #4409 and #4410 because their `quality-gate`
failed at the conflict-marker step and their `tests` lanes never got a runner.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nstalled With `filelock` declared, the test lanes got past collection for the first time and surfaced three genuine defects. All three are in this consolidated work, and all three were invisible on #4409/#4410 because their `quality-gate` died at the conflict-marker step and their `tests` lanes never ran. 1. `uvicorn` was missing from `requirements.txt`, exactly like `filelock`. `src/rate_of_closure/web_authority/runtime.py` spawns the isolated loopback authority as a `uvicorn` child process, so without it that child died instantly and **seven** tests failed with `RuntimeError: local Python authority exited before readiness` -- six in `test_regional_ground_real_loopback.py` plus the `test_documented_web_launcher_direct_path_smoke` launcher check. `pyproject.toml` declares it only under the `rate-of-closure-web` and `full` extras, which the `tests` job does not install. 2. `tests/rate_of_closure/test_regional_ground_authority_api.py` split PYTHONPATH on a hardcoded `";"`. Production `build_authority_process_spec` correctly joins with `os.pathsep`, so the test only ever worked on Windows; on POSIX the split is a no-op and the whole joined path was compared against `tmp_path`. Now uses `os.pathsep`. (Same class of bug as an `MYPYPATH` separator trap found earlier in this drive -- worth watching for elsewhere.) 3. The cross-client wind golden asserted an ABSOLUTE 1e-12 tolerance on a value of magnitude ~9.79, i.e. ~1e-13 relative, which is below cross-libm reproducibility for a chained `sin`/`sqrt` evaluation. Hosted Linux CI on Python 3.12.13 obtains `9.786440272809793` against the fixture's `9.7864402728063`: **absolute difference 3.494e-12, relative 3.570e-13**. Switched to `rel=1e-9` while keeping `abs=1e-12` for components legitimately near zero. Credit where due: the Codex review bot flagged this as a P1 and its predicted 3.49e-12 drift was exact. I declined to act on it earlier because the golden was bit-exact on my Windows runtime (measured zero drift on both 3.11.9 and 3.12.10) and I was unwilling to loosen a parity tolerance on an unreproducible claim. That was the right call on the evidence then, and this is the right fix now that CI has produced a measured delta -- 1e-9 is ~2800x the observed drift yet still pins 9 significant digits, so a genuine divergence in the shared wind model still fails. Verified locally: the wind golden, the full authority-API suite, every real-loopback test and the launcher smoke check -- **46 passed**. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Consolidates Rate of Closure PRs into a single batch (#4378 #4369 #4274 #4284 #4273 #4192):\n\n- Closes #4339: feat(rate): add matched regional surface plan editors\n- Closes #4342: feat(rate): add canonical regional plan file I/O\n- Closes #4358: feat(rate-of-closure): add canonical camera preset parity\n- Closes #4362: feat(rate): track clubhead in matched camera views (#4284)\n- Closes #4363: feat(rate): add bounded ground-result playback (#4274)\n- Closes #4364: feat(rate): project qualified post-ground spatial targets (#4192)\n- Closes #4368: feat(rate): add regional-ground request file controls (#4273)\n- Closes #4371: fix(rate): type regional outcome validation failures (#4369)\n- Closes #4376: feat(rate-of-closure): recover durable authority jobs\n- Closes #4388: Rate of Closure: qualify deterministic static web distribution\n- Closes #4402: Add Proximal–Distal Dynamics Companion Guide