ACTUATION AND ADAPTIVE-WEIGHT REVIEW
Scope: active source in Module/Scheduler.h, ThermalGovernor.h, AdaptiveWeightManager.h, RuntimeControls.h and ActuationReadback.h; cross-check ConfigManager, GA, EvolutionarySelector, harness, AlgorithmConcrete. Reviewed source unchanged. All line references refer to files under full_code_review/source. No hardware execution performed.

EXECUTIVE FINDINGS
A1 HIGH — The thermal policy is only partly enforced, and the special shutdown override is one-shot.
  ThermalGovernor.h:170–175 declares target_fps_scale, gpu_allowed, allow_inference, frame_skip_ratio, power_budget_reduction. Its CRITICAL and EMERGENCY policies populate skip/no-inference/power reductions at 405–417. Scheduler.h:547–556 consumes only target_fps_scale and gpu_allowed, then dispatches normally at 581–603. RuntimeControls.h:56–98 has no inference-permission or skip-ratio control. Repository search finds no other active use of these ThermalPolicy fields apart from formatting telemetry. FrameSkippingScheduler.h is a separate latency/backlog helper and has no integration with this governor.
  Consequently >65C (class default emergency) does not stop inference or force a CPU cap: MAX_PERFORMANCE still publishes four cores and writes its requested cap at Scheduler.h:788–808. FPS scaling affects only BALANCED's core/frequency heuristic (999–1036); MAX/LOW do not consume target_fps. There is no frame-rate limiter here.
  At >75C default shutdown threshold, ThermalGovernor::shouldShutdown sets shutdown_initiated_ and returns true only once (244–253). Scheduler.h:531–540 forces LOW_POWER only for that call. It preserves the original cpu_max_freq_khz gene, so the first override may still retain 1479000 kHz; next hot tick resumes the original MAX mode. resetAfterCooldown exists (267–270), but Scheduler never calls it. This is application-level thermal behavior; kernel hardware protection is outside this source review.
  Confirmed actual-header test: 70C + MAX1479000 => 4 cores,1479000,GPU off; 80C => first 2 cores then next tick4,1479000. Fix: apply a persistent thermal constraint on every actuation path; explicitly wire inference/skip controls or remove unsupported policy/telemetry claims; define a shutdown latch/cooldown contract.

A2 HIGH — Recovery and invalid-metric paths bypass thermal permission.
  Scheduler.h:465–475 recoverFast unconditionally sets four cores/performance/full CPU range, GPU enabled, split1. It never checks or preserves thermal permission. Active callers include EvolutionarySelector_02.h:684–697 watchdog and 713–726 invalid-snapshot recovery. The latter can happen with no fresh temperature; a prior thermal ban is lost.
  Scheduler.h:516–525 handles invalid metrics BEFORE governor.update. It invents BALANCED/prefer_gpu=true and calls applyBalanced directly; the previous split is not republished. BALANCED's raw75/80C frequency guards are not a substitute for profile-specific GPU permission.
  Confirmed actual-header tests: recoverFast after thermal GPU-off enables it; invalid snapshot carrying80C leaves GPU enabled/split1. Fix: keep the last known thermal permission or conservative stale-temperature envelope when restoring liveness.

A3 MEDIUM/HIGH — Two advertised CPU-ceiling guarantees are not strict ceilings.
  (a) E1b OPP floor/quantization is absent. Scheduler MAX_PERFORMANCE writes min=max=raw clamped gene (794–801). expectedPolicyMaxKHz (183–195) instead predicts upward kernel adjustment when this window contains no OPP; ActuationReadback.h:11–13 explicitly accepts1190400 ->1224000. This helper is a readback expectation, not an actuator transformation. Thus a higher actual OPP can be considered verified against a lower advertised command. There is no E1b/quantization implementation anywhere in the supplied active source. This host test confirms the helper's result; regular files do not emulate Linux cpufreq rounding, so actual kernel rounding is source-described and not hardware-tested.
  (b) BALANCED first takes min(PIDcap,gene cap) at1028–1036, then the <=100000 kHz deadband can replace that smaller ceiling with the PREVIOUS larger target at1085–1089. Confirmed request900000 followed850000 retains900000. This also can suppress a small thermally motivated reduction. Fix: quantize explicit cap downward to supported OPP where strictness is intended; deadband must never retain a value above an explicit new hard ceiling. Distinguish requested, transformed, expected-policy, and measured-frequency values.

