# Development Plan ## Phase 1: Vertical Slice (MVP) | Document ID | DEV-001 | |-------------|---------| | Version | 1.0.0 | | Status | Active | | Author | Kai Chappell | | Created | 2025-12-01 | --- ## Approach This plan follows an **iterative, stub-first development** strategy optimised for incremental progress: 1. **Interfaces First** - Define protocols/interfaces before implementations 2. **Stubs Before Logic** - Create skeleton classes that pass type checks before adding behaviour 3. **Bottom-Up Construction** - Build foundational layers before dependent layers 4. **Frequent Commits** - Small, atomic commits after each meaningful change 5. **Minimal Context** - Each iteration should be completable with minimal codebase knowledge --- ## Sprint Structure Each sprint represents ~2-4 hours of focused work. Sprints are designed to be self-contained with clear deliverables. --- ## Sprint 1: Project Scaffolding **Goal:** Create project structure and build configuration. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 1.1 | Create `pyproject.toml` with project metadata and dependencies | `chore: add pyproject.toml with dependencies` | | 1.2 | Create `src/thermaulate/__init__.py` with version | `chore: create package structure` | | 1.3 | Create empty subpackage `__init__.py` files for all modules | `chore: add subpackage stubs` | | 1.4 | Create `py.typed` marker file | `chore: add py.typed marker for PEP 561` | | 1.5 | Create `config/default.yaml` with basic structure | `chore: add default configuration file` | ### Deliverables - `pip install -e .` works - All imports resolve (empty packages) - Type checker can be run --- ## Sprint 2: Configuration System **Goal:** Load and validate configuration. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 2.1 | Create `config/models.py` with Pydantic config classes | `feat(config): add Pydantic configuration models` | | 2.2 | Create `config/loader.py` to load YAML and return AppConfig | `feat(config): add configuration loader` | | 2.3 | Add unit tests for config loading | `test(config): add configuration tests` | ### Deliverables - Can load `config/default.yaml` into typed Python objects - Invalid configs raise clear errors --- ## Sprint 3: Transport Layer (Stubs) **Goal:** Define transport abstractions. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 3.1 | Create `transport/base.py` with `Transport` Protocol | `feat(transport): add Transport protocol` | | 3.2 | Create `transport/tcp.py` with `TCPTransport` stub class | `feat(transport): add TCPTransport stub` | ### Deliverables - Transport interface defined - TCPTransport class exists with NotImplementedError methods --- ## Sprint 4: Transport Layer (Implementation) **Goal:** Implement TCP transport. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 4.1 | Implement `TCPTransport.connect()` and `disconnect()` | `feat(transport): implement TCP connect/disconnect` | | 4.2 | Implement `TCPTransport.write()` and `read()` | `feat(transport): implement TCP read/write` | | 4.3 | Implement `TCPTransport.query()` | `feat(transport): implement TCP query` | | 4.4 | Add unit tests with mock socket | `test(transport): add TCP transport tests` | ### Deliverables - Can connect to TCP server and exchange messages - Handles connection errors gracefully --- ## Sprint 5: SCPI Parser **Goal:** Parse SCPI command strings. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 5.1 | Create `instruments/scpi_parser.py` with `SCPICommand` dataclass | `feat(scpi): add SCPICommand dataclass` | | 5.2 | Implement `SCPIParser.parse()` method | `feat(scpi): implement SCPI parser` | | 5.3 | Add comprehensive parser tests | `test(scpi): add parser tests` | ### Deliverables - Can parse `*IDN?`, `VOLT 3.3`, `TEMP:SETPOINT?`, etc. - Returns structured command objects --- ## Sprint 6: Physics Engine (Stubs) **Goal:** Define physics simulation interfaces. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 6.1 | Create `physics/engine.py` with state dataclasses | `feat(physics): add ThermalState and ElectricalState` | | 6.2 | Create `PhysicsEngine` class with stub methods | `feat(physics): add PhysicsEngine stub` | | 6.3 | Create `physics/dut/base.py` with `DUTModel` Protocol | `feat(physics): add DUT model protocol` | ### Deliverables - Physics interfaces defined - State objects can be instantiated --- ## Sprint 7: Physics Engine (Thermal) **Goal:** Implement thermal simulation. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 7.1 | Implement `PhysicsEngine.step()` thermal calculations | `feat(physics): implement thermal step` | | 7.2 | Implement `PhysicsEngine.set_chamber_setpoint()` | `feat(physics): implement chamber setpoint` | | 7.3 | Implement `PhysicsEngine.get_thermal_state()` | `feat(physics): implement thermal state getter` | | 7.4 | Add thermal simulation tests | `test(physics): add thermal simulation tests` | ### Deliverables - Chamber temperature ramps toward setpoint - Case temperature follows with time constant --- ## Sprint 8: LDO DUT Model **Goal:** Implement LDO electrical model. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 8.1 | Create `physics/dut/ldo.py` with `LDOModel` class | `feat(physics): add LDO model stub` | | 8.2 | Implement temperature-dependent output voltage | `feat(physics): implement LDO Vout vs temperature` | | 8.3 | Implement power dissipation calculation | `feat(physics): implement LDO power dissipation` | | 8.4 | Implement quiescent current model | `feat(physics): implement LDO quiescent current` | | 8.5 | Add LDO model tests | `test(physics): add LDO model tests` | ### Deliverables - LDO output voltage varies with temperature (TempCo) - Power dissipation calculated correctly --- ## Sprint 9: Physics Engine (Electrical Coupling) **Goal:** Connect electrical and thermal domains. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 9.1 | Integrate LDO model into PhysicsEngine | `feat(physics): integrate DUT model` | | 9.2 | Implement self-heating feedback loop | `feat(physics): implement self-heating` | | 9.3 | Implement `get_electrical_state()` | `feat(physics): implement electrical state getter` | | 9.4 | Add coupled physics tests | `test(physics): add thermal-electrical coupling tests` | ### Deliverables - Higher load current causes self-heating - Junction temperature affects output voltage --- ## Sprint 10: Virtual Instruments (Stubs) **Goal:** Define virtual instrument classes. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 10.1 | Create `instruments/base.py` with `VirtualInstrument` base class | `feat(instruments): add VirtualInstrument base` | | 10.2 | Create `instruments/thermal_chamber.py` stub | `feat(instruments): add ThermalChamberSim stub` | | 10.3 | Create `instruments/power_supply.py` stub | `feat(instruments): add PowerSupplySim stub` | | 10.4 | Create `instruments/multimeter.py` stub | `feat(instruments): add MultimeterSim stub` | ### Deliverables - All instrument classes exist - Common SCPI commands stubbed (IDN, RST) --- ## Sprint 11: Thermal Chamber Simulator **Goal:** Implement thermal chamber SCPI commands. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 11.1 | Implement `TEMP:SETPOINT` command | `feat(instruments): implement chamber TEMP:SETPOINT` | | 11.2 | Implement `TEMP:ACTUAL?` query | `feat(instruments): implement chamber TEMP:ACTUAL?` | | 11.3 | Implement `TEMP:STAB?` query | `feat(instruments): implement chamber stability query` | | 11.4 | Add thermal chamber tests | `test(instruments): add thermal chamber tests` | ### Deliverables - Chamber responds to SCPI commands - Reads from physics engine state --- ## Sprint 12: Power Supply Simulator **Goal:** Implement power supply SCPI commands. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 12.1 | Implement `VOLT`, `CURR`, `OUTP` commands | `feat(instruments): implement PSU control commands` | | 12.2 | Implement `MEAS:VOLT?`, `MEAS:CURR?` queries | `feat(instruments): implement PSU measurements` | | 12.3 | Add power supply tests | `test(instruments): add power supply tests` | ### Deliverables - PSU responds to voltage/current/output commands - Measurements reflect physics state --- ## Sprint 13: Multimeter Simulator **Goal:** Implement DMM SCPI commands. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 13.1 | Implement `MEAS:VOLT:DC?` query | `feat(instruments): implement DMM voltage measurement` | | 13.2 | Implement `SENS:VOLT:DC:NPLC` command | `feat(instruments): implement DMM NPLC setting` | | 13.3 | Add multimeter tests | `test(instruments): add multimeter tests` | ### Deliverables - DMM returns DUT output voltage from physics - Integration time configurable --- ## Sprint 14: TCP Server **Goal:** Create async TCP server for instruments. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 14.1 | Create `server/tcp_server.py` with async server class | `feat(server): add async TCP server` | | 14.2 | Implement connection handling and command dispatch | `feat(server): implement command dispatch` | | 14.3 | Create `server/main.py` entry point | `feat(server): add server entry point` | | 14.4 | Add server integration tests | `test(server): add TCP server tests` | ### Deliverables - Server listens on configured ports - Routes commands to correct instrument - Runs physics engine in background --- ## Sprint 15: HAL Interfaces **Goal:** Define hardware abstraction protocols. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 15.1 | Create `hal/interfaces.py` with all Protocol classes | `feat(hal): add HAL protocol definitions` | | 15.2 | Create `hal/factory.py` with `InstrumentSet` and stub factory | `feat(hal): add instrument factory stub` | ### Deliverables - IThermalChamber, IPowerSupply, IMultimeter defined - Factory interface established --- ## Sprint 16: SCPI Drivers **Goal:** Create client-side SCPI drivers. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 16.1 | Create `drivers/base.py` with common driver functionality | `feat(drivers): add driver base class` | | 16.2 | Create `drivers/thermal_chamber.py` | `feat(drivers): add thermal chamber driver` | | 16.3 | Create `drivers/power_supply.py` | `feat(drivers): add power supply driver` | | 16.4 | Create `drivers/multimeter.py` | `feat(drivers): add multimeter driver` | ### Deliverables - Drivers send SCPI commands via transport - Parse responses into Python types --- ## Sprint 17: HAL Implementations **Goal:** Implement HAL using drivers. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 17.1 | Create `hal/impl/thermal_chamber.py` | `feat(hal): implement ThermalChamberHAL` | | 17.2 | Create `hal/impl/power_supply.py` | `feat(hal): implement PowerSupplyHAL` | | 17.3 | Create `hal/impl/multimeter.py` | `feat(hal): implement MultimeterHAL` | | 17.4 | Implement `InstrumentFactory.create()` | `feat(hal): implement instrument factory` | | 17.5 | Add HAL integration tests | `test(hal): add HAL integration tests` | ### Deliverables - HAL classes wrap drivers - Factory creates connected instrument set --- ## Sprint 18: Test Executive (Core) **Goal:** Create test execution framework. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 18.1 | Create `executive/models.py` with domain models | `feat(executive): add test domain models` | | 18.2 | Create `executive/context.py` with TestContext | `feat(executive): add test context` | | 18.3 | Create `executive/logger.py` with test logger | `feat(executive): add test logger` | | 18.4 | Create `executive/limits.py` with limit checker | `feat(executive): add limit checker` | ### Deliverables - Can create test contexts - Can log measurements - Can evaluate limits --- ## Sprint 19: Test Executive (Sequencer) **Goal:** Implement test sequencer. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 19.1 | Create `executive/sequencer.py` with TestSequencer class | `feat(executive): add test sequencer` | | 19.2 | Create `tests/base.py` with ITest protocol | `feat(tests): add test base class` | | 19.3 | Add sequencer tests | `test(executive): add sequencer tests` | ### Deliverables - Sequencer runs test instances - Manages context lifecycle --- ## Sprint 20: TempCo Test Implementation **Goal:** Implement temperature coefficient characterisation test. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 20.1 | Create `tests/tempco.py` with TempCoTest class | `feat(tests): add TempCo test stub` | | 20.2 | Implement temperature sweep logic | `feat(tests): implement TempCo temperature sweep` | | 20.3 | Implement TempCo calculation | `feat(tests): implement TempCo calculation` | | 20.4 | Add TempCo test tests | `test(tests): add TempCo test coverage` | ### Deliverables - Complete TempCo characterisation test - Calculates ppm/°C result --- ## Sprint 21: Data Persistence (Schema) **Goal:** Set up data storage. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 21.1 | Create `data/models.py` with data models | `feat(data): add data models` | | 21.2 | Create `data/migrations/001_initial.sql` | `feat(data): add initial schema migration` | | 21.3 | Create `data/repository.py` with repository interface | `feat(data): add repository interface` | ### Deliverables - SQLite schema defined - Repository interface established --- ## Sprint 22: Data Persistence (Implementation) **Goal:** Implement data repository. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 22.1 | Implement SQLite repository for test runs | `feat(data): implement test run persistence` | | 22.2 | Implement Parquet writer for measurements | `feat(data): implement measurement persistence` | | 22.3 | Add repository tests | `test(data): add repository tests` | ### Deliverables - Test runs persisted to SQLite - Measurements saved as Parquet files --- ## Sprint 23: CLI (Basic) **Goal:** Create command-line interface. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 23.1 | Create `cli/main.py` with Typer app | `feat(cli): add CLI application` | | 23.2 | Add `server start` command | `feat(cli): add server start command` | | 23.3 | Add `test run` command | `feat(cli): add test run command` | | 23.4 | Add `test list` command | `feat(cli): add test list command` | ### Deliverables - `thermaulate server start` launches simulation - `thermaulate test run tempco` executes test --- ## Sprint 24: Streamlit Dashboard (Basic) **Goal:** Create real-time monitoring dashboard. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 24.1 | Create `dashboard/app.py` with main Streamlit app | `feat(dashboard): add Streamlit app` | | 24.2 | Create instruments status page | `feat(dashboard): add instruments page` | | 24.3 | Add real-time temperature chart | `feat(dashboard): add temperature chart` | ### Deliverables - Dashboard shows instrument status - Temperature updates in real-time --- ## Sprint 25: Integration & Polish **Goal:** End-to-end testing and refinement. ### Tasks | # | Task | Commit Message | |---|------|----------------| | 25.1 | Run full TempCo test end-to-end | `test: add end-to-end TempCo test` | | 25.2 | Fix any integration issues discovered | `fix: resolve integration issues` | | 25.3 | Add demo script | `docs: add demo script` | | 25.4 | Update README with usage instructions | `docs: update README with usage` | | 25.5 | Verify 80% test coverage on core modules | `test: ensure coverage targets met` | ### Deliverables - Complete working vertical slice - Demo-able system - Documentation updated --- ## Sprint Summary | Sprint | Focus | Estimated Tasks | |--------|-------|-----------------| | 1 | Project scaffolding | 5 | | 2 | Configuration | 3 | | 3-4 | Transport layer | 7 | | 5 | SCPI parser | 3 | | 6-9 | Physics engine | 16 | | 10-13 | Virtual instruments | 14 | | 14 | TCP server | 4 | | 15-17 | HAL layer | 10 | | 18-19 | Test executive | 7 | | 20 | TempCo test | 4 | | 21-22 | Data persistence | 6 | | 23 | CLI | 4 | | 24 | Dashboard | 3 | | 25 | Integration | 5 | **Total: 25 sprints, ~91 tasks, ~91 commits** --- ## LLM Optimisation Notes Each sprint is designed for LLM execution with: 1. **Minimal Context Required** - Each sprint focuses on 1-2 files 2. **Clear Boundaries** - Interfaces defined before implementations 3. **Testable Increments** - Each sprint has verification criteria 4. **Atomic Commits** - Small, focused changes that are easy to review 5. **Stub-First Approach** - Type-safe placeholders before full logic When starting a sprint: 1. Read only the relevant module's existing code 2. Reference interfaces/protocols, not implementations 3. Complete all tasks before moving to next sprint 4. Commit after each task --- **End of Development Plan**