Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
b15ccfc
updating template module
kopecn Jun 30, 2026
0162ccc
cleanups
kopecn Jul 2, 2026
02efdd7
cont...
kopecn Jul 2, 2026
d339936
cool...
kopecn Jul 2, 2026
7872825
cool...
kopecn Jul 2, 2026
043def9
scoping out updates and upgrades.
kopecn Jul 12, 2026
f8935f6
01 Template rename and refresh
kopecn Jul 12, 2026
7be1ffd
02 Errors and layering
kopecn Jul 12, 2026
d792bb1
03 Governance and readme
kopecn Jul 12, 2026
c33c0f2
updating the github actions
kopecn Jul 12, 2026
7b0e3cd
fixes for ci-cd
kopecn Jul 12, 2026
d72c657
04 Precision time interval
kopecn Jul 14, 2026
0598ed4
05 Precision timestamp
kopecn Jul 14, 2026
94dad27
06 Position
kopecn Jul 14, 2026
1f3d794
07 Quaternion additions
kopecn Jul 14, 2026
f258076
08 Spatial pose
kopecn Jul 14, 2026
0241552
09 Univariate polynomial
kopecn Jul 14, 2026
518c27e
10 Roots kernel
kopecn Jul 15, 2026
c5f07c2
11 Waveform1D core container
kopecn Jul 15, 2026
4b69970
12 Waveform1D operators & comparison
kopecn Jul 15, 2026
ff19cc1
13 Waveform1D signal generators
kopecn Jul 15, 2026
383eb9a
14 DSP support types + mixin protocol
kopecn Jul 15, 2026
00ed834
15 WaveformPosition
kopecn Jul 15, 2026
c057c3f
16 WaveformQuaternion
kopecn Jul 15, 2026
93d7f51
17 WaveformSpatialPose
kopecn Jul 15, 2026
f730895
18 DspCalcMixin
kopecn Jul 17, 2026
c5fe37a
19 DspCorrelationMixin
kopecn Jul 17, 2026
fd03b47
20 DspEnvelopeMixin
kopecn Jul 17, 2026
1212cdf
21 DspSpectralMixin
kopecn Jul 17, 2026
f9344db
22 DspFilteringMixin
kopecn Jul 17, 2026
e4f8e57
23 DspPeakMixin
kopecn Jul 17, 2026
e1abf4f
24 DspPhaseMixin
kopecn Jul 17, 2026
8ead898
25 DspResamplingMixin
kopecn Jul 17, 2026
b736f94
26 DspTimeAlignmentMixin
kopecn Jul 17, 2026
aba432f
27 DspTriggerMixin
kopecn Jul 17, 2026
a86ef84
28 DspWindowingMixin
kopecn Jul 17, 2026
1f28184
29 DspZeroCrossingMixin
kopecn Jul 17, 2026
50e90c5
30 DspCompose
kopecn Jul 17, 2026
8cc9e5f
31 OtgEnumsAndErrors
kopecn Jul 21, 2026
264c3f0
32 OtgInputParameter
kopecn Jul 21, 2026
e74a061
33 OtgProfile
kopecn Jul 21, 2026
d728ad4
34 OtgBlockBrakeBound
kopecn Jul 21, 2026
926e571
35 OtgTrajectoryAndOutput
kopecn Jul 21, 2026
12f97f0
36 OtgVelocitySteps
kopecn Jul 22, 2026
bc481c9
37 OtgPositionFirstSecondSteps
kopecn Jul 22, 2026
0b2b842
38 OtgPositionThirdStep1
kopecn Jul 22, 2026
0799f00
39 OtgPositionThirdStep2
kopecn Jul 22, 2026
cccee9b
40 OtgCalculatorTarget
kopecn Jul 22, 2026
a2cabd2
41 OtgDriver
kopecn Jul 22, 2026
521a3f1
42 OtgOracleSuites
kopecn Jul 22, 2026
d39ef65
43 PublicSurface
kopecn Jul 22, 2026
ace092c
Mark math-tools-port plan complete (all 43 chunks done)
kopecn Jul 22, 2026
dbe24f9
44 OtgStep2UdudDiscriminant
kopecn Jul 23, 2026
d4b4ed1
45 OtgTrivialProfileLength
kopecn Jul 23, 2026
aa16d3e
46 OtgStep1SqrtGuard
kopecn Jul 23, 2026
8c373bc
47 PositionToleranceAndTimestampAccessors
kopecn Jul 23, 2026
e7c9f22
48 RootsDegenerateCases
kopecn Jul 23, 2026
acd7026
49 WaveformSpatialPoseIndexing
kopecn Jul 23, 2026
a9598e1
50 AggregateContainerApiIdioms
kopecn Jul 23, 2026
7d145cf
51 WaveformGeneratorPhaseConventions
kopecn Jul 23, 2026
45829be
52 SubpackagePublicSurface
kopecn Jul 23, 2026
9c775ac
53 WindowConventionReconciliation
kopecn Jul 23, 2026
e55e268
54 TestClosureTracksBC
kopecn Jul 23, 2026
8cff4a4
55 TestClosureDsp
kopecn Jul 24, 2026
d377068
56 TestClosureOtgOracles
kopecn Jul 24, 2026
5de627f
57 DocsAndConventionSweep
kopecn Jul 24, 2026
9f807e0
Mark math-tools-port plan complete (Track F, all 57 chunks done)
kopecn Jul 24, 2026
0cdb480
clean room installs requirements.txt before the package
kopecn Aug 11, 2026
03c9556
rename clean-room sub-steps so they stop implying tests
kopecn Aug 11, 2026
2e3d15a
cont....
kopecn Aug 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[bumpversion]
current_version = 0.0.1
commit = true
tag = false
tag_name = v{new_version}
message = Bump version: {current_version} → {new_version}

