ACTIVE SURROGATE REVIEW
Source root: full_code_review/source. All line references below refer to the supplied original files.
Scope: active Module/SurrogateModel.h:35–598, active GA/Selector call sites. Later commented variants were excluded. Source files were not edited. Confidence is high for code behavior; no Jetson hardware run or predictive-accuracy validation was performed.

ARCHITECTURE AND ACTUAL LEARNING
This is a workload-conditioned online empirical surrogate coupled to evolutionary selection, not a separate RL learner. Each workload owns a map of configuration buckets containing four exponential moving averages plus shared success/stall counters. Predictions use exact quantized bucket -> inverse-distance k-nearest-neighbor interpolation -> hand-specified physics prior. GA uses these predictions for all candidates, adds a visit-count exploration bonus to scalar fitness, then executes one selected genome. The only RL replay routine counts/logs Rank-0 members and ignores the snapshot (GeneticAlgorithm_05.h:1808–1817); absence of independent RL is consistent with the author's stated architecture and is not itself a defect.

The prior is warm-start scaffolding, not fitted learning: fr=clamp((freq−102000)/(1479000−102000)); power=1.5+2*fr*(1+.15*(clamped_concurrency−2))+(gpu?1:0); fps=max(1,fps_max*fr); latency=latency_prior_ms; temp=38+6*(power−1.5). It ignores split, models no GPU throughput benefit, and has confidence=.1 (SurrogateModel.h:101–114,570–590). GA passes workload fps_max, latency_prior_ms, split applicability and exploration weight; all other model defaults remain fixed (GA:961–967). No active GA/Selector call invokes seed(). The public seed API directly assigns all values and creates synthetic support count (default3), but it is not the live learning path (Surrogate:372–392).

KEY, FEATURES AND POOLING
Namespace = workloadId. WorkloadMission::workloadIdFor assigns process-local sequential IDs per exact label; IDs recur during the process, not a content hash or guaranteed cross-run ID (WorkloadMission.h:61–73). Model context switching reuses the same ContextStore and changes shared active priors/capability; banks are never cleared (Surrogate:145–178; GA:446–501).
Within a workload the key is fb*1000 + gpu*100 + split_bucket*10 + clamped_concurrency:
  frequency: nearest of [102000,403200,921600,1132800,1479000] kHz, lower index wins ties;
  GPU: requested bool;
  split: round(clamp(split)*4), five bins; binary workloads canonicalize split to GPU?1:0;
  concurrency: clamp to integer1..4.
Refs Surrogate:499–560. Maximum representable keys per bank:40 for binary split,200 for continuous split,20 for CPU-only binary use. Different frequencies/splits within a bin deliberately pool into EXACT_BUCKET. Predictions report distance0 for the whole bin, not equality to an exact measured request. For binary workloads, GPU and split are duplicate feature axes, so a GPU change adds squared distance2. KNN features are normalized raw query frequency, gpu, effective split, (concurrency−1)/3; stored features are decoded bucket-center values. Metric is equal-weight Euclidean distance, with no learned feature weighting. No mode, target FPS, power budget, affinity, governor, GPU frequency, measured temperatures/utilization, queue state, input resolution/content, workload epoch, time, or applied/readback identity is in the key. Some genes influence key indirectly through configFromGenome. Consequence: pooling is over a coarse requested-control representation, not all physically influential state.

UPDATE AND DECISION ORDER
Selector reads snapshot (including updating power history) before freshness/provenance gates (Selector:711,747–815). Accepted snapshots call evolve(snapshot) with default creditPreviousAction=true and previousActionStalled=false (847; GA:513–515). GA stable-data gate checks valid/FPS and optional power (GA:524–527,1845–1857). Then AWM updates, previous genome receives one observation, every candidate is predicted/scored, NSGA ranks, candidate selected/applied, evidence emitted, population reproduced, generation incremented (GA:538–638,690–727,1085–1101). Thus the live model learns previous action evidence before computing current predictions; selected-action CSV current measured fields describe preceding evidence, while prediction/action fields describe next action.

observe validates each target independently: FPS finite>=0, other targets finite>0; if ANY target valid the shared bucket count increments. First accepted observation initializes every channel from prior and blends valid channels with alpha=.60; later valid channels use alpha=.30. FPS observations clamp at1.10*active fps_max. Invalid channels remain prior/previous EMA. There is no per-channel count, validity history, variance, or timestamp (Surrogate:203–239,464–478). A count is an admitted snapshot-call count, not per-frame support or number of independent meter observations.

