`oxmpl` - sprint-006
Sprint 006 — Release 0.9.0 "Validation" (provisional)
Provisional scaffold for release 0.9.0 (E4), written 2026-10-08 so the release isn't lost. Nothing here is committed: the stories carry no
oxmpl/sprint/006tag until planning confirms them against the owner's stated availability. Dates are re-derived at the previous sprint's retro if it slipped.
- Dates (provisional): Thu 2026-12-31 → Wed 2027-01-20 (three weeks)
- Epic: E4 — Validation (0.9.0)
- Goal (provisional): v0.9.0 published on crates.io, PyPI and npm with a migration guide.
Provisional commitment
- S4.7 — User motion validators in the bindings (size-M; after E3, S4.5, S4.6)
- S4.9 — Docs, migration guide, ADR-0003 accepted (size-M; after E3, S4.1, S4.2, S4.3, S4.4, S4.5, S4.6, S4.7, S4.8)
- S4.10 — Release 0.9.0 (size-S; after E3, S4.1, S4.2, S4.3, S4.4, S4.5, S4.6, S4.7, S4.8, S4.9)
Order: S4.7 → S4.9 → S4.10.
Entry criteria: S4.1–S4.6 and S4.8 done. After the release: close E4 and run release planning for 0.10.0 "Path Quality" (scope in oxmpl - backlog; no epic exists yet).
Blind pickup: how to (re)generate the tickets
Tickets for these stories already exist in TaskNotes (created 2026-10-08). Once a ticket exists, its TaskNotes details are authoritative and this page is only the regeneration spec. If a ticket is missing or was lost, recreate it from the spec below:
tasknotes_create_taskwith the title, projects, tags and priority shown. MCP quirks: create drops the description and defaultsscheduledto today, so follow withtasknotes_update_taskto setdetails(the body below) andscheduled: null.- Wire
blockedByby editing the task file's YAML frontmatter directly (no MCP tool exposes it). A story lists all upstream dependencies, including done ones. - Verify with
tasknotes_get_task:isBlocked: trueon the story while its upstreams are open, andisBlockingon each upstream. After any laterupdate_task, re-check thatblockedBysurvived. - If the epic E4 is missing, recreate it first from the spec in
oxmpl- sprint-003 § Epic E4. - At this sprint's planning (owner confirms availability): add the
oxmpl/sprint/NNNtag, setscheduled/dueto the sprint dates, removesprint-status: provisionalfrom this page's frontmatter, and rewrite the "Provisional commitment" heading as "Commitment".
Conventions: oxmpl - planning. Repo context: ADR docs/planning/adr/0003-motion-validation.md (decisions), CONTEXT.md (glossary). Line references are as of origin/main c558556 (2026-10-08), before E3. E3 renames things (rand Rng→RngExt, PyO3 with_gil→attach, edition 2024), so re-grep before trusting a line number.
Story specs
S4.7 — User motion validators in the bindings (size-M)
# TaskNotes task — file: task_notes/tasks/S4.7 — User motion validators in the bindings.md
title: "S4.7 — User motion validators in the bindings"
status: open
priority: normal
projects: ["[[E4 Validation — 0.9.0]]"]
tags: [oxmpl, oxmpl/epic, oxmpl/story/size-M] # add oxmpl/sprint/006 only when committed at planning
scheduled: null # set to sprint start when committed
due: null # set to sprint end when committed
blockedBy: # wire in frontmatter by hand (no MCP tool exposes it)
- uid: "[[E3 Toolchain refresh — 0.8.0]]"
reltype: FINISHTOSTART
- uid: "[[S4.5 — SpaceInformation migration]]"
reltype: FINISHTOSTART
- uid: "[[S4.6 — Binding error hierarchy]]"
reltype: FINISHTOSTART
details body:
Intent
Let Python and JS users validate a whole motion in one cross-language call (vectorised NumPy checks, physics-engine continuous collision, swept volumes) instead of one call per interpolated state. This is the main performance win of 0.9.0 for binding users.
Decisions (ADR-0003; grilling Q14)
- A user motion validator is a duck-typed object, not a callable and not a required base class: Python
check_motion(s1, s2) -> bool, JScheckMotion(s1, s2) -> boolean. - Verified when set (
set_motion_validator/ constructor kwarg): a missing method raisesConfigurationErrorimmediately, not mid-solve. - Later optional methods (e.g. a last-valid variant) are detected by presence (
hasattr/ property check) so they can be added without breaking anyone. - Strict return types: Python accepts
booland NumPybool_(pyo3 extraction already handles it); anything else, includingNone, raises. JS: non-boolean raises (replacing today'sconsole.warn+falsebehaviour). - One generic adapter per binding (via
PyStateConvert/JsStateConvert), not one per state type. - Type hints: Python
typing.Protocolstub (MotionValidator), TypeScriptinterface MotionValidator. - Exposing the built-in discrete validator as a wrappable object is not in scope (YAGNI; additive later).
Acceptance criteria
S4.9 — Docs, migration guide, ADR-0003 accepted (size-M)
# TaskNotes task — file: task_notes/tasks/S4.9 — Docs, migration guide, ADR-0003 accepted.md
title: "S4.9 — Docs, migration guide, ADR-0003 accepted"
status: open
priority: normal
projects: ["[[E4 Validation — 0.9.0]]"]
tags: [oxmpl, oxmpl/epic, oxmpl/story/size-M] # add oxmpl/sprint/006 only when committed at planning
scheduled: null # set to sprint start when committed
due: null # set to sprint end when committed
blockedBy: # wire in frontmatter by hand (no MCP tool exposes it)
- uid: "[[E3 Toolchain refresh — 0.8.0]]"
reltype: FINISHTOSTART
- uid: "[[S4.1 — PRM milestone budget]]"
reltype: FINISHTOSTART
- uid: "[[S4.2 — Fallible, thread-safe validation core]]"
reltype: FINISHTOSTART
- uid: "[[S4.3 — Space resolution valid segment count]]"
reltype: FINISHTOSTART
- uid: "[[S4.4 — Motion validator trait and discrete validator]]"
reltype: FINISHTOSTART
- uid: "[[S4.5 — SpaceInformation migration]]"
reltype: FINISHTOSTART
- uid: "[[S4.6 — Binding error hierarchy]]"
reltype: FINISHTOSTART
- uid: "[[S4.7 — User motion validators in the bindings]]"
reltype: FINISHTOSTART
- uid: "[[S4.8 — Resolution exposed in the bindings]]"
reltype: FINISHTOSTART
details body:
Intent
Document the 0.9.0 model and give users one migration path for all its breaking changes.
Acceptance criteria
-
- fallible
is_valid/is_satisfied/distance_goal(Ok(..)) Send + Syncon checkers, spaces, goals (Rc/RefCell→Arc/Mutex)PlanningErrornon-exhaustive, noPartialEq, newUservariant- default fraction 0.05 → 0.01 and no ×0.1 (set 0.005 for the old single-space spacing)
SpaceInformation+ProblemDefinition+setup(pd); bindings dropsetup; JSStateValidityCheckerremoved- binding exceptions; JS setter rename
- spaces shared and frozen once used
- fallible
S4.10 — Release 0.9.0 (size-S)
# TaskNotes task — file: task_notes/tasks/S4.10 — Release 0.9.0.md
title: "S4.10 — Release 0.9.0"
status: open
priority: normal
projects: ["[[E4 Validation — 0.9.0]]"]
tags: [oxmpl, oxmpl/epic, oxmpl/story/size-S] # add oxmpl/sprint/006 only when committed at planning
scheduled: null # set to sprint start when committed
due: null # set to sprint end when committed
blockedBy: # wire in frontmatter by hand (no MCP tool exposes it)
- uid: "[[E3 Toolchain refresh — 0.8.0]]"
reltype: FINISHTOSTART
- uid: "[[S4.1 — PRM milestone budget]]"
reltype: FINISHTOSTART
- uid: "[[S4.2 — Fallible, thread-safe validation core]]"
reltype: FINISHTOSTART
- uid: "[[S4.3 — Space resolution valid segment count]]"
reltype: FINISHTOSTART
- uid: "[[S4.4 — Motion validator trait and discrete validator]]"
reltype: FINISHTOSTART
- uid: "[[S4.5 — SpaceInformation migration]]"
reltype: FINISHTOSTART
- uid: "[[S4.6 — Binding error hierarchy]]"
reltype: FINISHTOSTART
- uid: "[[S4.7 — User motion validators in the bindings]]"
reltype: FINISHTOSTART
- uid: "[[S4.8 — Resolution exposed in the bindings]]"
reltype: FINISHTOSTART
- uid: "[[S4.9 — Docs, migration guide, ADR-0003 accepted]]"
reltype: FINISHTOSTART
details body:
Intent
Cut 0.9.0 "Validation" on all three registries through the tokenless publishing set up in E3 (S3.4).
Acceptance criteria
Tasks
Progress log
- 2026-10-08 — Scaffolded as provisional during sprint-002 planning (owner request); expanded the same day into a full regeneration spec (owner request: "enough that a blind pickup can generate all the tickets"). Not yet planned or committed.
Review & retro
At sprint end: done / carried over / dropped, what was over- or underestimated, and at most one process change for the next sprint.