Files
py-dvt-ate/docs/04_development_plan.md
Kai Chappell 85024f8670 Restructure package for domain-driven design
Reorganise package structure to improve separation of concerns:
- instruments/ - SCPI, transport, drivers, interfaces, factory
- simulation/ - physics engine, virtual instruments, server
- framework/ - test runner, logger, limits, context
- tests/ - thermal/, electrical/ (DVT test implementations)
- data/ - repository, models
- reporting/ - generator, templates
- app/ - CLI, config, dashboard

This structure enables:
- Reusable instruments package for other test suites
- Clear separation of simulation (dev) vs production code
- Domain-focused package organisation

Updated documentation to reflect new paths.
2025-02-10 12:06:22 +00:00

19 KiB

Phase 1 Development Plan: py-dvt-ate MVP

Document ID DEV-001
Version 2.0.0
Status Approved
Author Kai Chappell
Created 2025-12-01
Last Updated 2025-12-01

Purpose

This document defines when to build each component of py-dvt-ate Phase 1. It provides an iterative sprint breakdown with atomic tasks optimised for incremental development.

For what the system must do, see 01_requirements.md. For how to implement the system, see 02_technical_specification.md. For why decisions were made, see 03_architecture_decisions.md.


Design Principles

  1. Small, Focused Commits - Each task = 1 commit, ~50-150 lines changed
  2. Stubs First - Define interfaces/types before implementation
  3. Vertical Slice First - Get something visual early, then build infrastructure
  4. Minimal Context - Each task completable with knowledge of 1-3 files
  5. Test Alongside - Write tests immediately after implementation
  6. Iterative Refinement - Get something working, then improve

Sprint Structure

Each sprint is ~1-2 days of work, producing demonstrable progress.

Vertical Slice Strategy:

  • Sprints 1-3: Foundation + Physics Engine (the core simulation)
  • Sprint 4: Dashboard (see the physics working!)
  • Sprints 5-11: Infrastructure/Plumbing (SCPI, TCP, Instruments)
  • Sprints 12-17: Test Framework, CLI, Polish

Sprint 1: Project Foundation

Goal: Establish project structure and build system.

Task 1.1: Create pyproject.toml

  • Create minimal pyproject.toml with project metadata
  • Package name: py_dvt_ate
  • Include only core dependencies initially
  • Commit: "Add pyproject.toml with core dependencies"

Task 1.2: Create directory structure (empty)

  • Create src/py_dvt_ate/ with init.py and py.typed
  • Create empty subpackage directories with init.py
  • Create tests/ directory structure
  • Create config/ directory
  • Commit: "Add package directory structure"

Task 1.3: Add development tooling config

  • Add ruff configuration to pyproject.toml
  • Add mypy configuration to pyproject.toml
  • Add pytest configuration to pyproject.toml
  • Commit: "Configure development tooling (ruff, mypy, pytest)"

Task 1.4: Create basic CLI entry point

  • Create src/py_dvt_ate/cli/init.py
  • Create src/py_dvt_ate/cli/main.py with Typer app stub
  • Add version command only
  • Commit: "Add CLI entry point with version command"

Sprint 2: Physics Engine Core (Stubs)

Goal: Define physics interfaces and data structures.

Task 2.1: Define thermal state dataclasses

  • Create src/py_dvt_ate/simulation/physics/models.py
  • Define ThermalState (frozen dataclass)
  • Define ElectricalState (frozen dataclass)
  • Commit: "Add physics state dataclasses"

Task 2.2: Define DUT base protocol

  • Create src/py_dvt_ate/simulation/physics/models/base.py
  • Define DUTModel Protocol with method signatures
  • Commit: "Add DUT model protocol"

Task 2.3: Create physics engine stub

  • Create src/py_dvt_ate/simulation/physics/engine.py
  • Define PhysicsEngine class with stub methods
  • Methods return placeholder values
  • Commit: "Add physics engine stub"

Task 2.4: Add physics unit tests (for stubs)

  • Create tests/unit/test_physics_models.py
  • Test dataclass creation and immutability
  • Commit: "Add physics model unit tests"