PREDICTIONS, CONFIDENCE, GATES AND FALLBACK
Exact measured bucket returns EMAs, from_data=true, support_count=n, neighbor_count1, distance0. Confidence=[n/(n+1)]*[n/(n+stalls)] (Surrogate:249–271). This is explicitly a support heuristic, not calibrated correctness probability (49–50).
Exact stall-only bucket returns physics prior plus its own stall metadata, bypassing otherwise available neighboring measured buckets (273–279). KNN scans all measured buckets in active workload, k=min(3,num_buckets), weights1/(.001+distance), without sample-count weighting or maximum distance. Its support_count sums success counts of neighbors, confidence=.6/(1+4*nearest_distance), regardless support or neighbor residuals (283–341). There is no uncertainty interval, validation error estimate, out-of-distribution rejection or minimum-similarity fallback. Prior is used when no measured neighbor exists (345–346). A distant neighbor still produces from_data=true.
GA applies FPS-only reality gates: if !from_data or support<3, FPS <=max(1,.5*best_measured_fps), or <=4 during cold start; all predictions also capped at1.2*best_measured_fps or8 when none measured (GA:85–95,1140–1154). These caps are not confidence gates: confidence does not participate. Power/temperature/latency are not pessimised. Active Selector does not parse JSON overrides for the three reality-gate defaults (the only matching parse lines3638–3640 are commented); it does parse enable/explore/fps_max/latency_prior (150–176).
Exploration bonus=.15/sqrt(1+successes+stalls), workload/exact-bucket-local; it is a visit-count bonus, not classical UCB using log(total visits) or statistical uncertainty (Surrogate:349–359). Applied after scalar fitness and age decay, together with exact bucket stall penalty .5*stalls/(successes+stalls) (GA:1169–1172,1245–1249). KNN's interpolated stall_penalty field is not used for fitness: GA explicitly queries exact stallPenalty. Hard feasibility requires exact attempts>=3 and timeout ratio>.5 (GA:1174–1185). Thermal/performance feasibility uses current real snapshot independently; see evolution review.

RETENTION AND RECALL
All buckets and counts remain for the life of SurrogateModel; no age eviction, time decay, capacity eviction, change-point invalidation, or cross-workload pooling. Repeated visits update EMA but lifetime counts never forget old support/stalls (Surrogate:237–239,362–369,473–486). No runtime persistence loader; exportCSV serializes all bank summaries, not raw samples or sufficient provenance (439–460). Banks are bounded by quantization per workload, while number of workload IDs can grow without bound. Workload switch restores per-workload best measured FPS and drops previous action credit; it preserves generation/population/RNG/mutation/AWM (GA:446–501). This genuinely supports recurrence recall. It does not demonstrate that retained evidence is still valid after input/environment changes. A supplied duplicate workloadId with another label only logs error and retains original label; it still uses the same bank and updates priors before the collision check (Surrogate:160–177). Normal WorkloadMission registry avoids collisions, but initial Selector JSON workload_id override can violate that contract (Selector:163–168). Treat as defensive robustness issue, not proven normal mission behavior.

CONSEQUENTIAL FINDINGS
S1. HIGH: Training key is the requested genome, even when execution differs. GA stores lastAppliedGenome before scheduler call (2412–2428), later reconstructs key from it (1085–1097), and never uses readback for admission/rekeying. Static nominal mapping assumes BALANCED concurrency2 and LOW concurrency1 when budget<3.5, with LOW frequency floor403200 (1014–1051). Actual Scheduler LOW always uses2 cores and floor460800 (Scheduler:811–830); BALANCED changes cores2..4, lowers cap using target/FPS, thermal reductions and deadband (999–1090); ThermalGovernor can force GPU false/split0 or force LOW_POWER (528–555). For example LOW budget3 produces actual2-core evidence entered into1-core bucket; BALANCED with an FPS deficit may operate3/4 cores but trains2. Thermal-forced CPU evidence can train a requested GPU bucket. Readback is exported but is not a learning gate (GA:2651–2660,2779 onward). This is a confirmed code-path mismatch; magnitude depends on run. Fix by freezing action provenance with actual applied/verified configuration and gating/rekeying evidence, while predicting through the same scheduler mapping or modelling request-conditioned outcomes explicitly.

S2. HIGH: Watchdog recovery neither resets attribution nor supplies timeout evidence. Active Selector watchdog recoverFast(694) and invalid-snapshot emergency recovery(726) do not call notifyExternalOverride (GA:433). Next accepted normal evolve defaults to crediting the pre-recovery genome, so recovery outcome can strengthen the stalled request. Selector never passes previousActionStalled=true (only active evolve call847), making observeStarvation and hard timeout feasibility dormant through this integration. Stale rejection is useful (754), but freshness means only a new finalized frame; action epoch and a settled measurement window are not checked. Workload epoch gate771–815 is a separate protection and is not action provenance. This is established from active paths, without relying on commented older timeout code.

