Skip to content

feat(design-report): state where sigma comes from, and how precise it is, at the observed T (#114) - #124

Merged
cnicholas merged 2 commits into
mainfrom
feat/series-length-precision
Sep 15, 2026
Merged

cnicholas merged 2 commits into
mainfrom
feat/series-length-precision

Conversation

@cnicholas

@cnicholas cnicholas commented Sep 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • What: one line under Structure in the design report naming where the sigma behind the limits comes from at the observed structure and series length. Exposed as study.series_length (a frozen SeriesLengthPrecision) and study.series_length_description.
  • Why: the series-length half of Series length (T) as an axis in design-state admissibility — and a saturation question #114. Tom's position is that judgment belongs to the analyst, not to a prescribed rule, so the report states a fact and attaches no threshold, label, or warning. The design state, the recommended chart, and the analysis menu do not move with T; the line sits beside the state, not inside it.
  • Scope: series_length.py (new, pure), spc_constants.py (the MR_SIGMA_INTERVAL_80 table, carried on the result for callers, not printed), study.py (two properties, one DesignReport field and one report line), api.md, key-concepts.md, CHANGELOG, tests/test_series_length.py.

The six forms the line takes, wording per Tom (no degrees of freedom, no estimates, no "stable process"):

Series length: T=4. Sigma for X/mR rests on 3 moving ranges.
Series length: T=1. Sigma rests on within-cell replication.
Series length: Sigma rests on within-cell replication.             (replicated, no time variable)
Series length: T=8. Sigma for X/mR rests on 7 moving ranges.       (partial replication)
Series length: T=60. Sigma for X/mR rests on 59 moving ranges.
Series length: T=2. Sigma for X/mR rests on a single moving range.

No time variable and no replication prints nothing. within_cell_df and mr_interval_80 (the p10/p90 of MRbar/d2 by n = 3..30, from validation/short_series_bands.py, contributed by @rabujamra in #114 / #119) ride on the result for anyone who wants the numbers in code.

Contract / invariants

  • Defaults unchanged — no chart math, no detection change. validation/e2e_bishop_report.py exits 0 and docs/reference/validation.md is unchanged.
  • Residuals unaffected.
  • Row/index alignment preserved — n/a.
  • Output schema compatibleDesignReport gains one field with a default, appended last; positional construction is unaffected. Two new read-only Study properties.
  • Pinned error strings unchanged.
  • ADS/ODS/PDS, recommended_chart, valid_charts identical at T = 3 and T = 300 on the same structure (test_design_state_and_menu_do_not_move_with_T). No warning is emitted (pinned).

Behaviour changes

  • study.design() prints one extra line whenever there is something to say. That is the only visible change.

Methodology

  • No methodology change — a statement of where sigma comes from, with no gating.
  • The sentences live in one place, processbehavior/series_length.py.

Tests

  • TestAssessSeriesLength — the six forms exactly; the retired words ("short", "adequate", "provisional", "warning", "degrees of freedom", "estimate", "stable process") never appear; frozen result.

  • TestIntervalTable — covers n = 3..30, narrows monotonically, and rows n = 4 and n = 20 regenerate from the validation script's seed scheme to three decimals.

  • TestStudySurface — the reporter's four-point shape, Tom's T = 1 replicated file shape, replication with no time variable, T-invariance of the design state, and no warning on a short series.

  • pytest tests/ — 2360 passed, 10 skipped

  • ruff check . — clean

  • mypy processbehavior — 17 pre-existing errors, none new

  • Golden masters untouched

Notes

  • The three tutorials whose committed output shows a design report (coffee-shop, sds-validation, sds1-complete-analysis) will show the new line when next re-executed; not re-run here.
  • The docs page that explains the position at length is not in this PR; the API reference and key concepts carry the short version.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BKphCi1LC1hjGYteWEK9JV

… is, at the observed T (#114)

## Summary
- **What:** one line under Structure in the design report, plus study.series_length /
  study.series_length_description, and the MR_SIGMA_INTERVAL_80 table in spc_constants.
- **Why:** #114's series-length question. Tom's position: judgment belongs to the analyst,
  not to a rule. So the report states a fact — where sigma rests at this structure and the
  80% interval of the moving-range estimate at this T — and attaches no threshold, label,
  or warning. ADS 2 is ADS 2 whether T is 4 or 400; the line sits beside the state.
- **Scope:** series_length.py (new, pure), spc_constants.py (table), study.py (two
  properties, DesignReport field + line), api.md, key-concepts.md, CHANGELOG, tests.

## Contract / Invariants (must remain true)
- ADS/ODS/PDS detection, recommended_chart, valid_charts and the analysis menu unchanged
  and independent of T (pinned: test_design_state_and_menu_do_not_move_with_T).
- No chart math; validation/e2e_bishop_report.py exit 0, validation.md unchanged.
- DesignReport field appended with a default; positional construction unaffected.
- No warnings emitted (pinned).

## Behavior Changes (explicit)
- design() prints "Series length: ..." after Structure whenever there is something to
  say (time variable present, or replication present). Nothing when neither.
- Sentences: unreplicated 3..30 -> interval from the table; >30 -> bounded by the n=30
  row; T=2 -> single moving range; replicated -> within-cell degrees of freedom, not T;
  partial replication -> both facts.

## Tests
- tests/test_series_length.py: the pure function on every branch; no verdict words;
  frozen; the table covers 3..30, narrows monotonically, and rows n=4 and n=20
  regenerate from the validation script's seed; Study surface on the reporter's shape,
  Tom's T=1 replicated shape, no-time replicated, and the T-invariance of the design state.

## Manual Verification
- pytest tests/: 2360 passed, 10 skipped
- ruff check .: clean; mypy: 17 pre-existing errors, none new
- validation/e2e_bishop_report.py: exit 0
…sigma

Per Tom: no degrees of freedom, no estimates, no 'stable process' in the
report sentence. Six forms:
  T=4. Sigma for X/mR rests on 3 moving ranges.
  T=1. Sigma rests on within-cell replication.
  Sigma rests on within-cell replication.            (no time variable)
  T=8. Sigma for X/mR rests on 7 moving ranges.      (partial replication)
  T=60. Sigma for X/mR rests on 59 moving ranges.
  T=2. Sigma for X/mR rests on a single moving range.
within_cell_df and mr_interval_80 stay on SeriesLengthPrecision for callers;
the report prints only the sentence. Tests pin the six forms and forbid the
retired words. pytest: 2360 passed; ruff clean; validator exit 0.
@cnicholas
cnicholas merged commit 139e357 into main Sep 15, 2026
17 checks passed
@cnicholas
cnicholas deleted the feat/series-length-precision branch September 15, 2026 00:40
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