Sprint 3: Physics Engine Implementation

Goal: Implement working physics simulation.

Task 3.1: Implement thermal calculations

  • Create src/py_dvt_ate/simulation/physics/thermal.py
  • Implement first-order thermal response calculations
  • Pure functions, no state
  • Commit: "Implement thermal calculation functions"

Task 3.2: Implement LDO DUT model

  • Create src/py_dvt_ate/simulation/physics/models/ldo.py
  • Implement LDOModel class
  • Temperature-dependent Vout, Iq calculations
  • Power dissipation calculation
  • Commit: "Implement LDO DUT model"

Task 3.3: Implement physics engine step()

  • Update engine.py with working step() method
  • Integrate thermal calculations
  • Integrate DUT model
  • Commit: "Implement physics engine stepping"

Task 3.4: Add physics integration tests

  • Create tests/unit/test_physics_engine.py
  • Test thermal settling behaviour
  • Test self-heating effects
  • Commit: "Add physics engine tests"

Sprint 4: Streamlit Dashboard (Early Visual!)

Goal: Visualise physics engine directly - see something working!

Task 4.1: Create dashboard app skeleton

  • Create src/py_dvt_ate/app/dashboard/init.py
  • Create src/py_dvt_ate/app/dashboard/app.py
  • Basic Streamlit page with title
  • Commit: "Add Streamlit dashboard skeleton"

Task 4.2: Add physics visualisation panel

  • Create direct connection to PhysicsEngine (no HAL yet)
  • Display chamber temperature, DUT temperature
  • Real-time updating chart
  • Commit: "Add physics visualisation panel"

Task 4.3: Add interactive controls

  • Temperature setpoint slider
  • Input voltage control
  • Load current control
  • Start/Stop simulation button
  • Commit: "Add interactive physics controls"

Task 4.4: Add self-heating demonstration

  • Show junction temperature vs case temperature
  • Demonstrate thermal coupling visually
  • Commit: "Add self-heating visualisation"

Milestone: Working "Virtual Lab Bench" toy to play with!


Sprint 5: SCPI Foundation

Goal: Create SCPI parsing infrastructure.

Task 5.1: Define SCPI command dataclass

  • Create src/py_dvt_ate/instruments/init.py
  • Create src/py_dvt_ate/instruments/scpi.py
  • Define SCPICommand dataclass
  • Commit: "Add SCPI command dataclass"

Task 5.2: Implement SCPI parser

  • Implement SCPIParser.parse() method
  • Handle queries, commands with arguments
  • Handle IEEE 488.2 common commands (*IDN?, *RST)
  • Commit: "Implement SCPI parser"

Task 5.3: Add SCPI parser tests

  • Create tests/unit/test_scpi_parser.py
  • Test various command formats
  • Test edge cases
  • Commit: "Add SCPI parser tests"

Sprint 6: Instrument Base & Thermal Chamber Simulator

Goal: Create first virtual instrument.

Task 6.1: Define instrument base class

  • Create src/py_dvt_ate/simulation/virtual/base.py
  • Define BaseInstrument with common functionality
  • Command dispatch mechanism
  • Commit: "Add base instrument class"

Task 6.2: Create thermal chamber simulator stub

  • Create src/py_dvt_ate/simulation/virtual/chamber.py
  • Define ThermalChamberSim class
  • Stub SCPI command handlers
  • Commit: "Add thermal chamber simulator stub"

Task 6.3: Implement thermal chamber commands

  • Implement TEMP:SETPOINT, TEMP:ACTUAL?, TEMP:STAB?
  • Connect to physics engine reference
  • Commit: "Implement thermal chamber SCPI commands"

Task 6.4: Add thermal chamber tests

  • Create tests/unit/test_thermal_chamber.py
  • Test SCPI command responses
  • Commit: "Add thermal chamber simulator tests"

Sprint 7: Power Supply & DMM Simulators

Goal: Complete instrument simulators.

Task 7.1: Create power supply simulator

  • Create src/py_dvt_ate/simulation/virtual/power_supply.py
  • Implement PSU SCPI commands
  • VOLT, CURR, OUTP, MEAS commands
  • Commit: "Add power supply simulator"