S3. HIGH: Unsupported targets masquerade as exact, sufficiently supported data. Three FPS-only calls give power/latency/temp still at physics-prior values, but all channels share EXACT_BUCKET/from_data=true/support3/confidence.75 and pass GA support gating. Even 100 FPS-only calls can make all-target confidence>.99. Because power is optional and invalid/absent power returns0, this is reachable with normal configuration. The same single support status/count is copied to every collector target (Selector:868–871). Fix per-target values/counts/provenance/confidence and fallback/gating; do not treat any-target success as evidence for all targets. Verified by compiled actual-header test below.

S4. HIGH: Power target is mixed/stale history across actions and workloads. getLatestSnapshot accepts positive physical power into five-entry history, returns the average, never expires/rejects stale cached history, and runs before frame freshness gate (Selector:711,1075–1105). No action/workload boundary clears history. Repeated stale polls can insert the same raw sample again, even though later stale-snapshot rejection prevents another model update. After transition, hasLastApplied=false prevents the first new-workload observation, but the second may still contain up to3 old-workload readings. Concrete arithmetic: five old2W readings then two new8W readings yields4.4W trained as a new-workload outcome. A sensor rejection after history exists continues supplying positive old average as valid training power. Bank partitioning cannot correct contaminated labels. Need action/epoch/window-aligned fresh meter evidence or explicitly defined time-aware measurement filter.

S5. MEDIUM: KNN's 'nearby' and support gates provide no locality protection. An opposite-end config at distance2 can receive KNN from one bucket, support3, confidence.0667 (<prior .1), yet pass GA lowSupport=false. Pooling three weak neighbors also sums counts to pass. No confidence/distance threshold causes prior fallback; physics outputs for distant control settings can become copied data of another setting. Confidence remains informational. This is confirmed by test; predictive harm requires empirical validation. A support threshold should be target-aware and combined with locality/residual-validation policy if admissible counterfactuals are required.

S6. MEDIUM/CLAIM LIMIT: Latency target is E2E, not processing latency. Selector copies raw.algorithmStats.inferenceTimeMs to avg_inference_ms (1058–1059), but copies raw.endToEndLatencyMs to avg_latency_ms (1125–1126), which is what GA trains (1095–1097). The prior/config comments say processing-latency prior and L1 separates latency from FPS, but actual channel is pipeline E2E. Collector correctly excludes latency from scoring against processing target (Selector:838,869). Specify target explicitly; the supplied path does not establish processing-latency prediction accuracy.

OTHER ATTRIBUTION LIMITS
Temperature is one CPU reading, not independent CPU/GPU temperature outputs; GA intentionally avoids mixing previous GPU temperature into candidate temperature objectives (GA:1304–1313). No thermal initial-state/history features mean historical temperatures pool across warm/cold states. KNN has no counts-weighted fit and no residuals. maxMeasuredFps is workload-local but lifetime maximum with no expiry (GA:1098–1100); raw measured FPS max can differ from clipped observation envelope. Phase recurrence and old counts support 'retained per-workload knowledge', not evidence of contextual generalization, causality, stability or predictive accuracy. CSV has model bank summaries and selection provenance, but no raw training sample ledger/per-target validity to reconstruct EMAs exactly. Collector's assigned previous-action window is explicitly not verified meter/SoC membership (Selector:832–834), so action-offset joining alone does not close these gaps.

FOCUSED VERIFICATION
Compiled unchanged supplied SurrogateModel.h using g++ -std=c++14 -O2 -Wall -Wextra -pedantic and test-only no-op spdlog::warn/error because system spdlog is absent. Test does not substitute model logic, build the full pipeline, or run hardware.
Artifacts: analysis/surrogate_focused_test.cpp; analysis/surrogate_test_stubs/spdlog/spdlog.h; analysis/surrogate_focused_test_output.txt.
PASS: three FPS-only updates => exact support3/confidence.75; unmeasured power5.1W/latency10ms/temp59.6C remain prior; GA lowSupport false.
PASS: A->B->A isolates initially cold B and restores exactly A's3 observations; overall4 observations.
PASS: distant KNN distance2/support3/confidence.0666667 still from_data and passes support gate.
PASS: 200000kHz query returns EXACT_BUCKET trained at102000kHz; binary split canonicalization pools0.73 with CPU0.

Recommended review priority: resolve S1/S2/S3/S4 before relying on model-accuracy, timeout-feasibility or recurrence-benefit comparisons; state S5/S6 and context/retention limits in evaluation. Existing architecture is coherent as workload-conditioned EMA memory + KNN + evolutionary search, but current admission/provenance semantics are weaker than its names imply.
