Skip to content

feat(rate-of-closure): add launch monitor analytics tabs - #4212

Merged
dieterolson merged 5 commits into
feat/4181-launch-monitor-registryfrom
feat/4205-launch-monitor-analytics
Aug 7, 2026
Merged

feat(rate-of-closure): add launch monitor analytics tabs#4212
dieterolson merged 5 commits into
feat/4181-launch-monitor-registryfrom
feat/4205-launch-monitor-analytics

Conversation

@dieterolson

Copy link
Copy Markdown
Collaborator

Summary

  • add Launch Monitor Analytics as a persistent primary tab in the Rate of Closure PyQt6 and React/Vite applications
  • retain every imported CSV/JSON source column and allow arbitrary numeric outcomes with multiple predictors
  • provide Pearson/Spearman/Kendall association, BH correction, multivariable OLS uncertainty, residual diagnostics, grouping, scatter visualization, SHA-256 lineage, and JSON exports
  • consume the feat(rate-of-closure): add launch monitor convention registry #4203 Python/TypeScript convention registries and retain TrackMan-Comparable / Foresight-Comparable language without device-emulation or certification claims
  • preserve old persisted tab orders by appending the stable new tab ID automatically

Stack

This draft intentionally targets feat/4181-launch-monitor-registry (#4203), the authoritative shared convention/provenance foundation identified for the active Impact Zone Model stack.

Verification

  • python -m pytest tests/rate_of_closure -q — 583 passed
  • focused Ruff — passed
  • focused MyPy — passed
  • npm test — 374 passed
  • npm run type-check — passed
  • npm run lint — passed
  • npm run build — passed
  • in-app rendered layout and Run Analysis interaction — passed with no console errors

Relates to D-sorganization/UpstreamDrift#8364
Closes #4205

@dieterolson

Copy link
Copy Markdown
Collaborator Author

Engineering hardening follow-up 4b22e79 splits the analytics Python/TypeScript facades into focused contract, statistics, parsing, and fingerprint modules; all production modules are now <=361 lines and the spec trailing whitespace is fixed. Public facade APIs are preserved. Validation: 583 Rate of Closure Python tests, 374 React tests, focused analytics tests, TypeScript type-check, ESLint, production build, Python 3.12 mypy, Ruff, Black, module-size and diff checks passed. Python 3.13 mypy hit an upstream internal cache assertion; the CI-relevant 3.12 lane is clean.

@dieterolson

dieterolson commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator Author

CI recovery is now published on exact head a4dcddd.\n\nResolved protected-check failures from earlier heads:\n- CI-pinned Ruff formatting for src/rate_of_closure/launch_monitor_analysis.py.\n- Narrow detect-secrets allowlist annotation on the published SHA-256 abc test vector; no baseline or broad exclusion change.\n- Pinned mypy 1.13 Literal typing at the PyQt combo-box boundary and distinct correlation/coefficient loop types; the shared analysis contract was not weakened.\n\nLocal evidence:\n- Ruff check and format: pass\n- focused detect-secrets scan: zero findings\n- React analytics: 5 passed\n- TypeScript type-check: pass\n- ESLint, zero warnings: pass\n- Python fail-closed/missingness boundary: 1 passed\n- PyQt analytics tab: 2 passed\n- exact mypy 1.13 adapter check: pass\n- Prettier and git diff --check: pass\n\nThe full hardening evidence remains 583 Python tests and 374 React tests, plus build, type, static, and module-size gates. The current handoff is docs/development/LAUNCH_MONITOR_ANALYTICS_HANDOFF.md.\n\nThis PR remains draft. Fresh protected checks and required review are still required; no checks or review controls have been bypassed.

@dieterolson
dieterolson marked this pull request as ready for review August 7, 2026 02:08

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a4dcddde61

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +117 to +119
missingPolicy: missing, groupBy: groupBy || undefined,
confidenceLevel: confidence, minSamples,
}));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Let users opt in to aggregate correlations

