diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 54b6c97..175d563 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.0.2 +current_version = 0.0.3 commit = true tag = false tag_name = v{new_version} diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index f1ef708..b27913f 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -54,15 +54,20 @@ and every module's behavior. Consult the relevant spec before extending a module; if implementation forces a contract change, the spec is updated in the same change and its `semver` bumped. +Reproduced defect evidence, measurements, source locations, and +implementation material live in `.claude/findings/` — never in a spec. + - [mathToolsArchitecture.md](specs/mathToolsArchitecture.md) — umbrella: layering, package layout, dependency policy, shared conventions, error semantics -- [templateConformance.md](specs/templateConformance.md) — template - migration: packaging, Makefile/CI parity, rename, governance docs +- [templateConformance.md](specs/templateConformance.md) — packaging, + dependency resolvability, CI install parity, governance artifacts - [precisionTimeMath.md](specs/precisionTimeMath.md) — `PrecisionTimeInterval`, `PrecisionTimestamp` - [spatialMath.md](specs/spatialMath.md) — `Position`, `Quaternion`, `SpatialPose` +- [sphericalGeometry.md](specs/sphericalGeometry.md) — unit-sphere arcs and + small circles, transforms, the `orient` bearing convention - [waveformCore.md](specs/waveformCore.md) — `Waveform1D` + aggregate waveform containers - [waveformDsp.md](specs/waveformDsp.md) — DSP families, scipy mapping, diff --git a/.claude/archive/math-tools-port.md b/.claude/archive/math-tools-port.md new file mode 100644 index 0000000..19e135c --- /dev/null +++ b/.claude/archive/math-tools-port.md @@ -0,0 +1,30 @@ +--- +version: 1.0 +type: retrospective +name: math-tools-port +purpose: Concise record of the completed py-MathTools template migration and Swift math capability port +scope: project +status: complete +last_updated: 2026-09-24 +semver: 0.0.1 +author: Nicholas Bergantz +--- + +# Math Tools Port Retrospective + +## Goal + +Bring py-MathTools onto the py-foundationTools template conventions and implement the Swift `FoundationMathTypes` capability set as the Tier-3 Python math layer. + +## Outcome + +The 57 implementation and corrective-action chunks completed the precision-time, spatial, waveform, DSP, polynomial, and online trajectory generation surfaces. The final recorded gate passed Ruff, strict mypy, and 1,550 tests. The original chunk-by-chunk plans and resolution notes remain available in Git history, principally commits `24582be` and `6002a9a`. + +## Preserved Decisions + +- `Position` and `SpatialPose` arithmetic may return base types for subclasses. No in-repository subclasses existed; revisit only when subclass preservation is required. +- `SpatialPose.inverse` and `UnivariatePolynomial.derivative` remain methods. Changing them to properties would be a breaking cosmetic change. +- Behavioral test coverage for spherical geometry and `math_plot_helpers` was deferred from the original port. Current spherical defects and required outcomes are tracked separately in the active findings and specifications. +- `WaveformPaddingStrategy`, `WaveformFilterCoefficients`, `WaveformFrequencyRange`, and `WaveformSpectrogramScaling` remain public support types without current DSP consumers. Whether to remove them or add consuming APIs requires a separate contract decision. +- `SpectralMixin.spectrogram` retains the legacy SciPy implementation despite the DSP specification naming `ShortTimeFFT`; migration would be a behavioral change. +- The uncalled `_time_none_smooth` online trajectory generation path remains because the Swift source also retains it. diff --git a/.claude/archive/math-tools-port/00-overview.md b/.claude/archive/math-tools-port/00-overview.md deleted file mode 100644 index e820701..0000000 --- a/.claude/archive/math-tools-port/00-overview.md +++ /dev/null @@ -1,195 +0,0 @@ ---- -plan: math-tools-port -status: complete -last_updated: 2026-07-23 -semver: 0.1.2 -author: Nicholas Bergantz ---- - -# Action Plan — Template Migration + Swift Math Port - -**Goal:** bring py-MathTools onto the py-foundationTools template conventions -and port the Swift `FoundationMathTypes` capability set (spatial SE(3) types, -precision time, waveforms + DSP, polynomials/roots, OTG trajectory -generation) as the Tier-3 math layer, per the accepted specs in -[`../specs/`](../specs/mathToolsArchitecture.md). - -**Usability north star:** a robotics/DSP engineer in a notebook can build a -waveform or pose, do the obvious math, and reach scipy-grade analysis with -minimal ceremony — well-typed numpy-adjacent Python, not translated Swift. - -## Conventions every chunk inherits (do not restate per chunk) - -1. **Spec is authoritative.** Each chunk lists its governing spec section(s). - If implementation forces a contract change, update the spec in the same - chunk and bump its `semver`. -2. **TDD:** write the failing tests first, implement, then run the gate. -3. **Gate:** `make uv-fullCheck` (ruff lint + mypy strict + pytest) must pass - at the end of every chunk. Test layout mirrors the package - (`tests//test_.py`), `unittest.TestCase` style, `test_*` - methods. -4. **Stay in scope:** touch ONLY the files the chunk lists. Adjacent - problems get reported in the chunk's completion notes, not fixed. -5. **Frontmatter:** every chunk carries `status: pending` → set - `in_progress` while working, then `complete` when done (not `done` - — `complete` is the convention actually used across every chunk file - in this repo); bump `last_updated`. -6. **Swift reference roots** (read-only, for faithful-port chunks): - - `SWIFT_MATH` = `/Users/nbergantz/__Workspaces__/spmWorkspaces/spmMathTools/spm/Sources/spmMathTools/FoundationMathTypes` - - `SWIFT_TYPES` = `/Users/nbergantz/__Workspaces__/spmWorkspaces/spmFoundationTools/spm/Sources/FoundationTypes` - - `SWIFT_TESTS` = `/Users/nbergantz/__Workspaces__/spmWorkspaces/spmMathTools/spm/Tests/spmMathToolsTests` -7. **Shared API idioms** (umbrella spec "API idioms"): `normalized()` method - / `normalize()` in-place; `isclose(rtol, atol)`; `__array__`; - `__hash__ = None` on mutable numpy-backed classes; snake_case throughout. -8. Do not commit; the human reviews and commits per track. - -## Dependency graph - -``` -Track A (template) 01 ──► 02 ──► 03 - │ - ┌────────────────┴───────────────────────────────┐ -Track B │ 04 ─► 05 06 ─► 07 ─► 08 09 10 │ (02 before all B) - │ └──────┬──────────┘└───┬────┘ │ │ -Track C │ ▼ │ │ │ - │ 11 ─► {12, 13, 14} │ │ │ - │ │ │ ▼ │ │ - │ │ │ 15(◄06) 16(◄07) ─► 17(◄08,15,16)│ -Track D │ │ ▼ │ │ - │ │ 18..29 (one per mixin; 26 also ◄19) │ │ - │ │ └────────► 30 (compose) │ │ -Track E │ └──────────────────────────────────────────┘ │ - │ 31(◄10) ─► 32 │ - │ 31 ─► 33 ─► 34 ─► {35, 36, 37, 38, 39} │ - │ {32,35..39} ─► 40 ─► 41 ─► 42 │ - └────────────────────────────────────────────────┘ -``` - -Tracks B/C/D/E parallelize after 01–02; within a track, run in numeric -order unless the graph says otherwise. Chunk 43 (public surface) runs last, -after 09, 17, 30, and 42. - -## Chunk index - -| # | Chunk | Track | Depends on | Spec | -|---|---|---|---|---| -| 01 | [template-rename-and-refresh](01-template-rename-and-refresh.md) | A | — | templateConformance | -| 02 | [errors-and-layering](02-errors-and-layering.md) | A | 01 | umbrella, templateConformance §5 | -| 03 | [governance-and-readme](03-governance-and-readme.md) | A | 02 | templateConformance §3–4 | -| 04 | [precision-time-interval](04-precision-time-interval.md) | B | 02 | precisionTimeMath | -| 05 | [precision-timestamp](05-precision-timestamp.md) | B | 04 | precisionTimeMath | -| 06 | [position](06-position.md) | B | 02 | spatialMath | -| 07 | [quaternion-additions](07-quaternion-additions.md) | B | 06 | spatialMath | -| 08 | [spatial-pose](08-spatial-pose.md) | B | 07 | spatialMath | -| 09 | [univariate-polynomial](09-univariate-polynomial.md) | B | 02 | polynomials | -| 10 | [roots-kernel](10-roots-kernel.md) | B | 02 | polynomials | -| 11 | [waveform1d-core](11-waveform1d-core.md) | C | 05 | waveformCore | -| 12 | [waveform1d-operators](12-waveform1d-operators.md) | C | 11 | waveformCore | -| 13 | [waveform1d-generators](13-waveform1d-generators.md) | C | 11 | waveformCore | -| 14 | [dsp-support-and-protocol](14-dsp-support-and-protocol.md) | C | 11 | waveformDsp | -| 15 | [waveform-position](15-waveform-position.md) | C | 11, 06 | waveformCore | -| 16 | [waveform-quaternion](16-waveform-quaternion.md) | C | 11, 07 | waveformCore | -| 17 | [waveform-spatial-pose](17-waveform-spatial-pose.md) | C | 08, 15, 16 | waveformCore | -| 18 | [dsp-calc](18-dsp-calc.md) | D | 14 | waveformDsp | -| 19 | [dsp-correlation](19-dsp-correlation.md) | D | 14 | waveformDsp | -| 20 | [dsp-envelope](20-dsp-envelope.md) | D | 14 | waveformDsp | -| 21 | [dsp-spectral](21-dsp-spectral.md) | D | 14 | waveformDsp | -| 22 | [dsp-filtering](22-dsp-filtering.md) | D | 14 | waveformDsp | -| 23 | [dsp-peaks](23-dsp-peaks.md) | D | 14 | waveformDsp | -| 24 | [dsp-phase](24-dsp-phase.md) | D | 14 | waveformDsp | -| 25 | [dsp-resampling](25-dsp-resampling.md) | D | 14 | waveformDsp | -| 26 | [dsp-time-alignment](26-dsp-time-alignment.md) | D | 14, 19 | waveformDsp | -| 27 | [dsp-triggers](27-dsp-triggers.md) | D | 14 | waveformDsp | -| 28 | [dsp-windowing](28-dsp-windowing.md) | D | 14 | waveformDsp | -| 29 | [dsp-zero-crossings](29-dsp-zero-crossings.md) | D | 14 | waveformDsp | -| 30 | [dsp-compose](30-dsp-compose.md) | D | 18–29 | waveformDsp | -| 31 | [otg-enums-and-errors](31-otg-enums-and-errors.md) | E | 10 | otg | -| 32 | [otg-input-parameter](32-otg-input-parameter.md) | E | 31 | otg | -| 33 | [otg-profile](33-otg-profile.md) | E | 31 | otg | -| 34 | [otg-block-brake-bound](34-otg-block-brake-bound.md) | E | 33 | otg | -| 35 | [otg-trajectory-and-output](35-otg-trajectory-and-output.md) | E | 34 | otg | -| 36 | [otg-velocity-steps](36-otg-velocity-steps.md) | E | 34 | otg | -| 37 | [otg-position-first-second-steps](37-otg-position-first-second-steps.md) | E | 34 | otg | -| 38 | [otg-position-third-step1](38-otg-position-third-step1.md) | E | 34 | otg | -| 39 | [otg-position-third-step2](39-otg-position-third-step2.md) | E | 34 | otg | -| 40 | [otg-calculator-target](40-otg-calculator-target.md) | E | 32, 35–39 | otg | -| 41 | [otg-driver](41-otg-driver.md) | E | 40 | otg | -| 42 | [otg-oracle-suites](42-otg-oracle-suites.md) | E | 41 | otg | -| 43 | [public-surface](43-public-surface.md) | A | 30, 42, 09, 17 | umbrella | - ---- - -# Corrective actions — 2026-07-22 post-audit - -Chunks 01–43 were audited against their governing specs by five parallel -skeptical auditors (one per track), with the top findings independently -reproduced at runtime and source level before being recorded here. - -**Verdict: substantially complete.** `make uv-fullCheck` is green (exit 0) and -the port is faithful in the large — the 31-case OTG numeric truth table was -re-derived from the Swift source with 0 mismatches, no test in the repo is -skipped or xfail'd, and no unsolved algorithm case, stub, or swallowed `None` -was found in the solvers. The confirmed gaps are specific and are chunked below. - -Chunks 44–57 form **Track F**. They are corrective, not new capability. - -## Confirmed defect summary - -| Class | Count | Where | -|---|---|---| -| (c) drift / correctness | 8 | OTG solvers, spatial/time accessors, waveform indexing | -| (a) not implemented | 6 | aggregate API idioms, subpackage exports, roots degeneracy | -| (b) implemented, untested | ~45 | concentrated in DSP mixins and OTG oracles | -| (e) docs/convention drift | 14 | dead workflow refs, stale tolerances, boilerplate | -| (d) out-of-scope violations | **0** | — none found in any track | - -The single most consequential finding is a **transcription defect** at -`position_third_order_step2.py:1731,1752,1763` (`j·tf⁴` where Swift has -`j·tf³`), confirmed by direct comparison against -`PositionThirdOrderStep2.swift:1279,1286,1289`. It changes profile-branch -selection in ~0.57% of prescribed-duration Step2 solves and is invisible to the -current gate — because the entire 1,784-case OTG oracle corpus is 1-DOF, which -takes a fast path that **never invokes Step2 at all** (measured: 0 invocations). - -## Dependency graph - -``` -Track F (corrective) - - OTG code fixes 44 45 46 - └────┴────┴──────► 56 (OTG oracle closure) - - Track B/C code fixes 47 48 49 ─► 50 51 - └────┴────┴─► 54 (B/C test closure) - - Surface / conventions 52 53 ─────────────► 55 (DSP test closure) - - Everything above ───────────────────────────────► 57 (docs sweep, last) -``` - -44–49, 51, 52, 53 are mutually independent and may run in parallel. -50 waits on 49. The three closure chunks wait on their code fixes. 57 runs last -so it reconciles docs against the post-fix repo. - -## Corrective chunk index - -| # | Chunk | Kind | Depends on | Origin | -|---|---|---|---|---| -| 44 | [otg-step2-udud-discriminant](44-otg-step2-udud-discriminant.md) | fix | — | E-1 | -| 45 | [otg-trivial-profile-length](45-otg-trivial-profile-length.md) | fix | — | E-2 | -| 46 | [otg-step1-sqrt-guard](46-otg-step1-sqrt-guard.md) | fix | — | E-3 | -| 47 | [position-tolerance-and-timestamp-accessors](47-position-tolerance-and-timestamp-accessors.md) | fix | — | B-1, B-2 | -| 48 | [roots-degenerate-cases](48-roots-degenerate-cases.md) | fix | — | B-7, B-14 | -| 49 | [waveform-spatial-pose-indexing](49-waveform-spatial-pose-indexing.md) | fix | — | C-4, C-5 | -| 50 | [aggregate-container-api-idioms](50-aggregate-container-api-idioms.md) | fix | 49 | C-1, C-2, C-3, C-7 | -| 51 | [waveform-generator-phase-conventions](51-waveform-generator-phase-conventions.md) | fix | — | C-15 | -| 52 | [subpackage-public-surface](52-subpackage-public-surface.md) | fix | — | A-1, A-2 | -| 53 | [window-convention-reconciliation](53-window-convention-reconciliation.md) | fix | — | D-windowing | -| 54 | [test-closure-tracks-bc](54-test-closure-tracks-bc.md) | tests | 47–51 | 11 (b) findings | -| 55 | [test-closure-dsp](55-test-closure-dsp.md) | tests | 53 | 23 (b) findings | -| 56 | [test-closure-otg-oracles](56-test-closure-otg-oracles.md) | tests | 44, 45, 46 | 8 (b) findings | -| 57 | [docs-and-convention-sweep](57-docs-and-convention-sweep.md) | docs | 44–56 | 14 (e) findings | - -Findings deliberately **not** actioned (B-4, B-5, B-6, A-7, D-cross-cutting, -D-spectral-(c), E-10) are recorded with rationale in chunk 57's -"Recorded — no action" section, so the decisions are not relitigated. diff --git a/.claude/archive/math-tools-port/01-template-rename-and-refresh.md b/.claude/archive/math-tools-port/01-template-rename-and-refresh.md deleted file mode 100644 index 2d09849..0000000 --- a/.claude/archive/math-tools-port/01-template-rename-and-refresh.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -chunk: 01-template-rename-and-refresh -track: A -status: complete -depends_on: [] -spec: ../specs/templateConformance.md §Gap 1, §Gap 2.4; ../specs/spatialMath.md §Modules (ABC re-parent) -last_updated: 2026-07-11 -semver: 0.0.1 -author: Nicholas Bergantz ---- - -# 01 — Package rename + environment refresh - -**Deliverable:** the repo builds and gates green under the new snake_case -package names against the pinned foundation branch. Mechanical migration — -no behavior changes beyond the required ABC re-parent. - -## Files - -- `git mv src/pyMathTools src/math_tools`; inside it: - `git mv src/math_tools/spatial/Quaternion.py src/math_tools/spatial/quaternion.py`, - `git mv src/math_tools/spherical/sphericalGenerators.py src/math_tools/spherical/spherical_generators.py`, - `git mv src/math_tools/spherical/sphericalTransforms.py src/math_tools/spherical/spherical_transforms.py` - (`constructors.py`, `hints.py` keep their names). -- `git mv src/pyMathToolsPlotHelpers src/math_plot_helpers`; - `git mv src/math_plot_helpers/plotUnitSpherical.py src/math_plot_helpers/plot_unit_spherical.py`. -- Edit: `src/math_tools/spatial/quaternion.py` (imports/base only, see below), - every `__init__.py` touched by moves, `tests/test_quaternion.py`, - `examples/sphericalPlotting/plotArcs.py`, - `examples/sphericalPlotting/plotQuatUnitCircles.py`, `Makefile` (mypy - package list if it names packages), `.env` if it names packages. -- Add: `py.typed` in `src/math_tools/` and `src/math_plot_helpers/` roots - (keep the existing ones in subpackages). - -## Design constraints - -1. **First action:** `make uv-refresh` so `.venv` matches the - `requirements.txt` branch pin (the stale install has the pre-template ABC - layout; nothing imports correctly until this runs). -2. **ABC re-parent (the one semantic edit):** in `quaternion.py`, replace - `from foundationTypes.mathTypes.quaternionABC import QuaternionABC` with - `from foundation_abc.math.spatialABCs import QuaternionABC`. The old ABC - carried `DataModelHelper`; the new one is ABC-only with a concrete - `to_dict`. In `tests/test_quaternion.py`, update the serialization tests' - base-class assertions (`DataModelHelper` inheritance assertion → the new - ABC) — assertions on `to_dict`/`from_dict` *values* stay untouched. If any - other import from the old layout exists (grep `foundationTypes.mathTypes.` - across `src/`), re-point to `foundation_abc.math.*` / - `foundationTypes.mathTypes.MathTypes` equivalents. -3. All other edits are import-path text substitutions - (`pyMathTools` → `math_tools`, `pyMathToolsPlotHelpers` → - `math_plot_helpers`, moved module filenames). -4. `pyproject.toml`: update `description` only if trivially co-located; the - deps list changes in chunk 03, not here. - -## TDD steps - -1. `make uv-refresh`; run `make uv-test` to record the pre-existing pass/fail - baseline (the ABC import may already be broken — note it). -2. Perform moves + edits. -3. `make uv-fullCheck` green. - -## Acceptance criteria - -- [x] `grep -rn "pyMathTools" src/ tests/ examples/ Makefile .env pyproject.toml` → no hits -- [x] `grep -rn "foundationTypes.mathTypes.quaternionABC" src/ tests/` → no hits -- [x] `git log --follow --oneline src/math_tools/spatial/quaternion.py` shows history (moves were `git mv`) — verified via `git status`/`git diff --staged` showing `renamed: src/pyMathTools/spatial/Quaternion.py -> src/math_tools/spatial/quaternion.py`; `--follow` itself needs a commit to walk, which this chunk intentionally leaves to the supervising process -- [x] All ~90 quaternion tests pass (89 collected/passed); diff to `tests/test_quaternion.py` contains only import lines, base-class assertion lines, and their two adjacent docstring lines (see Resolution notes) -- [x] `make uv-fullCheck` passes - -## Out of scope - -`errors.py`, layering test, README, `.claude/CLAUDE.md`, pyproject dependency -list, any new math code, any `__init__.py` re-export curation beyond fixing -broken imports. - -## Resolution notes - -- `make uv-refresh` pulled the pinned foundation branch fresh; pre-move - `make uv-test` baseline reproduced the expected pre-existing break - (`ModuleNotFoundError: foundationTypes.mathTypes.quaternionABC`), confirming - the venv was stale before this chunk and the gate is meaningful after. -- Moves done via `git mv` as specified. `git status`/`git diff --staged` - correctly report `quaternion.py` as a rename from `Quaternion.py`; git's - similarity heuristic cross-matched some of the (byte-identical, empty) - `__init__.py` files to different-but-equivalent old empty `__init__.py` - paths — cosmetic only, every file's on-disk destination was verified - directly with `find`, and it does not affect `--follow` on the files that - matter (confirmed for `quaternion.py`). -- The old-layout ABC repoint (design constraint 2) turned out to reach beyond - `quaternion.py`: `foundationTypes.mathTypes.unitSphericalArcABC` and - `unitSphericalSmallCircleABC` (imported by `spherical_generators.py`, - `spherical_transforms.py`, `constructors.py`, `plot_unit_spherical.py`) - were also deleted from the pinned foundation branch and now live at - `foundation_abc.math.sphericalABCs`. Re-pointed all of them per the chunk's - explicit "grep `foundationTypes.mathTypes.` across `src/`" instruction — - required for `make uv-fullCheck` (mypy strict) to pass, since mypy scans - all of `src/`, not just the quaternion module. `foundationTypes.mathTypes.MathTypes.*` - imports (the codegen `*Type` classes) were left untouched — that module - still exists unchanged in the new layout. - This is a scope note, not a spec deviation: constraint 2's own text - authorized exactly this action; the "Files" list section above just didn't - enumerate every file it touched. -- `examples/sphericalPlotting/plotArcs.py` and `plotQuatUnitCircles.py` got - only the mechanical package-name substitution, per constraint 3 and Gap 4's - explicit ownership of their pre-existing broken `foundationTypes.mathTypes.UnitSphericalArc` - / `UnitSphericalSmallCircle` imports (not part of this chunk's scope, and - not scanned by `make uv-typecheck` since `PY_EXAMPLES` is unset in `.env`). -- `tests/test_quaternion.py`: `test_inheritance_from_data_model_helper` - asserted `isinstance(q, DataModelHelper)`, which is no longer true (the new - `QuaternionABC` is ABC-only). Repointed the import and assertion to - `QuaternionABC` per constraint 2's directive, and updated that test's and - the class's docstrings by one line each so the docstrings don't contradict - the assertion right below them — the only lines in this diff beyond raw - import-path substitution. No `to_dict`/`from_dict` value assertions were - touched. -- Added `py.typed` at `src/math_tools/` and `src/math_plot_helpers/` package - roots (subpackage ones already existed). -- No `Makefile`/`.env` edits were needed — neither names packages explicitly - (both scope quality targets via path variables, not package names). -- `pyproject.toml` `description` left untouched — no trivially co-located - edit was applicable in this chunk; still boilerplate text, tracked as Gap 4 - (chunk 03). diff --git a/.claude/archive/math-tools-port/02-errors-and-layering.md b/.claude/archive/math-tools-port/02-errors-and-layering.md deleted file mode 100644 index 78fdbfb..0000000 --- a/.claude/archive/math-tools-port/02-errors-and-layering.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -chunk: 02-errors-and-layering -track: A -status: complete -depends_on: [01] -spec: ../specs/mathToolsArchitecture.md §Error semantics; ../specs/templateConformance.md §Gap 5 -last_updated: 2026-07-11 -semver: 0.0.1 -author: Nicholas Bergantz ---- - -# 02 — Exception hierarchy + package layering test - -**Deliverable:** `math_tools/errors.py` and the AST-based layering test. - -## Files - -- Create: `src/math_tools/errors.py` -- Create: `tests/test_package_layering.py` -- Create: `tests/test_errors.py` - -## Design constraints - -1. `errors.py` defines exactly (each with a one-line docstring): - `MathToolsError(Exception)`, `WaveformCompatibilityError(MathToolsError)`, - `TimestampComparisonError(MathToolsError)`, - `PolynomialSolveError(MathToolsError)`. -2. Layering test pattern: copy the approach of py-foundationTools - `tests/test_package_layering.py` (AST-walk every module under `src/`, - collect `import`/`from` roots). Assertions per templateConformance §Gap 5: - `math_tools` imports neither `math_plot_helpers` nor `matplotlib`; - only `math_plot_helpers` imports `matplotlib`. -3. Additionally assert `math_tools.otg` (once it exists) does not import - `numpy` — write the rule now, guarded to skip if the package dir is - absent, so OTG chunks inherit enforcement for free. - -## TDD steps - -1. Write `tests/test_errors.py` (hierarchy, catchability as `MathToolsError`) - and `tests/test_package_layering.py`; watch errors test fail. -2. Implement `errors.py`; layering test must pass against the current tree. -3. Temporarily add `import matplotlib` to a `math_tools` module and confirm - the layering test fails; revert. `make uv-fullCheck` green. - -## Acceptance criteria - -- [x] All four exception classes exist and subclass as specified -- [x] Layering test fails on an injected `import matplotlib` in `math_tools` (verified then reverted) -- [x] `make uv-fullCheck` passes - -## Out of scope - -Any consumer of the exceptions; OTG's `OtgError` (lives in `otg/errors.py`, -chunk 31); README/CLAUDE.md. - -## Resolution notes - -- `errors.py` implements exactly the four classes from the spec, each a - one-line docstring, no added behavior. -- `test_package_layering.py` follows the py-foundationTools AST-scan pattern - (`tests/test_package_layering.py` there) rather than executing imports, so - it can't be defeated by import side effects. Four checks: `math_tools` ↛ - `math_plot_helpers`, `math_tools` ↛ `matplotlib`, only `math_plot_helpers` - → `matplotlib` (scans all of `src/` excluding that package), and the - guarded `math_tools.otg` ↛ `numpy` rule (currently a no-op skip since - `otg/` doesn't exist yet — will activate automatically once chunk 31 lands). -- Verification step 3 (inject `import matplotlib` into `math_tools/errors.py`, - confirm two layering assertions fail, revert) was done live against the - actual gate, not simulated; file diffed back to the original after. -- One ruff fix needed: the injected-violation assertion message exceeded the - 100-char line limit in `test_only_math_plot_helpers_imports_matplotlib`'s - sibling test; wrapped the f-string across two lines. -- No spec changes were required — the chunk's design constraints matched the - umbrella spec's Error semantics section exactly. diff --git a/.claude/archive/math-tools-port/03-governance-and-readme.md b/.claude/archive/math-tools-port/03-governance-and-readme.md deleted file mode 100644 index 804cdab..0000000 --- a/.claude/archive/math-tools-port/03-governance-and-readme.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -chunk: 03-governance-and-readme -track: A -status: complete -depends_on: [02] -spec: ../specs/templateConformance.md §Gap 2, §Gap 3, §Gap 4 -last_updated: 2026-07-11 -semver: 0.0.2 -author: Nicholas Bergantz ---- - -# 03 — Governance docs, README, dependency names - -**Deliverable:** `.claude/CLAUDE.md`, real README, pyproject dependency -names, fixed examples. - -## Files - -- Create: `.claude/CLAUDE.md` -- Edit: `README.md`, `pyproject.toml` (deps + description only), - `examples/sphericalPlotting/plotArcs.py`, - `examples/sphericalPlotting/plotQuatUnitCircles.py` - -## Design constraints - -1. `.claude/CLAUDE.md` follows the shape of py-foundationTools - `.claude/CLAUDE.md` but stays short: repo role (Tier 3 of foundation's - `mathTypeTiers.md`), the two-package layering diagram, gate command, - Makefile-is-source-of-truth note, and a linked index of every spec in - `.claude/specs/`. Reference specs; never duplicate their content. -2. `pyproject.toml` `dependencies` = names only: - `pyFoundationTools`, `numpy`, `scipy`, `numpy-quaternion`, `matplotlib`. - Replace the boilerplate `description`. -3. README per templateConformance Gap 4: describe only what exists at - execution time (quaternion, spherical utilities, template workflows); - sections: title → Features → Installation → Quick Start → Development - Workflows → Requirements. Quick Start snippets must actually run. -4. `plotArcs.py`: fix the dead - `foundationTypes.mathTypes.UnitSphericalArc.UnitSphericalArc` import to - the real generated type in `foundationTypes.mathTypes.MathTypes` - (verify the class name by reading that module). - -## TDD steps - -1. Add a test `tests/test_governance.py`: `.claude/CLAUDE.md` exists and its - text links every `*.md` in `.claude/specs/`; `README.md` contains no - "Boilerplate". Watch it fail. -2. Write the docs; run both example scripts manually - (`uv run python examples/sphericalPlotting/plotArcs.py` with a - non-interactive matplotlib backend) to prove imports resolve. -3. `make uv-fullCheck` green. - -## Acceptance criteria - -- [x] `tests/test_governance.py` passes -- [x] `pyproject.toml` deps are exactly the five names, unpinned -- [x] Both example scripts import-run without error -- [x] `make uv-fullCheck` passes - -## Out of scope - -Makefile/CI edits; requirements pin changes; any `src/` code beyond the -example imports. - -## Resolution notes - -- `tests/test_governance.py` added: asserts `.claude/CLAUDE.md` exists and - its text contains the filename of every `.claude/specs/*.md` file, and - that `README.md` contains no `"Boilerplate"` text. Confirmed it failed - before the docs existed, passed after. -- `.claude/CLAUDE.md` written to the shape of py-foundationTools' - `.claude/CLAUDE.md` (Project Overview → layering → Commands → Specs index - → Tests) but scoped to what exists in this repo today: Tier 3 role, the - two-package layering diagram, the gate command, a Makefile-is-source-of- - truth note, and a linked index of all 7 specs in `.claude/specs/`. -- `README.md` rewritten per Gap 4's section shape (title → Features → - Installation → Quick Start → Development Workflows → Requirements), - describing only what exists at execution time: `Quaternion`, the - spherical arc/small-circle utilities, `errors.py`, and the - `math_plot_helpers` plotting package. Both Quick Start snippets - (quaternion arithmetic/conversion, spherical arc construction + - endpoint) were executed directly to confirm they run as written. -- `pyproject.toml`: `dependencies` set to the five names - (`pyFoundationTools`, `numpy`, `scipy`, `numpy-quaternion`, `matplotlib`) - — the prior list was missing `numpy`/`scipy` and had an unrelated stray - order; `description` replaced with a one-line Tier-3 summary. -- `examples/sphericalPlotting/plotArcs.py`: fixed the dead - `foundationTypes.mathTypes.UnitSphericalArc.UnitSphericalArc` import to - `foundationTypes.mathTypes.MathTypes.UnitSphericalArcType` (verified the - real class name by reading the installed `MathTypes.py`) and updated the - two local usages/type hints accordingly. -- `examples/sphericalPlotting/plotQuatUnitCircles.py`: same dead-import - pattern existed for `UnitSphericalSmallCircle` (not called out by name in - the chunk's design constraint 4, but the file was listed for edit and the - acceptance criterion requires *both* scripts to import-run without - error) — fixed to `foundationTypes.mathTypes.MathTypes.UnitSphericalSmallCircleType`. -- Both example scripts verified to run end-to-end with - `MPLBACKEND=Agg PYTHONPATH=src .venv/bin/python examples/sphericalPlotting/