Task 7.2: Add power supply tests

  • Create tests/unit/test_power_supply.py
  • Commit: "Add power supply simulator tests"

Task 7.3: Create DMM simulator

  • Create src/py_dvt_ate/simulation/virtual/multimeter.py
  • Implement DMM SCPI commands
  • MEAS:VOLT:DC?, CONF commands
  • Commit: "Add multimeter simulator"

Task 7.4: Add DMM tests

  • Create tests/unit/test_multimeter.py
  • Commit: "Add multimeter simulator tests"

Sprint 8: TCP Server

Goal: Expose instruments over network.

Task 8.1: Create async TCP server foundation

  • Create src/py_dvt_ate/simulation/init.py
  • Create src/py_dvt_ate/simulation/tcp_server.py
  • Define InstrumentServer class with asyncio
  • Commit: "Add async TCP server foundation"

Task 8.2: Implement client connection handling

  • Handle multiple concurrent connections
  • Line-based SCPI protocol (newline terminated)
  • Commit: "Implement TCP client handling"

Task 8.3: Create server main entry point

  • Create src/py_dvt_ate/simulation/server.py
  • Wire up physics engine and instruments
  • Add CLI command to start server
  • Commit: "Add simulation server entry point"

Task 8.4: Add server integration tests

  • Create tests/integration/test_tcp_server.py
  • Test connection and basic commands
  • Commit: "Add TCP server integration tests"

Sprint 9: Transport Layer (Client Side)

Goal: Create client-side communication.

Task 9.1: Define transport protocol

  • Create src/py_dvt_ate/instruments/transport/init.py
  • Create src/py_dvt_ate/instruments/transport/base.py
  • Define Transport Protocol class
  • Commit: "Add transport protocol definition"

Task 9.2: Implement TCP transport

  • Create src/py_dvt_ate/instruments/transport/tcp.py
  • Implement TCPTransport class
  • connect(), write(), read(), query() methods
  • Commit: "Implement TCP transport"

Task 9.3: Add transport tests

  • Create tests/unit/test_transport.py
  • Test with mock socket
  • Commit: "Add transport layer tests"

Sprint 10: SCPI Drivers

Goal: Create instrument drivers using transport.

Task 10.1: Define driver base class

  • Create src/py_dvt_ate/instruments/drivers/init.py
  • Create src/py_dvt_ate/instruments/drivers/base.py
  • Define BaseDriver with transport dependency
  • Commit: "Add driver base class"

Task 10.2: Implement thermal chamber driver

  • Create src/py_dvt_ate/instruments/drivers/chamber.py
  • Methods map to SCPI commands
  • Commit: "Add thermal chamber driver"

Task 10.3: Implement PSU and DMM drivers

  • Create src/py_dvt_ate/instruments/drivers/power_supply.py
  • Create src/py_dvt_ate/instruments/drivers/multimeter.py
  • Commit: "Add PSU and DMM drivers"

Task 10.4: Add driver tests

  • Create tests/unit/test_drivers.py
  • Test command formatting
  • Commit: "Add driver unit tests"

Sprint 11: Instrument Interfaces

Goal: Create instrument protocol interfaces and factory.

Task 11.1: Define instrument interface protocols

  • Create src/py_dvt_ate/instruments/interfaces.py
  • Define IThermalChamber, IPowerSupply, IMultimeter protocols
  • Commit: "Add instrument interface protocols"

Task 11.2: Ensure drivers implement interfaces

  • Update drivers to satisfy Protocol interfaces
  • Add type hints for interface compliance
  • Commit: "Implement instrument interfaces in drivers"

Task 11.3: Create instrument factory

  • Create src/py_dvt_ate/instruments/factory.py
  • InstrumentSet dataclass
  • InstrumentFactory.create() method
  • Commit: "Add instrument factory"

Task 11.4: Add instrument interface tests

  • Create tests/unit/test_instruments.py
  • Test factory creates correct types
  • Commit: "Add instrument interface tests"