A4 MEDIUM — Spread affinity can contradict the online CPU set and silently reduce effective parallelism.
  Sysfs::cpuOnline(cores) keeps prefix CPUs0..cores-1 (Scheduler.h:265–275). chooseCpus(2,Spread) returns{0,2} (346–357), while online2={0,1}. BALANCED can choose2 cores and Spread when0<target-fps<=2 and CPUutil>85 (1003–1018). sched_setaffinity uses the intersection with available CPUs, so a two-worker intent can be restricted to one online CPU. At4 or3 cores these sets overlap correctly.
  setThreadAffinity acts on calling thread only (338–343); Scheduler ignores its return everywhere and caches affinity anyway (1075–1078). AlgorithmConcrete_new.h:494–518 later applies the same mapping to the algorithm thread and also ignores failure. Its CPU workers are newly spawned at1396–1412 and inherit that affinity. RuntimeControls.cpu_affinity_mask remains initialized0xF (74,107) and is not maintained by Scheduler.
  Test confirms the two conflicting sets (without calling the host affinity syscall). Fix: derive affinity from the actual online mask, check failures, and publish effective mask. The parent algorithm reviewer may cover worker behavior in more detail.

A5 MEDIUM — Readback proves a narrow CPU-max condition, while several caches never reconcile observed drift.
  CPU/governor/core/GPU writes return success and cache only accepted requests (Scheduler.h:700–742), retrying failed writes on subsequent applications. setMinMaxOrdered enforces write ordering and rejects inverted windows (198–216). CPU max mismatch invalidates the CPU window and core-count mismatch invalidates core count (749–770). This is useful E1 work.
  However cpu_cap_verified means actuation_possible && cpu_write_ok && cpu0.max==expected only (755–780). It neither verifies CPU minimum, governor, other policies, nor GPU. ActuationReadback.h:8's 'every write this period accepted' is too broad: cpu_write_ok_ covers CPU-window calls only, and is true on cache hit. cpu0 scaling_min and GPU readbacks are published but not reconciled; governor is not read at publish time. The broad Scheduler comment at372–374 about invalidating caches on readback disagreement is not true for all caches. GPU drift can persist indefinitely even though GPU readback visibly disagrees; external CPU min/governor drift can coexist with cpu_cap_verified=true. Per-core verification may be less important on a shared Tegra cpufreq policy, but the source claims all-online-core writes and only validates cpu0.
  Confirmed actual-header fake-tree test: externally change CPU0min to408000, governor to powersave, GPUmax to76800000; repeat the same action => all remain changed, cpu_cap_verified=true. Fix: name verification according to its exact contract and periodically reconcile all state whose cache is used to suppress writes. Report governor/core/GPU actuation success independently.

A6 MEDIUM — Requested GA config is not executed config; model evidence must represent transformations.
  Coordinate with evolution/surrogate reviews: GA configFromGenome(lastAppliedGenome_) at GeneticAlgorithm_05.h:1085–1101 models requested state; lastAppliedGenome is set before scheduler.apply at2412–2428. Scheduler independently changes CPU cap, concurrency, GPU permission and split as above. LOW_POWER always2 cores/Pack, ignores power_budget (812–830); MAX always4 cores/Spread; BAL changes concurrency dynamically. The model cannot treat an unmodified requested feature vector as a measured hardware state without accounting for these overrides. Watchdog external overrides compound attribution. Parent evolution/surrogate findings own the integration recommendation.

A7 LOW/MEDIUM — GPU/split/control publication can be inconsistent or delayed.
  Normal Scheduler publishes split before mode handler publishes enable_gpu/concurrency, using independent atomics (567–573 vs788–837/1007–1026). Explicit split and prefer_gpu are accepted independently; no consistency normalization here. BALANCED with prefer_gpu missing may change GPU enable heuristically after split's fallback was computed, so split may remain1 while enable_gpu becomesfalse. The active GA may sanitize its own genome, but the public Scheduler contract does not enforce consistency for other callers. Invalid-metrics branch never updates split. NaN split bypasses both range comparisons.
  AlgorithmConcrete_new.h:494–505 samples enable_gpu/concurrency/affinity every10frames; CPU parallelFor loads concurrency per call1370–1377; heterogeneous blur loads split per frame913–918. These fields are therefore not applied atomically at one algorithm boundary. GPU denial may take up to the next adaptation block for ordinary GPU workloads, while heterogeneous split can change immediately. Affinity/control application failures are not surfaced in readback. Action generation may be observed before all these controls are sampled; see integration reviewer for timing consequences.