[bumpversion:file:pyproject.toml]
search = version = "{current_version}"
replace = version = "{new_version}"
78 changes: 78 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
last_updated: 2026-07-23
semver: 0.0.1
author: Nicholas Bergantz
---

# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

`py-MathTools` is the **Tier 3 math implementation layer** of the foundation
math tiers defined in py-foundationTools' `mathTypeTiers.md`: it subclasses
the Tier-2 `foundation_abc.math.*` ABCs, chooses numpy-backed storage, and
implements arithmetic, composition, interpolation, DSP, and trajectory
generation on top of the Tier-1 `foundationTypes.mathTypes` data carriers.
Unlike `pyFoundationTools` (zero-dependency by policy), this repo depends on
a curated set of mature numeric packages rather than reimplementing them.

## Packages and layering

Two top-level snake_case packages under `src/`, one-way dependency:

```
math_plot_helpers → math_tools → pyFoundationTools → stdlib
(matplotlib) (numpy, scipy, numpy-quaternion)
```

`math_tools` never imports `math_plot_helpers` or `matplotlib`; only
`math_plot_helpers` imports `matplotlib`. This is enforced by
`tests/test_package_layering.py` (static AST scan of `src/`).

## Commands

All workflows go through the Makefile (`make help` lists them); **the
Makefile is the source of truth for tooling**, not this file or the README.
The `uv-` prefixed targets are the primary path. Key ones:

- `make uv-fullCheck` — CI gate: `uv-lint` + `uv-typecheck` + `uv-test`. Run
this before considering work done.
- `make uv-lint` — ruff check
- `make uv-format` — `ruff format` + `ruff check --fix --unsafe-fixes`
- `make uv-typecheck` — strict `mypy` over `src/` + `tests/`
- `make uv-test` — sync deps then run pytest
- `make uv-refresh` — clean cache + reinstall from `requirements.txt` +
upgrade editable dev install (required after a `pyFoundationTools` pin
changes; a stale `.venv` makes the gate meaningless)

## Specs

`.claude/specs/` is the authoritative contract for this repo's architecture
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.

- [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
- [precisionTimeMath.md](specs/precisionTimeMath.md) — `PrecisionTimeInterval`,
`PrecisionTimestamp`
- [spatialMath.md](specs/spatialMath.md) — `Position`, `Quaternion`,
`SpatialPose`
- [waveformCore.md](specs/waveformCore.md) — `Waveform1D` + aggregate
waveform containers
- [waveformDsp.md](specs/waveformDsp.md) — DSP families, scipy mapping,
support types
- [polynomials.md](specs/polynomials.md) — polynomial type + analytic root
solvers
- [otg.md](specs/otg.md) — online trajectory generation (Ruckig port)

## Tests

Tests live in `tests/`, `unittest.TestCase` style run under pytest
(`test*.py` files, `test_*` methods), mirroring the package layout under
`src/` (e.g. `tests/spatial/test_position.py`).
195 changes: 195 additions & 0 deletions .claude/archive/math-tools-port/00-overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
---
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/<subpkg>/test_<module>.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.
Loading
Loading