Sprint 12: Configuration System

Goal: YAML-based configuration.

Task 12.1: Define config models

  • Create src/py_dvt_ate/app/config.py
  • Define Pydantic models for all config sections
  • Commit: "Add configuration Pydantic models"

Task 12.2: Implement config loader

  • Add load_config() function to src/py_dvt_ate/app/config.py
  • Load YAML, validate with Pydantic
  • Environment variable overrides
  • Commit: "Implement configuration loader"

Task 12.3: Create default config file

  • Create config/default.yaml
  • Document all options
  • Commit: "Add default configuration file"

Task 12.4: Add config tests

  • Create tests/unit/test_config.py
  • Commit: "Add configuration tests"

Sprint 13: Data Persistence

Goal: Store test results.

Task 13.1: Define data models

  • Create src/py_dvt_ate/data/init.py
  • Create src/py_dvt_ate/data/models.py
  • TestRun, TestResult, Measurement dataclasses
  • Commit: "Add data persistence models"

Task 13.2: Create SQLite repository

  • Create src/py_dvt_ate/data/repository.py
  • Implement test run and result storage
  • Commit: "Implement SQLite repository"

Task 13.3: Add Parquet measurement storage

  • Extend repository for Parquet files
  • Batch measurement writing
  • Commit: "Add Parquet measurement storage"

Task 13.4: Add data persistence tests

  • Create tests/unit/test_repository.py
  • Commit: "Add data persistence tests"

Sprint 14: Test Executive Framework

Goal: Test execution orchestration.

Task 14.1: Define test interface and models

  • Create src/py_dvt_ate/framework/init.py
  • Create src/py_dvt_ate/framework/context.py
  • TestStatus enum, TestContext, ITest protocol
  • Commit: "Add test framework models"

Task 14.2: Implement test logger

  • Create src/py_dvt_ate/framework/logger.py
  • Log measurements and events
  • Commit: "Implement test logger"

Task 14.3: Implement limit checker

  • Create src/py_dvt_ate/framework/limits.py
  • Evaluate pass/fail against limits
  • Commit: "Implement limit checker"

Task 14.4: Implement test runner

  • Create src/py_dvt_ate/framework/runner.py
  • Run tests, collect results
  • Commit: "Implement test runner"

Sprint 15: TempCo Characterisation Test

Goal: First complete DVT test.

Task 15.1: Define test base class

  • Create src/py_dvt_ate/tests/init.py
  • Create src/py_dvt_ate/tests/base.py
  • Common test utilities
  • Commit: "Add DVT test base class"

Task 15.2: Implement TempCo test

  • Create src/py_dvt_ate/tests/thermal/tempco.py
  • Temperature sweep logic
  • Vout measurement at each temperature
  • TempCo calculation
  • Commit: "Implement TempCo characterisation test"

Task 15.3: Add TempCo test integration tests

  • Create tests/integration/test_tempco.py
  • Full end-to-end test with simulator
  • Commit: "Add TempCo integration tests"

Sprint 16: CLI Enhancement

Goal: Complete CLI for test execution.

Task 16.1: Add server commands to CLI

  • start-server command
  • Configure ports via options
  • Commit: "Add server CLI commands"

Task 16.2: Add test execution commands

  • run-test command
  • List available tests
  • Commit: "Add test execution CLI commands"

Task 16.3: Add instrument query commands

  • Direct instrument query/command
  • Useful for debugging
  • Commit: "Add instrument CLI commands"

Sprint 17: Dashboard Enhancement & Polish

Goal: Connect dashboard to full stack + end-to-end verification.

Task 17.1: Update dashboard to use HAL

  • Replace direct physics connection with HAL
  • Add instrument status panels
  • Commit: "Update dashboard to use HAL"

Task 17.2: Add test execution page

  • Run tests from dashboard
  • Progress display
  • Commit: "Add test execution dashboard page"

Task 17.3: Add results viewer page

  • Historical results display
  • Basic charts
  • Commit: "Add results viewer dashboard page"