PRECISE NORMAL PIPELINE (active ERL)
  1. EvolutionarySelector gates useful/fresh/settled snapshots and calls GA evolve(snapshot). Watchdog recovery is an alternate direct Scheduler path.
  2. GA calls authoritative weightManager.update with valid snapshot, global generation, fixed performance target (GeneticAlgorithm_05.h:539–568). AWM operates on observed raw metrics, not counterfactual predictions.
  3. GA uses persistent population and workload-conditioned surrogate; scalar fitness gets AWM weights if enabled (2149–2158), otherwise configured static vector. Pareto and exploration arbitrate a requested genome/action (covered by parent evolution review).
  4. Scheduler.apply invokes applyDispatch then ALWAYS publishReadback (508–510), including early-return branches.
  5. initializePlatformEnvelope pins nvpmodel0 and restores jetson_clocks once; reports failure but marks initialized regardless (444–458). applyPowerProfileOnce is now an unused no-op (1097–1103), so mode changes do not shell out. reset turns jetson_clocks on then rearms envelope for next application (487–503).
  6. Invalid metrics go straight to safeAction/BALANCED, bypassing governor (516–525).
  7. Valid metrics -> ThermalGovernor.update(max(rawCPU,rawGPU)+offset) immediate strict-threshold stage (198–213,354–359), no hysteresis; shouldShutdown one-shot (244–253).
  8. Otherwise copy action; scale explicit target_fps, revoke GPU/split if required (543–556). Publish normalized split (567–573). Dispatch mode (581–603).
  9. Mode computes concurrency/affinity/clock window and applies accepted-write caches. Core hotplug first; governor; CPU min/max; GPU min/max. BAL has heuristic GPU/PID-like rules and separate hardcoded raw75/80C guards, then deadband. It is threshold feedback, not a PID controller with integral/derivative state.
  10. Publish cpu0 min/max/current, expected max, online mask, GPU max/current, CPU-max verification and failure counts/timestamp (749–785). 'enable_gpu' grants algorithm permission; it does not physically power-gate GPU. GPU off means software flagfalse and devfreq pinned/min-limited to76.8MHz.
  11. Algorithm consumes controls at different cadences, runs work; future telemetry feeds the next generation. Commanded cap is intent even if writes fail.

AWM SEMANTICS AND DEFAULTS
  Active AWM implementation ends at505; lines508–2782 are commented historical content, not multiple classes/configurations.
  Config default: update interval5 generations, power critical7.5W, CPU/GPUwarn45C, CPU/GPUcrit55C, latency30ms, underperformance0.70*fixed performance target, EMAalpha0.30 (116–126).
  Classifier priority (392–458): CPUcritical then GPUcritical; physically plausible power>7.5W; CPUwarning then GPUwarning; latency>SLA; fps<ratio*target; nominal. All thermal comparisons strict>. PowerSanity rejects physically implausible power, but the public update itself does not check snapshot.valid (GA caller does).
  update only executes at generations divisible by5 (178–182); regime commits after2 successive qualifying detections (217–235), including forced regime. EMA is applied at each sampled tick only (238–239,479–489). If first hot detection is generation0, commit generation5; arbitrary onset may wait nearly10 generations. Debounce is not time-based and not a thermal safety latch.
  Weight order [FPS,power/energy,temp,latency]: nominal[.50,.20,.20,.10]; power[.25,.50,.15,.10]; thermal warn[.35,.15,.40,.10]; critical[.20,.10,.60,.10]; latency[.30,.15,.15,.40]; highperf[.65,.15,.15,.05] (466–475). These are SOFT scalarization preferences. No AWM method grants/revokes hardware permission or writes sysfs. Governor can override selected GPU action afterward.
  Test: hot60C atgen0 retains nominal; gen5 commits critical and current weights[.41,.17,.32,.10], not final profile immediately.

THERMAL PROFILE / EFFECTIVE CONFIG TABLE
  Source default Governor C/W/Crit/Emergency/Shutdown =45/50/55/65/75C; offset0 (ThermalGovernor.h:97–104). Header prose54–59 incorrectly says55/62/70/80.
  Governor original factory =75/85/95/105/108 (106–115); coolerBaseline only applies offset-15 (118–121).
  AWM source defaults warn45/45 crit55/55; original factory warn75/78 crit80/83, power8W, latency45ms (130–138).
  ConfigManager parses ThermalGovernor JSON into governor config (301–308), constructs an AWM config from Scheduler keys (310–320), and passes both objects to the selector (350–353). The selector forwards thermalCfg to Scheduler, but ignores its awmCfg argument (EvolutionarySelector_02.h:42–54). When AWM is enabled, it reconstructs gaCfg.awm_config from its merged Brain JSON (235–275). ConfigManager merges EvolutionarySelector keys over Scheduler keys (327–330), so an EvolutionarySelector section can override both harness brain flags and harness awm_* thresholds. Passing the separately constructed AWM object does not make it authoritative. No supplied base JSON establishes a final actual-run configuration.
  GA/selector adaptive_weights_enabled default false (GA155; Selector209), whereas harness ERL explicitly enables it (SampleTestIntegrationCode_v35.cpp:735–747).
  Harness profiles (317–337):
    INACTIVE_75C: governor75/85/95/105/108; AWMwarn75/78 crit80/83.
    MODERATE_55C: governor55/62/70/80/90; AWMwarn57/57 crit63/63.
    AGGRESSIVE_45C: governor45/50/55/60/75; AWMwarn45/45 crit55/55.
  Harness CLI defaults AGGRESSIVE_45C (2045). Its emergency60 differs from class default65. apply_thermal_profile overwrites governor/AWM temperature fields only and preserves power/SLA/EMA etc (356–396); surrounding comments claiming power3.5W or warning57C are historical, not actual active defaults (738–745).
  temperature_offset applies to governor effective temperature only; AWM and GA use raw snapshot temperature. Harness's separate set_thermal_config modifies static objective weights using offset (1020–1036), but authoritative AWM replaces those weights while enabled (GA2149–2153). Static thermal gate uses raw max temperature and profilewarning (harness998–1005), no offset. Avoid treating labels/telemetry as proof of equivalent effective policy.
  Static harness modes do not instantiate Scheduler/ERL; their GPU thermal gate is separately implemented (981–1010). OS_DEFAULT is exempt. Thus statements about governor's nominal frame skipping do not demonstrate applied skips in either arm.