In the React panel, every request omits allowAggregate, so an imported dataset containing observation_kind values other than shot always reaches the Aggregate observations require allowAggregate=true error—even when the user selects correlation-only mode, which the shared contract explicitly supports. Add an opt-in control and pass its value; the desktop request construction has the same omission.

Useful? React with 👍 / 👎.

Comment on lines +58 to +61
const columns = [...identity, ...selected];
return sha256(JSON.stringify(rows.map((row) => Object.fromEntries(
columns.map((column) => [column, row[column] ?? null]),
))));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Fingerprint every retained source field

The displayed dataset SHA-256 covers only the selected analysis columns plus four identity fields. If an imported source URL, environment, unit, monitor setting, or any other retained provenance field changes, the analysis export still reports the same fingerprint, so the hash cannot identify the dataset it claims to trace. Canonicalize and hash every retained row field rather than only columns.

Useful? React with 👍 / 👎.

Comment on lines +192 to +195
const pValue = method === "kendall"
? 2 * (1 - normalCdf(Math.abs(coefficient) * Math.sqrt(
9 * count * (count - 1) / (2 * (2 * count + 5)),
)))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Correct Kendall significance for tied measurements

When either selected variable contains ties, the coefficient is Kendall tau-b, but its p-value is calculated with the no-ties variance formula. Rounded and categorical launch-monitor measurements commonly contain ties, so this produces incorrect p-values and consequently incorrect Benjamini-Hochberg adjusted values; use a tie-corrected Kendall variance or a validated statistical implementation.

Useful? React with 👍 / 👎.

Comment on lines +122 to +123
let low = -20;
let high = 20;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Expand the Student-t quantile search bracket

For low-residual-degree regressions at the allowed high confidence levels, the required Student-t critical value exceeds 20—for example, a four-row single-predictor regression has two residual degrees of freedom and a 99.9% interval needs a critical value above 30. The binary search therefore saturates at 20 and reports confidence intervals that are materially too narrow; grow the bracket until it encloses the requested probability.

AGENTS.md reference: AGENTS.md:L178-L182

Useful? React with 👍 / 👎.

Comment on lines +132 to +135
setRows(next);
setSourceName(file.name);
setOutcome(nextNumeric[0]);
setPredictors([nextNumeric[1]]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reset grouping when loading a different schema

When a user imports a file without the currently selected grouping column—most immediately, any file without the default monitor_vendor field—the rows, outcome, and predictors are updated but groupBy remains stale. The controlled selector then has no matching option, while Run still submits the stale name and fails with Columns not present; reset grouping to an available column or no grouping when the dataset changes.

Useful? React with 👍 / 👎.

Comment on lines +303 to +306
const design = complete.map((values) => [1, ...values.slice(1)]);
const inverseInformation = inverse(multiply(transpose(design), design));
const beta = multiply(
multiply(inverseInformation, transpose(design)), outcome.map((value) => [value]),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use a scale-aware regression solver

The browser OLS path forms and directly inverts XᵀX, and the inverse routine rejects pivots using an absolute 1e-12 threshold. A valid full-rank predictor whose values vary around 1e-7 produces a post-intercept pivot below that threshold and is falsely reported as rank deficient; differently scaled or nearly collinear launch-monitor variables also suffer the numerical instability of normal equations. Standardize predictors or use a scale-aware QR/SVD solver.

AGENTS.md reference: AGENTS.md:L178-L182

Useful? React with 👍 / 👎.

@dieterolson
dieterolson merged commit 8526f7e into feat/4181-launch-monitor-registry Aug 7, 2026
13 of 20 checks passed
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

⚠️ SPEC.md Update Required

Source files were modified in this PR but SPEC.md was not updated.

Per the Specification-Driven Development Policy:

  • Any PR that adds, removes, or changes functionality must update SPEC.md
  • Update the relevant sections (features, architecture, tests, dependencies, etc.)
  • Bump the Spec Version if making substantive changes

To resolve:

  1. Update SPEC.md to reflect your changes, OR
  2. Add the spec-exempt label if this PR genuinely doesn't affect the spec (e.g., pure refactor with no behavior change)

This check is enforced by the spec-check CI workflow.

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.

1 participant