Skip to content

fix(pc): Phase 4.4 — virtual-clock HIL sims, real physics fixes, HSMS close sentinel - #172

Merged
alovladi007 merged 2 commits into
mainfrom
fix/phase-4.4-virtual-clock
Aug 3, 2026
Merged

fix(pc): Phase 4.4 — virtual-clock HIL sims, real physics fixes, HSMS close sentinel#172
alovladi007 merged 2 commits into
mainfrom
fix/phase-4.4-virtual-clock

Conversation

@alovladi007

Copy link
Copy Markdown
Owner

Why

Phase 4.4 was the tracked "physics reconciliation" debt. Investigation showed the soak tests' wall-clock coupling had been masking a stack of real defects — in the simulators, the recipe engine, and the HSMS transport. This PR gives the HIL sims a true virtual clock and fixes everything that surfaced once 12 simulated hours actually ran.

Root cause chain

  1. Time was silently discarded: _update_simulation int-truncated elapsed/dt and reset the clock, so any poll faster than one timestep advanced the sim zero steps while consuming the time. Sim progress depended on caller cadence → the pass/fail flips between identical runs.
  2. With a real clock, the plant couldn't reach 1000°C: losses were computed over the full wafer area in every zone (a 4× double-count) against a 10 kW total bank — equilibrium at ~450°C, lamps saturated.
  3. The zone integrator applied a dimensionally-wrong dt²/τ double-lag (physics ~25× too sluggish, timestep-dependent). The lag now lives on the lamp (actuator), temperature integrates directly.
  4. set_target_temperature ignored the requested ramp rate (now honored via setpoint profiling) and clobbered RUNNING_RECIPE status — every recipe reported is_running=False from the first poll.
  5. Natural recipe completion cleared _run_id, making finished recipes report 0% progress — the stress test scored 0/3 on recipes that had completed.
  6. The 72h test's own timeout counted only dwell times (ramp-dominated recipes always "timed out") and polled at 500 simulated seconds per iteration.
  7. HSMS: reader-task EOF never woke coroutines blocked in recv_data_message — the handler hung until cancelled (the skipped equipment_manager test). A close sentinel through the data queue makes shutdown deterministic.

Plus: PID anti-windup, and the stale CI comment claiming physics files were "excluded" (they run — all 441 — and pass) corrected.

Proof

  • Soak suite 6/6, twice consecutively (was 1 pass, 4 xfail, 1 xpass — with flips between runs)
  • RTP 12h: holds 1000°C with 1.5°C pyrometer std, 0.04°C mean control error (was 45°C std, 550°C error)
  • Recipe stress: 3/3 completed (was 0/3)
  • Un-skipped race test: 5/5 consecutive passes
  • pc unit + integration: 460 passed (was 459 + 1 skip)
  • time_acceleration defaults to 1.0 — production behavior unchanged

🤖 Generated with Claude Code

alovladi007 and others added 2 commits August 3, 2026 16:38
… close sentinel

The soak suite's wall-clock coupling had been masking a stack of real
defects; giving the sims a virtual clock surfaced and fixed them all.

Virtual clock (both HIL drivers, time_acceleration param, default 1.0):
- rtp_hil: _update_simulation now accumulates a residual instead of
  int-truncating elapsed/dt and resetting the clock — the old code
  silently DISCARDED time on any poll faster than one timestep, so sim
  progress depended on caller cadence (the source of the flakiness).
  Recipe/segment elapsed times run on the same accelerated clock.
- ion_implant_hil: dose integration and beam jitter use accelerated
  elapsed; at 1.0 production behavior is unchanged.

Physics defects exposed and fixed once the sim actually ran 12 hours:
- Power budget: losses were computed over the FULL wafer area in every
  zone (4x double-count) while each zone got 1/4 of a 10 kW bank — the
  plant saturated ~450C and could never reach a 1000C setpoint. Zone
  loss area is now area/num_zones and the bank is 10 kW/zone.
- Zone integrator applied a dimensionally-wrong dt^2/tau double-lag
  (response scaled with the timestep, ~25x too sluggish). Temperature
  now integrates directly; the zone time constant models the LAMP's
  first-order response, where the lag physically belongs.
- PID anti-windup: integral clamped to actuator authority.
- set_target_temperature honors ramp_rate_C_per_s via setpoint
  profiling (was silently ignored).
- set_target_temperature no longer clobbers RUNNING_RECIPE status —
  is_running was False from the first poll of every recipe.
- get_recipe_progress preserves the last completed run's summary —
  natural completion cleared _run_id, so finished recipes reported
  progress_pct 0.0 and the stress test scored 0% completion.
- 72h test: per-recipe timeout now counts ramp AND dwell durations
  (dwell-only meant ramp-dominated recipes always "timed out") with a
  300-sim-second cool-to-ambient floor; poll tightened (0.5s real was
  500 simulated seconds).

HSMS transport (the Phase 4.4 equipment_manager skip):
- Reader-task EOF and close() now push a None sentinel through the
  data queue; recv_data_message wakes deterministically and raises
  HsmsConnectionError instead of hanging until cancelled. Queued
  messages still drain first; the sentinel re-arms for later getters.
- test_equipment_handler_exits_when_connection_closes un-skipped:
  5/5 consecutive passes.

ci.yml: corrected the stale Phase 4.1 comment claiming physics files
were excluded (no exclusion mechanism ever existed; all 441 run green).

Proof: soak suite 6/6 twice consecutively (was 1 pass, 4 xfail,
1 xpass); RTP 12h holds 1000C with 1.5C pyro std, 0.04C mean control
error; recipe completion 3/3; pc unit+integration 460 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@alovladi007
alovladi007 merged commit e2efdc6 into main Aug 3, 2026
18 checks passed
@alovladi007
alovladi007 deleted the fix/phase-4.4-virtual-clock branch August 3, 2026 20:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant