← Commit history
README.md+1−1
@@ -18,7 +18,7 @@ The [current board model review](docs/board-model-review.md) includes the export - D1 now uses [SBR10U45SP5-13](https://wiki.adom.inc/adom/sbr10u45sp5-13), with published symbol, footprint and drawing-derived nominal STEP/GLB assets. Its local thermal study excludes Q1 and is not complete assembly acceptance. - The fan has a [component page with GLB motion states](https://wiki.adom.inc/adom/mf40200v1-1000u-g99). Its preview is simulated; shared viewer integration remains proposed. - The [thermal budget](docs/thermal-budget.md) now matches the 55 °C firmware trip ceiling. The earlier 25 W assumption is retained as an unqualified future option; R0 targets 5 W and still requires cooling validation.-- There are 90 unique raw takes, 35 reviewed excerpts and 31 storyboard clips. Failed/static captures remain identified in the shot log; the final narrated 4–5 minute film is unfinished.+- There are 90 unique raw takes, 36 reviewed excerpts and 32 storyboard clips. Failed/static captures remain identified in the shot log; the final narrated 4–5 minute film is unfinished.  Read the [engineering status](docs/status.md), [placement review](docs/placement-review.md), [library review](docs/library-review.md), [cost breakdown](docs/cost/README.md), [firmware/control-panel contract](docs/firmware-contract.md), and [raw clip log](videos/shotlog.json). The [AI Flow report](docs/runs/board-codex-20261007-1749/README.md) records the run. 
design/fan-adapter-review.jsonadded+14
@@ -0,0 +1,14 @@+{+  "status": "host-adapter-tests-pass",+  "hardwareTimingQualified": false,+  "firmwareChanged": false,+  "inputs": {+    "firmware/stm32/fan_input.c": "d4ebe5572dbbcd1a3ea84c4e31442732a7237e94d554ec8acdc07142486e92f8",+    "firmware/fan_tach.c": "844f00c1f77e39529bd8f667d543ecee187ff4fe91108aedb7a2c36eb22846fa",+    "tests/test_fan_input.c": "061f80a01f00b635bd574057c9b045a0f7427368b8edb71a967f4b6e5db72031",+    "tests/fan_hal_stub/stm32g0xx_hal.h": "b0e2892c065f28e761b8effb41e295fbddab71ccb2116ab28dde86053701952c",+    "tools/check_firmware.sh": "21cfce018ddbd808349f25413bb3921399bed9f2154140fde840b7b3c2cfe19d"+  },+  "log": "design/fan-adapter-test.log",+  "logSha256": "6278abe04f71b5c0c14e8efae39369277001ac8744311c419e472eb181b33c99"+}
design/fan-adapter-test.logadded+17
@@ -0,0 +1,17 @@+ADC adapter fake-HAL: channel isolation, every-operation failure, saturation and age/wrap passed.+STM32 adapter fake-HAL: pins, endian/address encoding, zero-only DAC, age and sticky faults passed.+Fan adapter fake-HAL: clock refusal, pin/IRQ setup, edge qualification, dual wrap, IRQ-mask restoration, stale edge and delayed poll passed; no hardware timing claim.+load_core: safety policy tests passed (host C build; no MCU/HAL validation)+fan_tach: qualification, RPM, stale input, noise, slow fan, timer wrap and stale-history expiry passed+fan shutdown: 240 synthetic scheduler cases passed; observation <=15ms + poll interval; no hardware timing claim+load_protocol: host safety/framing tests passed; no MCU or USB validation+ADC nominal conversion: divider, ratiometric NTC, invalid reference and saturation tests passed.+Measurement cache: conversion age, WAIT expiry, fault latch and clock wrap passed.+Instrument register, readback, signed conversion and transaction-failure tests passed.+.........................+----------------------------------------------------------------------+Ran 25 tests in 0.048s++OK+OK: external command completed; its running time is in this session+Hint: Use exec for build, browser automation and other work outside AI Flow. Do not start an idle heartbeat; only actual work counts.
design/sensor-candidate.json+78−1
@@ -1 +1,78 @@-{"candidate":"NTCLE428E3103H400A","status":"candidate-not-adopted","source":"https://www.vishay.com/docs/29186/ntcle428.pdf","table":5,"columns":["temperatureC","nominalOhms","minOhms","maxOhms"],"rows":[[0,32624,31440,33809],[25,10000,9700,10300],[40,5323.9,5146.6,5501.1],[50,3598.7,3471.6,3725.8],[55,2982.3,2874,3090.5],[60,2483.8,2391.3,2576.3],[65,2078.7,1999.4,2157.9],[85,1066.1,1021.8,1110.4]],"bodyMaxDiameterMm":3,"bodyMaxLengthMm":10,"leadLengthMm":{"nominal":40,"tolerance":5},"wireGaugeAwg":30,"wireNominalODMm":0.85,"dielectricWithstandingVrms":500,"temperatureRangeC":[-40,105],"minimumWireBendFromBodyMm":4,"minimumInsulatedWireBendRadii":5}+{+  "candidate": "NTCLE428E3103H301A",+  "status": "candidate-not-adopted",+  "source": "https://www.vishay.com/docs/29186/ntcle428.pdf",+  "table": 5,+  "columns": [+    "temperatureC",+    "nominalOhms",+    "minOhms",+    "maxOhms"+  ],+  "rows": [+    [+      0,+      32624,+      31440,+      33809+    ],+    [+      25,+      10000,+      9700,+      10300+    ],+    [+      40,+      5323.9,+      5146.6,+      5501.1+    ],+    [+      50,+      3598.7,+      3471.6,+      3725.8+    ],+    [+      55,+      2982.3,+      2874,+      3090.5+    ],+    [+      60,+      2483.8,+      2391.3,+      2576.3+    ],+    [+      65,+      2078.7,+      1999.4,+      2157.9+    ],+    [+      85,+      1066.1,+      1021.8,+      1110.4+    ]+  ],+  "bodyMaxDiameterMm": 3,+  "bodyMaxLengthMm": 10,+  "leadLengthMm": {+    "nominal": 300,+    "tolerance": 5+  },+  "wireGaugeAwg": 30,+  "wireNominalODMm": 0.85,+  "dielectricWithstandingVrms": 500,+  "temperatureRangeC": [+    -40,+    105+  ],+  "minimumWireBendFromBodyMm": 4,+  "minimumInsulatedWireBendRadii": 5,+  "variantNote": "Same manufacturer Table 5 resistance curve as the historical H400A screen; selected long-lead candidate is H301A."+}
docs/build-clips.md+4
@@ -209,3 +209,7 @@ The inventory now contains **89 raw takes and 33 reviewed excerpts**. Raw takes ## Insulating thermal stack  [Watch the 4.5-second 2× excerpt](clips/aln-stack-review.mp4). Actual insertion of the nominal AlN pad and PEEK fastener, with the sink hidden. Grease gaps are assumed; preload and cooling remain unqualified. Take 91 was decoded and visually reviewed. Current inventory: **91 raw takes, 35 reviewed excerpts and 31 storyboard candidates**. Human scene approval and final assembly remain pending.++## Native power-net walkthrough++[Eleven-second review, 3×](clips/power-net-review.mp4) · [Poster](clips/power-net-review.jpg). All six loaded nets selected and framed on unchanged v85. Review footage, not route creation or thermal acceptance. Take 92. Current inventory: **92 raw takes, 36 reviewed excerpts and 32 storyboard candidates**.
docs/clips/power-net-review.jpgadded
⋯ 1 unchanged line ⋯
docs/clips/power-net-review.mp4added
⋯ 1 unchanged line ⋯
docs/completion-plan.md+2−2
@@ -17,8 +17,8 @@ Continue the custom electronic load through AIFlow, firmware/control-panel and m 2. Establish installed airflow and fault operation. Fan RPM does not prove airflow; a blocked fan may keep spinning. Package-cooling sensitivity predicts approximately 75.6 C still / 51.1 C moving under assumed sink values. These are not measured or accepted results. Preserve the full-power still-air failure and solve the actual cooling/fault strategy. 3. After supported physical/spec changes, rerun exact-input current and thermal acceptance. Continue fields, net tour, silkscreen, native 3D, finish and export in enforced order. Review-only manufacturing exports already exist; do not present them as released. 4. Complete firmware/calibration and molecule integration. Control panel 0.0.4 drives the digital rotor only from fresh valid hardware RPM; stale/disconnected means unknown/paused. Host tests pass; output remains locked and hardware unflashed. [Fan shutdown review](fan-shutdown-review.md) adds 240 synthetic scheduler/clock-wrap integration cases, all passing. Physical timing, sensor calibration and load accuracy remain unverified.-5. Complete procurement and component provenance. [Cost review](cost/README.md) lists $70.88 known proposed subtotal with 63 board references unpriced and substantial assembly/process exclusions. Candidate hardware is not an approved BOM.-6. Continue significant-action captures. Inventory is 91 raw takes, 35 reviewed excerpts and 31 storyboard candidates. Three scenes have draft narration in `videos/narrated-review`; storyboard is `videos/build-storyboard.json`, port 8798. Obtain per-clip feedback before final assembly as required by aiflow-process-video. No final film exists.+5. Complete procurement and component provenance. [Cost review](cost/README.md) lists $77.28 in indicative listings, with bulk-tier, internal inventory and unavailable-part exclusions and substantial assembly/process exclusions. Candidate hardware is not an approved BOM.+6. Continue significant-action captures. Inventory is 92 raw takes, 36 reviewed excerpts and 32 storyboard candidates. Three scenes have draft narration in `videos/narrated-review`; storyboard is `videos/build-storyboard.json`, port 8798. Obtain per-clip feedback before final assembly as required by aiflow-process-video. No final film exists.  ## Tool and delivery boundaries 
docs/fan-feedback.md+3−1
@@ -4,7 +4,7 @@ Selected candidate: Sunon MF40200V1-1000U-G99, 5 V, nominal 7000 RPM ±15%, thre  The fan runs whenever auxiliary power is present. Keep the load disabled during spin-up. The portable policy now refuses ARM unless qualified RPM is valid and within a provisional 5000–10000 RPM window; it latches F_FAN and clears the DAC/enable when speed leaves that window, becomes invalid/nonfinite, or no tach edge arrives for 250 ms. Returning fan motion never automatically rearms the load. These limits are conservative bring-up settings, not a validated airflow rating. -The new portable fan_tach module calculates RPM = 30,000,000 / period_us from rising edges, requires eight consecutive periods in the 3000–6000 µs window, resets qualification on out-of-window timing, handles 32-bit timer wrap and invalidates readings 15 ms after the last edge. The output-locked STM32 bring-up adapter now connects PA7 rising-edge EXTI to a 32-bit 1 MHz TIM2 counter and atomically snapshots this ISR-owned state. It expires stale history and requalifies after a polling gap over 15 ms, preventing stale RPM from reappearing after a full timer wrap. This integration compiles but has not run on physical hardware. A tach wire stuck high or low, unplugged fan, stalled rotor and implausible pulse frequency must all fault. The firmware HAL and physical timing tests remain unfinished. The dashboard carries measured RPM; disconnected readings remain empty.+The new portable fan_tach module calculates RPM = 30,000,000 / period_us from rising edges, requires eight consecutive periods in the 3000–6000 µs window, resets qualification on out-of-window timing, handles 32-bit timer wrap and invalidates readings 15 ms after the last edge. The output-locked STM32 bring-up adapter now connects PA7 rising-edge EXTI to a 32-bit 1 MHz TIM2 counter and atomically snapshots this ISR-owned state. It expires stale history and requalifies after a polling gap over 15 ms, preventing stale RPM from reappearing after a full timer wrap. This integration compiles but has not run on physical hardware. A tach wire stuck high or low, unplugged fan, stalled rotor and implausible pulse frequency must all fault. The actual fan adapter now passes fake-HAL tests for clock refusal, pin/IRQ setup, edge qualification, both timer wraps, interrupt-mask restoration, stale input and delayed acquisition. These are host tests; physical interrupt and shutdown timing remain unverified. The dashboard carries measured RPM; disconnected readings remain empty.  Host C tests cover slow, zero, implausibly fast, nonfinite and unqualified RPM, missing edges and latched shutdown. Physical validation must additionally test startup, locked rotor, supply variation, blocked airflow and tach disconnection at load. RPM alone does not prove airflow: case-temperature shutdown remains independent, and the heatsink/duct must pass thermal testing before raising the 5 W ceiling. @@ -13,3 +13,5 @@ The reusable [fan component page](https://wiki.adom.inc/adom/mf40200v1-1000u-g99 On 9 October, fan component 0.2.3, Wiki Skill Pack 0.8.42 and Component Widgets 1.1.17 were released with gentle hero-presentation guidance and explicit connector assets. The baked hero animation works in the published canonical viewer without a new state runtime. The optional Adom harness is M20-1060300 plus three M20-1180046 contacts, mating with J9 M20-9990346. Native board readback confirms J9 pins 1/2/3 are 5V_AUX/GND/FAN_TACH, matching the documented red/black/yellow assembly map. The factory fan is bare-ended; orientation, strip preparation, crimp and continuity checks are still required.  Interactive shared motion-widget integration remains proposed in [Component Widgets PR 1](https://wiki.adom.inc/adom/component-widgets/prs/1), [wiki motion-authoring PR 8](https://wiki.adom.inc/adom/adom-wiki-skillpack/prs/8), and [Probing issue 1](https://wiki.adom.inc/adom/adom-aiflow-probing/issues/1). These remained open when checked on 9 October. AIFlow PR 32 is closed, not merged; do not cite it as a pending runtime delivery. Published hero playback does not establish a released probing simulator capability.++The [temperature trip budget](sensor-trip-budget.md) separately shows why nominal sensor readings need an installed measurement margin. Software tests do not establish airflow or actual-case temperature acceptance.
docs/sensor-trip-budget.mdadded+19
@@ -0,0 +1,19 @@+# Temperature trip and measurement margin++The long-lead candidate is NTCLE428E3103H301A. The earlier curve-screen input still named its short-lead sibling H400A; the input now identifies the actual 300 mm candidate. Both use manufacturer Table 5. No board, firmware or BOM substitution was made.++A reproducible static sensitivity check combines that table's resistance tolerance, the existing nominal firmware conversion, a 10 kΩ ±1% pull-up and ideal 12-bit ADC rounding:++| Indicated cutoff | Earliest sensor temperature | Latest sensor temperature |+|---|---:|---:|+| 55 C, current policy | 53.69 C | 56.19 C |+| 54 C, sensitivity only | 52.72 C | 55.17 C |+| 53 C, sensitivity only | 51.73 C | 54.17 C |++These are log-resistance interpolations, not guaranteed extrema between tabulated points. They exclude ADC offset/gain/INL/noise, resistor drift, self-heating, attachment gradients and thermal lag. Even the 53 C illustration is not an approved threshold or complete error budget. The existing 55 C actual-case limit is unchanged.++Vishay lists an approximately 2.5-second response **in oil**, permits taped/glued mounting, and excludes hard potting. That response is not the installed case-sensor response or a justified RC time constant. [Manufacturer sheet](https://www.vishay.com/docs/29186/ntcle428.pdf).++Before enabling load, qualify the exact sensor, attachment and acquisition chain against a reference case-temperature measurement across the intended range. Establish the maximum under-reading including transient lag, then derive an indicated cutoff that preserves the actual-case ceiling. Check the independent comparator separately; its nominal threshold is not a calibrated substitute for the software measurement. The bring-up image remains output locked.++Reproduce with `python3 tools/sensor_trip_budget.py`. [Inputs](../design/sensor-candidate.json) · [Results](../mechanical/sensor-trip-budget.json).
mechanical/sensor-candidate-screen.json+2−2
@@ -1,7 +1,7 @@ {   "status": "candidate-screen-not-adopted",-  "candidate": "NTCLE428E3103H400A",-  "inputSha256": "75ee0242ca0188176e46e01addf9251435edc5accd6f144aa011b8fd3a26f975",+  "candidate": "NTCLE428E3103H301A",+  "inputSha256": "ec74f77efe9446a6b4a54ddd3d1e1837ebfdeb26ede5a460a8da358be896b5ae",   "comparison": [     {       "actualC": 0,
mechanical/sensor-trip-budget.jsonadded+37
@@ -0,0 +1,37 @@+{+  "status": "conditional-static-sensitivity-not-qualified",+  "candidate": "NTCLE428E3103H301A",+  "sourceInputSha256": "ec74f77efe9446a6b4a54ddd3d1e1837ebfdeb26ede5a460a8da358be896b5ae",+  "source": "https://www.vishay.com/docs/29186/ntcle428.pdf",+  "curve": "existing NTCLE100 inverse polynomial; new sensor not adopted",+  "pullupTolerancePercent": 1,+  "adcModel": "ideal 12-bit rounding only; no offset, gain, INL, reference or noise error",+  "scenarios": [+    {+      "indicatedTripC": 55,+      "largestTripAdcCode": 942,+      "earliestStaticActualC": 53.69209465665597,+      "latestStaticActualC": 56.18731748129479+    },+    {+      "indicatedTripC": 54,+      "largestTripAdcCode": 969,+      "earliestStaticActualC": 52.71687050913772,+      "latestStaticActualC": 55.17494382993744+    },+    {+      "indicatedTripC": 53,+      "largestTripAdcCode": 997,+      "earliestStaticActualC": 51.725116440137214,+      "latestStaticActualC": 54.16813003623115+    }+  ],+  "responseTimeSourceSeconds": 2.5,+  "responseTimeMedium": "oil; cannot be reused as installed response or an RC time constant",+  "limits": [+    "Resistance tolerances use manufacturer Table 5 with log-resistance interpolation; interpolated extrema are a screen, not guaranteed between-tabulated bounds.",+    "No attachment gradient, thermal lag, self-heating, ADC electrical error or resistor temperature drift included.",+    "No software trip setting, formal case ceiling, BOM or hardware comparator change.",+    "A 55 C indicated cutoff alone does not guarantee a 55 C actual case ceiling."+  ]+}
tests/fan_hal_stub/stm32g0xx_hal.hadded+30
@@ -0,0 +1,30 @@+#ifndef ADOM_FAN_TEST_HAL_H+#define ADOM_FAN_TEST_HAL_H+#include <stdint.h>+typedef struct {uint32_t PSC,ARR,EGR,SR,CNT,CR1;} TestTimer;+typedef struct {uint32_t Pin,Mode,Pull,Speed;} GPIO_InitTypeDef;+extern TestTimer test_timer;+extern uint32_t test_pending,test_mask;+#define TIM2 (&test_timer)+#define GPIOA ((void *)1)+#define GPIO_PIN_7 128u+#define GPIO_MODE_IT_RISING 1u+#define GPIO_NOPULL 0u+#define TIM_EGR_UG 1u+#define TIM_CR1_CEN 1u+#define EXTI4_15_IRQn 7+#define __HAL_RCC_TIM2_CLK_ENABLE() ((void)0)+#define __HAL_RCC_TIM2_FORCE_RESET() ((void)0)+#define __HAL_RCC_TIM2_RELEASE_RESET() ((void)0)+#define __HAL_GPIO_EXTI_CLEAR_RISING_IT(pin) (test_pending &= ~(pin))+#define __HAL_GPIO_EXTI_GET_RISING_IT(pin) (test_pending & (pin))+#define __get_PRIMASK() (test_mask)+#define __disable_irq() (test_mask=1)+#define __set_PRIMASK(value) (test_mask=(value))+uint32_t HAL_GetTick(void);+uint32_t HAL_RCC_GetPCLK1Freq(void);+uint32_t HAL_RCC_GetHCLKFreq(void);+void HAL_GPIO_Init(void *,GPIO_InitTypeDef *);+void HAL_NVIC_SetPriority(int,unsigned,unsigned);+void HAL_NVIC_EnableIRQ(int);+#endif
tests/test_fan_input.cadded+48
@@ -0,0 +1,48 @@+/* Executes the actual STM32 tach adapter against fake registers/interrupts.+ * No physical ISR timing, GPIO electrical behavior or MCU execution claim. */+#include "fan_hal_stub/stm32g0xx_hal.h"+#include <assert.h>+#include <math.h>+#include <stdio.h>+#include "../firmware/stm32/fan_input.c"+TestTimer test_timer;+uint32_t test_pending,test_mask;+static uint32_t ms,pclk=64000000,hclk=64000000;+static unsigned configured;+uint32_t HAL_GetTick(void){return ms;}+uint32_t HAL_RCC_GetPCLK1Freq(void){return pclk;}+uint32_t HAL_RCC_GetHCLKFreq(void){return hclk;}+void HAL_GPIO_Init(void *port,GPIO_InitTypeDef *g){assert(port==GPIOA&&g->Pin==GPIO_PIN_7&&g->Mode==GPIO_MODE_IT_RISING&&g->Pull==GPIO_NOPULL);configured++;}+void HAL_NVIC_SetPriority(int irq,unsigned a,unsigned b){assert(irq==EXTI4_15_IRQn&&a==1&&b==0);}+void HAL_NVIC_EnableIRQ(int irq){assert(irq==EXTI4_15_IRQn);}+static void edge(uint32_t us){test_timer.CNT=us;test_pending|=GPIO_PIN_7;EXTI4_15_IRQHandler();assert(!(test_pending&GPIO_PIN_7));}+static void qualify(uint32_t us){+ float rpm;uint32_t stamp;+ edge(us);+ for(unsigned n=1;n<=8;n++){ms+=4;edge(us+n*4286);bool valid=load_fan_input_read(&rpm,&stamp);assert(valid==(n==8));}+ assert(fabsf(rpm-7000)<1&&stamp==ms);+}+int main(void){+ pclk=32000000;assert(!load_fan_input_init()&&!configured);+ pclk=hclk=64000001;assert(!load_fan_input_init()&&!configured);+ pclk=hclk=500000;assert(!load_fan_input_init()&&!configured);+ pclk=hclk=64000000;ms=UINT32_MAX-16;assert(load_fan_input_init());+ assert(test_timer.PSC==63&&test_timer.ARR==UINT32_MAX&&test_timer.CR1==TIM_CR1_CEN);+ float rpm=-1;uint32_t stamp=0;+ assert(!load_fan_input_read(&rpm,&stamp)&&rpm==0);+ /* Unrelated EXTI flag is neither accepted as tach nor cleared. */+ test_pending=1;EXTI4_15_IRQHandler();assert(test_pending==1&&!tach.seen);test_pending=0;+ qualify(UINT32_MAX-10000); /* microsecond and millisecond wrap */+ for(unsigned mask=0;mask<=1;mask++){test_mask=mask;assert(load_fan_input_read(&rpm,&stamp));assert(test_mask==mask);}+ test_mask=0;+ /* Input goes stale while the foreground continues to poll on time. */+ test_timer.CNT+=15000;ms+=15;assert(load_fan_input_read(&rpm,&stamp));+ test_timer.CNT+=1;assert(!load_fan_input_read(&rpm,&stamp)&&rpm==0);+ qualify(test_timer.CNT+1000);+ /* Recent ISR edges do not excuse an overdue foreground acquisition. */+ ms+=16;edge(test_timer.CNT+4286);+ assert(!load_fan_input_read(&rpm,&stamp)&&!tach.seen&&rpm==0);+ qualify(test_timer.CNT+1000);+ edge(test_timer.CNT+100);assert(!load_fan_input_read(&rpm,&stamp));+ puts("Fan adapter fake-HAL: clock refusal, pin/IRQ setup, edge qualification, dual wrap, IRQ-mask restoration, stale edge and delayed poll passed; no hardware timing claim.");+}
tools/check_firmware.sh+2
@@ -8,6 +8,8 @@ gcc "${cc_args[@]}" -Itests/adc_hal_stub -Ifirmware firmware/adc_conversion.c te "$load_check_dir/adc-adapter" gcc "${cc_args[@]}" -Itests/hal_stub -Ifirmware firmware/instruments.c firmware/measurement_cache.c tests/test_instrument_input.c -lm -o "$load_check_dir/adapter" "$load_check_dir/adapter"+gcc "${cc_args[@]}" -Itests/fan_hal_stub -Ifirmware firmware/fan_tach.c tests/test_fan_input.c -lm -o "$load_check_dir/fan-adapter"+"$load_check_dir/fan-adapter" gcc "${cc_args[@]}" firmware/load_core.c tests/test_load_core.c -lm -o "$load_check_dir/core" "$load_check_dir/core" gcc "${cc_args[@]}" firmware/fan_tach.c tests/test_fan_tach.c -lm -o "$load_check_dir/tach"
tools/sensor_trip_budget.pyadded+22
@@ -0,0 +1,22 @@+#!/usr/bin/env python3+"""Static sensitivity screen; no installed sensor or ADC qualification."""+import json, math, hashlib+from pathlib import Path+from sensor_candidate_screen import old_curve, interp_temp+R=Path(__file__).resolve().parents[1]+p=R/'design/sensor-candidate.json';d=json.loads(p.read_text());rows=d['rows']+assert d['candidate']=='NTCLE428E3103H301A'+assert all(lo<=nom<=hi for _,nom,lo,hi in rows)+assert all(a[1]>b[1] for a,b in zip(rows,rows[1:]))+scenarios=[]+for indicated in [55,54,53]:+ codes=[c for c in range(16,4080) if old_curve(10000*c/(4095-c))>=indicated]+ last_hot=max(codes)+ # ADC round-to-nearest switches at code + 0.5. Pull-up tolerance is isolated.+ ratio=(last_hot+.5)/(4095-last_hot-.5)+ earliest=interp_temp(rows,10100*ratio,2)+ latest=interp_temp(rows,9900*ratio,3)+ scenarios.append({'indicatedTripC':indicated,'largestTripAdcCode':last_hot,'earliestStaticActualC':earliest,'latestStaticActualC':latest})+out={'status':'conditional-static-sensitivity-not-qualified','candidate':d['candidate'],'sourceInputSha256':hashlib.sha256(p.read_bytes()).hexdigest(),'source':d['source'],'curve':'existing NTCLE100 inverse polynomial; new sensor not adopted','pullupTolerancePercent':1,'adcModel':'ideal 12-bit rounding only; no offset, gain, INL, reference or noise error','scenarios':scenarios,'responseTimeSourceSeconds':2.5,'responseTimeMedium':'oil; cannot be reused as installed response or an RC time constant','limits':['Resistance tolerances use manufacturer Table 5 with log-resistance interpolation; interpolated extrema are a screen, not guaranteed between-tabulated bounds.','No attachment gradient, thermal lag, self-heating, ADC electrical error or resistor temperature drift included.','No software trip setting, formal case ceiling, BOM or hardware comparator change.','A 55 C indicated cutoff alone does not guarantee a 55 C actual case ceiling.']}+(R/'mechanical/sensor-trip-budget.json').write_text(json.dumps(out,indent=2)+'\n')+print(json.dumps(out,indent=2))
videos/build-storyboard.json+6
@@ -198,6 +198,12 @@       "title": "Add the insulating thermal interface",       "description": "Actual nominal AlN and PEEK model insertion at 2x. Sink hidden; grease gaps assumed. Mechanical fit does not qualify insulation, preload or cooling.",       "raw_path": "/home/adom/project/adom-custom-electronic-load/docs/clips/aln-stack-review.mp4"+    },+    {+      "id": "power-net-review",+      "title": "Follow the six power paths in KiCad",+      "description": "Native saved-board net selection and framing at 3x. Review, not route creation; thermal acceptance remains open.",+      "raw_path": "/home/adom/project/adom-custom-electronic-load/docs/clips/power-net-review.mp4"     }   ] }
videos/inventory.json+8−2
@@ -1,6 +1,6 @@ {-  "rawTakeCount": 91,-  "reviewedExcerptCount": 35,+  "rawTakeCount": 92,+  "reviewedExcerptCount": 36,   "countingRule": "Unique raw window recording filenames in this project; excludes derivative action/speed exports and reference projects. Raw count includes rejected takes.",   "takes": [     {@@ -548,6 +548,12 @@       "durationSeconds": 9.866667,       "topic": "Add nominal AlN insulator and PEEK fastener stack",       "review": "Full raw and excerpt decode, contact sheet and poster reviewed. 4.5-second 2x excerpt, browser chrome cropped. Sink hidden explicitly. Assumed grease gaps; no preload, insulation or thermal qualification."+    },+    {+      "file": "aiflow/run/window-336160-20261010-194400.mp4",+      "durationSeconds": 41.4,+      "topic": "Native saved-board walkthrough of six power nets",+      "review": "Contact sheet and excerpt poster visually reviewed; excerpt fully decoded. Eleven-second 3x edit. Actual native selections and framing, not routing creation; unchanged v85, thermal gate open."     }   ] }