ACTUATION DETAILS THAT ARE IMPLEMENTED CORRECTLY / LIMITATIONS
  - Missing GPU devfreq is warned but permits CPU actuation; present but unwritable GPU disables entire Scheduler unless override. Constructor requires effective UID0 AND writable CPU0/hotplug/presentGPU nodes, otherwise throws unless HRL_ALLOW_NONROOT=1, which disables hardware actuation (398–432). checkWritable checks only CPU0 cpufreq permissions plus other-core hotplug (317–330), so it is narrower than comments claiming all nodes.
  - Write failures include fopen/fprintf/fclose errors and rate-limited per-path counts; success is not inferred from intent (103–125). Ordered window writes handle min/max conflict (202–216). A partially accepted action is not rolled back; readback helps diagnose CPU max only.
  - Runtime software controls still change in non-actuating mode. actuation_possible false means DVFS/hotplug disabled, not a wholly no-effect simulation; Algorithm still changes CPU/GPU processing/concurrency/affinity.
  - LOW bounded governor selects schedutil/ondemand/performance from available list (239–247). BALANCED unconditionally requests schedutil (1074), so a device without that governor may fail while CPU-max verification remains true.
  - GPU frequency writes clamp the devfreq range, not physical enable/disable; GPU is never device-power-gated here. applyGpuStateOnce nominal200ms cooldown is not a global GPU-write throttle because each mode immediately calls setGpu separately (805,837,1093).
  - EMC helper exists (290–294) but is not called in active per-mode code. The common nvpmodel0 platform envelope supplies the bandwidth policy. There is no active per-gen EMC genome/actuation path in Scheduler.
  - No user/kernel hardware tests were run. Fake regular-file sysfs reproduces C++ branching/cache/runtime-publication behavior, not real kernel write validation, OPP rounding, permissions, frequency residency, thermal physics, or thread affinity behavior.

REPRODUCTION ARTIFACTS
  analysis/actuation_tests/test_actuation.cpp includes unchanged actual production headers. A minimal spdlog stub discards logging only. HRL_SYSFS_TEST maps every sysfs path under analysis/actuation_tests/fake_sysfs. Compile-time system/sched_setaffinity hooks suppress all shell commands and affinity calls. Test asserts the root path marker before seeding. Build:
  g++ -std=c++17 -O0 -I full_code_review/analysis/actuation_tests/stubs -I full_code_review/source/Module full_code_review/analysis/actuation_tests/test_actuation.cpp -o full_code_review/analysis/actuation_tests/test_actuation
  Run:
  full_code_review/analysis/actuation_tests/test_actuation /workspace/scratch/c880e7664794/full_code_review/analysis/actuation_tests/fake_sysfs
  Result: exit0, seven PASS groups; exact output in analysis/actuation_tests/test_output.txt. These are reproductions of current behavior, not passing correctness regressions.

CROSS-REVIEW CONFIGURATION CLARIFICATION
  GAConfig's temperature-objective onset is initialized from the class AWM warning defaults (GeneticAlgorithm_05.h:193–194), but selector reads optional obj_temp_onset fields independently (EvolutionarySelector_02.h:195–196) before configured AWM threshold reparsing (254–262). Harness apply_thermal_profile only sets governor and awm_* thresholds (356–384), not obj_temp_onset. Thus INACTIVE/MODERATE profiles do not automatically align the GA temperature-objective onset with their AWM warn values. GA constructor warns of that divergence (GeneticAlgorithm_05.h:389–396). Source-default equality should not be presented as profile-configured equality.
  Lifecycle reviewer also verified standalone SchedulerModule::step creates a default invalid snapshot because the aggregator fetch remains commented (Modules.h:205–219). That non-ERL path therefore repeatedly takes Scheduler's invalid-metrics governor bypass. The v35 static arms disable Scheduler entirely and use the separate static GPU gate, so distinguish standalone Scheduler from harness BALANCED.