Task 17.4: End-to-end integration test

  • Create tests/integration/test_e2e.py
  • Full workflow: start server, run test, check results
  • Commit: "Add end-to-end integration test"

Task 17.5: Update README with usage

  • Quick start guide
  • Example commands
  • Screenshots
  • Commit: "Update README with usage instructions"

Task 17.6: Verify test coverage

  • Run coverage report
  • Add tests for gaps
  • Commit: "Improve test coverage to 80%+"

File Dependencies Map

simulation/physics/models.py         → (none)
simulation/physics/models/base.py    → models.py
simulation/physics/models/ldo.py     → base.py, models.py
simulation/physics/thermal.py        → models.py
simulation/physics/engine.py         → models.py, thermal.py, models/base.py

app/dashboard/app.py                 → simulation/physics/engine.py (Sprint 4)

instruments/scpi.py                  → (none)
simulation/virtual/base.py           → instruments/scpi.py
simulation/virtual/*.py              → base.py, simulation/physics/engine.py

instruments/transport/base.py        → (none)
instruments/transport/tcp.py         → base.py

instruments/drivers/base.py          → instruments/transport/base.py
instruments/drivers/*.py             → base.py

instruments/interfaces.py            → (none)
instruments/factory.py               → interfaces.py, drivers/*.py

app/config.py                        → (none)

data/models.py                       → (none)
data/repository.py                   → models.py

framework/context.py                 → instruments/interfaces.py
framework/*.py                       → context.py, data/repository.py

tests/*.py                           → framework/context.py, instruments/interfaces.py

app/dashboard/app.py                 → instruments/factory.py (Sprint 17, upgraded)

Versioning Strategy

Semantic Versioning

This project follows Semantic Versioning 2.0.0:

MAJOR.MINOR.PATCH[-PRERELEASE]

- MAJOR: Breaking API changes
- MINOR: New features, backwards compatible
- PATCH: Bug fixes, backwards compatible
- PRERELEASE: alpha.N, beta.N, rc.N

Phase 1 Version Progression

Sprint Version Tag Milestone Release Type
1 v0.0.1 Project scaffolding Internal
3 v0.1.0-alpha.1 Physics engine working Pre-release
4 v0.1.0-alpha.2 Visual demo (dashboard) Pre-release
8 v0.1.0-alpha.3 Network ready (TCP server) Pre-release
11 v0.1.0-beta.1 Interfaces complete Pre-release
15 v0.1.0-beta.2 First DVT test runs Pre-release
17 v0.1.0 MVP Complete Release

Tagging Convention

# After completing a milestone sprint:
git tag -a v0.1.0-alpha.1 -m "Physics engine working"
git push origin v0.1.0-alpha.1

Version Location

The version is defined in one place and read elsewhere:

src/py_dvt_ate/__init__.py:
    __version__ = "0.1.0-alpha.1"

pyproject.toml:
    [project]
    dynamic = ["version"]

    [tool.hatch.version]
    path = "src/py_dvt_ate/__init__.py"

CI/CD Pipeline

On every push:

  • Run ruff check (linting)
  • Run mypy (type checking)
  • Run pytest (tests)

On tag push (v*):

  • All of the above
  • Build package
  • Create release

CHANGELOG

Maintain CHANGELOG.md following Keep a Changelog:

## [Unreleased]
### Added
- ...

## [0.1.0-alpha.1] - 2025-12-XX
### Added
- Physics engine with thermal-electrical coupling
- LDO DUT model with temperature coefficient

Milestone Summary

Sprint Version Milestone What You Can Demo
1 v0.0.1 Scaffolding Package installs
3 v0.1.0-alpha.1 Physics Working Unit tests prove thermal coupling
4 v0.1.0-alpha.2 Visual Demo! Interactive Streamlit showing physics
7 - Instruments Done SCPI simulators respond to commands
8 v0.1.0-alpha.3 Network Ready TCP server accepts connections
11 v0.1.0-beta.1 Interfaces Complete Instrument layer swappable
15 v0.1.0-beta.2 First Test TempCo characterisation runs
17 v0.1.0 MVP Complete Full end-to-end workflow

End of Development Plan