Files
soothe2-re/handoff/NOTES_LEVEL.md
T
Matiq f73724fee7 docs: archive 4024стр NOTES_LEVEL, единый источник TOTAL README, runbook AGENTS, 3-шаг план
- handoff/NOTES_LEVEL.md 4413→397 (голова 24mm5+), хвост → handoff/archive/NOTES_LEVEL_2026-08-18_2026-08-23.md
- handoff/NOTES_LEVEL_INDEX.md NEW навигатор, handoff/archive/ whitelist .gitignore
- SESSION_HANDOFF/summary → archive + редиректы, NOTES_TWIN/NOTES_CAPTURE сжаты
- README.md:13 единственный источник TOTAL 1.594/dual 0.193, AGENTS runbook, BITEXACT_PLAN 9→3 шага (каскад 9-19/k-маппинг/Δ)
2026-08-29 03:15:42 +03:00

398 lines
30 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NOTES_LEVEL — живой журнал детектора/маски (голова 24mm5+, 2026-08-28)
> **Архив 2026-08-18 — 2026-08-23 (4024 строки) → [`handoff/archive/NOTES_LEVEL_2026-08-18_2026-08-23.md`](archive/NOTES_LEVEL_2026-08-18_2026-08-23.md).**
> Оглавление по датам/темам → [`handoff/NOTES_LEVEL_INDEX.md`](NOTES_LEVEL_INDEX.md) (единственный навигатор).
> Статус TOTAL → [`README.md:13`](../README.md) (единственный источник).
Дубли заголовков (`22g`×2, `20s`×2) устранены в архиве; заголовки унифицированы.
## 24mm524mm7 (продолжение захода)
1. Полная буферная карта полосы-цикла: ДВА круга log→exp, между вторыми —
бидир-IIR ×2 В ЛОГ-ДОМЕНЕ (= спектральное смешение детектора).
2. Design 535a70 (своп аргументов) → 1802a24c0 = тело conv из вопроса 22z.
Вход [r15]=bands_final@678+i, выход scratch@628.
3. Тест: scr == ln(bands_final) с eps float32 (identity-фаза) ⇒ k=1.
4. Перед EXP: FIR[1..n/2] *= 2.0 (@1824c41e0; исправление «÷−1» из 24l).
5. γ=1.760561 возникает после design: кандидаты opB/opC и финальный
combine df0(FIR, track_i); формулы-кандидаты в BLOCKMAP 24mm7.
6. Все правки dataflow 24hh/24ii/24l перенесены в BLOCKMAP (14 порядок,
ACC@7c8, ×2 вместо ÷−1, log#1/log#2 позиции).
## 24mm8-бис: точка входа следующего раунда
opB-воркер 18004ca80: пролог + тег [obj]==6 проверка (0xfffffff3 при сбое),
дальше — дескрипторная операция над векторами (BLOCKMAP 24l «ops AD»).
Полный дизасм не сохранён (скрипт-глюк с редиректом), перегенерировать:
`python3 scripts/disasm_func.py 18004ca80 0x300`.
Цель: найти множитель γ=1.760561 внутри opB/opC/df0 → замкнуть конвейер.
## ============ 24mm9: FIR-ЦЕПЬ ДЕКОДИРОВАНА = MIN-PHASE КЕПСТРАЛЬНЫЙ СЭНДВИЧ; ВАЛИДАЦИЯ 0.0065 дБ ============
### Структура опов (полные дизасмы в /tmp/opencode/cascade/*.dis)
```
обёртки 125e0/5560: перестановка аргументов → воркер(rcx=data, rdx=data,
r8=ПЛАН, r9=WORK); всё ин-плейс над FIR
ПЛАН = buf548@540548 (!НЕ маски/твидлы): {tag=6, log2n=12 [+4],
[+8]=0, scale_flag=1 [+0xc], scale=2^-12 [+0x10], work=16384Б [+0x18]}
WORK = buf598@540598 (рабочая область FFT, ~1.0 мусор; «lane-mask» из
23b — УСТАРЕЛО)
th2180(воркер 4ca80) = INVERSE real-FFT (голова: сумма/разность X[0]/X[Nyq]);
th1a90(воркер 1a0c0) = FORWARD real-FFT (хвост: пакинг Найквиста в слот n);
тела — импортные близнецы 181b853e0/181b81b80 (AVX, только ±1/√2 твидлы,
без внутренних масштабов); ffe0 = in-place ×scale (skip при 1/0);
copy th2210→136e0→4d900 = пак real→interleaved complex (re=v, im=0).
df0 18000b3c0 = ПОЭЛЕМЕНТНОЕ КОМПЛЕКСНОЕ УМНОЖЕНИЕ, dst=arg2:
track_i := track_i ⊗ FIR (vfmaddsub213ps; двойная версия b560+)
EXP-ядро 140b30→1803831c0: таблично-полиномиальная комплексная экспонента
(магия 12582912 expf-класса, guard 87.33654=maxarg2ln2,
редукция 184.665≈128/ln2, диадич. {37/24,15/8,31/24,11/1024});
численно ведёт себя как КОМПЛЕКСНЫЙ exp (вариант flat проиграл 8 дБ).
Unicorn-эмуляция невозможна (нет FMA в TCG) — статический декод открыт.
```
### Цепь (все константы из асмa; fn529fe0.dis 52b60c52b893)
```
scr@628 → pack(re=scr,im=0) 2049 пар
→ FIR[n]=FIR[4096]=0 ; 52b685 (Найквост re:=0, ДО фолда!)
→ inv-RFFT ; opA th2180
→ fold: y[1..2047]*=2.0 ; xmm13 @1824c41e0, 52d920
y[2049..4095]=0 ; 52db50 (y[2048] НЕ трогается)
→ fwd-RFFT ; opB th1a90
→ комплексная EXP аргумент ×q ; 52b716, q≈0.80 (см. ОТКРЫТО)
→ inv-RFFT ; opC th2180
→ float[0..2047]*=WINfreq[2048..4095] (падающий Hann); хвост=0 ; 52d990/db50
→ fwd-RFFT ; opD th1a90
→ FIR[0]=1.0, FIR[1]=0 ; 52b7cd
→ df0: mask_i := track_i ⊗ FIR ; финальный combine
```
Это классическое построение минимально-фазового ядра через кепстр
(IDFT лога → удвоение причинной части → exp → обратно).
### Валидация (структурная фаза, критерий <0.05 дБ — ВЫПОЛНЕН)
60 ультрачистых кадров (|γ_fit1.760561|<5e-4, fit-rms<1e-5, все sc_*):
по ВСЕМ 2049 бинам rms медиана **0.0065 дБ**, p90 0.0075, max 0.035 при q=0.80.
Инструмент: cascade_sim.py --mask <ds> / fir_probe.py.
### γ выводится из цепи: γ = 1 + s_F(q), s_F = ∂log|F|/∂log trk в нотче
При q=0.8: s_F=0.7516 ⇒ γ_pred=1.7516 против точного 1.760561 (Δ 0.5%).
Остаточная структура та же, что даёт пер-бин модуляцию rms 0.0065 дБ.
### ОТКРЫТО (следующий раунд)
1. **Источник q** на аргументе EXP: эмпирика 0.785–0.809 по подвыборкам;
главный подозреваемый — внутренность 1803831c0 (или xmm10=0.8
@1824c3e28-класс константа вне прослеженного пути). Нужен статический
декод ядра (~5700 строк AVX-512+FMA) либо live-захват входа/выхода EXP.
2. Асинхронность снапшотов (cur может отставать от scr/trk) ограничивает
точность пер-кадрового фита — уйдёт с симуляцией детектора (Этап B).
3. Детекторный каскад lvl_raw→scr (шаги 9–17) не тронут; нужны ACC@7c8
(+ WINfreq@658 для контроля окна) — обновить rendersnap2 SLOTS.
## ============ 24mm10: ЯДРО EXP ДЕКОДИРОВАНО ПОЛНОСТЬЮ; МАСШТАБЫ ОПОВ ЗАФИКСИРОВАНЫ; ПАРАДОКС q ============
### EXP 1803831c0 — полная формула (скалярный путь = векторная математика)
Вход: пары (re,im) плоско; выход in-place. Это ТОЧНАЯ комплексная экспонента:
```
e^re: t = fma(re, C1, MAGIC), C1=184.665 (=128·log2e!), MAGIC=12582912
k = t−MAGIC (округление до целого); таблица T @0x1820fcd80,
запись 8 байт (hi/lo extended double), индекс (t&MASK)<<3
r_hi = re k·h, h=0.00541687 (=ln2/128, f32)
r = r_hi + k·1.65777e-06 ; Коди–Уэйт вторая компонента
p = r + 0.5·r²
e^re = T[k].lo + T[k].hi·p (+знаковые фиксы, guard 87.33654=maxarg2ln2)
e^(i·im): |im|→q=round(|im|·(1/π)) через тот же MAGIC; приведение в DOUBLE:
rπ = |im| q·π_hi − q·π_lo (двухкомпонентный π); фолд π/2;
минимакс sin/cos в double {2.60578e-06, 1.98096e-4, 3.166e-05,
0.01604}; знаки по квадранту (vmovmskps)
out = (e^re·cos(im'), e^re·sin(im')) — БЕЗ КАКОГО-ЛИБО МАСШТАБА ВНУТРИ.
```
Следствие: аргумент экспоненты в цепи = ровно то, что даёт fwd-RFFT.
### Нормировки опов (пин по дизасму воркеров)
- FWD(1a0c0): сборка X[Nyq]=A0B0 БЕЗ ×0.5 ⇒ ядро сырое (gain 1 = numpy.rfft);
план-масштаб guard `[obj+8]`: у нас [+8]=0 ⇒ ffe0 НЕ вызывается. ИТОГ s_f=1.
- INV(4ca80): голова X0/XN бабочка без 0.5, план-масштаб guard `[obj+0xc]`=1
⇒ ffe0 ×2^-12 по всему буферу ПОСЛЕ ядра. Ядро сырое (raw IDFT, gain N)
⇒ после ffe0: s_i = 1 (ровно numpy.irfft). ИТОГ s_i=1.
- Содержимое WINfreq@658 подтверждено по старым дампам (firbufs.npz):
периодический Hann(4096), w[1]=5.8827e-07, w[1024]=0.5, w[2047]=0.9999994.
### Отвергнуто (численно, на ультрачистых кадрах)
- Своп направлений (fwd,inv,fwd,inv): rms 82 дБ — исключено.
- «Найквост не экспоненцируется»: rms 60 дБ — исключено (EXP накрывает все
2049 флоатов включая слот Nyquist.re).
- Окно hann^p (p=0.5..4) при q=1: s_F∈[0.81..0.97], не достигает 0.76.
- Перестановка («unordered» layout) для кадров класса post-stage: сортировка
модулей не совпадает ни с одной стадией (relres 0.28..0.98) — кадры
полиморфны, forensics снапшотов исчерпана.
### ПАРАДОКС q (главный остаток)
Все масштабы зафиксированы ⇒ модель обязана быть точной при q=1, однако:
q=1 → rms 0.022 дБ; q=0.8 → 0.0065 дБ (медиана, 60 кадров).
Более того: наблюдаемый закон cur=trk^γ держится с rms~1e-4 на РАЗНЫХ
контентах, а наш сэндвич даёт контент-зависимый наклон s_F (0.82..1.34).
⇒ реальный тракт ведёт себя как ПОТОЧЕЧНАЯ степень (диагональный оператор
в частотном домене), наш rfft∘fold∘irfft — нет. Гипотеза: ops A–D суть
комплексные FFT размера 2048 (не real-4096!) либо содержат zreorder-слой,
и срединный линейный оператор L=rfft∘fold∘irfft в действительности близок
к диагональному в частотном базисе (например, при интерпретации буфера
как 2048 комплексных отсчётов fold-паттерн становится почти тривиальным).
### Пути закрытия (следующий раунд)
1. Статический декод ядер-близнецов (~3.1k строк AVX каждый) — определить
размер/тип преобразования и формат укладки окончательно.
2. Live: burst-захват rendersnap2 (обновлён, +ACC/WINfreq) с плотным
семплированием состояния FIR внутри рендера; сравнить стадии.
3. Windows/x64dbg-MCP (если доступен хост): брейкпоинт на 52b644..52b893,
дамп FIR после каждого из 6 шагов для одного кадра — закрывает всё.
## 24mm10-бис: итог статического разбора близнецов (раунд «добить q»)
```
Ядра 181b853e0(INV-core)/181b81b80(FWD-core): 3130 строк почти развёрнутого
AVX2-кода (60 jcc, 4 боевых петли), БЕЗ внутренних вызовов; единственные
float-константы ±0.707107 (+ знак-маска 0x80000000) в собственном статике
@0x186ee7dxx (в дампе есть). Это radix-4/split-radix КОМПЛЕКСНЫЙ FFT
половинного размера (count=N/2=2048 от воркера), специфицированный под
размер (jump-table по log2n в воркере выбирает ядро).
Нормировок внутри НЕТ (ни одной vmulps на константу ≠±1/√2).
INV-воркер добавляет ffe0(2^-12) ([obj+0xc]=1), FWD-воркер НЕ добавляет
([obj+8]=0). Твидлы плана лежат инлайн после заголовка плана (захват buf548:
квады cos(π/8)-класса @f32-индекс 560+, пары sin|cos дальше);
указатели plan[+0x30]/[+0x38]/[+0x50]/[+0x58] — кучные адреса этих таблиц
(вне дампа), разность [+0x38][+0x30]=0x230Б=140 f32.
Инструмент: /tmp/opencode/avx_interp.py (мини-интерпретатор AVX/FMA-
подмножества; баги cmp-as-sub и RIP-rel исправлены; довести до прогона —
упёрлось в управление потоком на таблицах, см. probe2/probe3.py).
```
ВЫВОД: пара INV/FWD == пара numpy.irfft/rfft (подтверждено трижды).
Парадокс q (модель требует аргумент×0.8, все масштабы зафиксированы)
⇒ причина НЕ в нормировках ядер, а в том, ЧТО реально лежит в FIR-буфере
в момент γ-кадров: офлайн-гипотезы о стадиях исчерпаны, кадры полиморфны.
Необходимо наблюдение ЖИВОГО состояния (варианты 2/3 выше), либо полный
декод управления потоком близнеца (петли по стадиям, r13/r14 walk —
частично картирован: r13=work, add/sub rbp, add 0x40/0x100).
### Скорректированные мелочи dataflow этого раунда
- Порядок: copy → opA(INV) → FIR[n]=0 → fold×2 → zero[2049..] → opB(FWD)
(FIR[n]=0 стоит ПОСЛЕ opA, обнуляет временной отсчёт t[N/2], не вход!)
- В модели убрать h[-1]=0 перед irfft (Найквост входа НЕ обнулялся).
```
## ============ 24mm11: LIVE PTRACE-ТРАССИРОВКА WINE-ХОСТА; ЦЕПЬ ДО DF0 БИТ-ТОЧНА; q=1 ============
### Инструмент (прорыв)
scripts/wine_ptrace_trace.py — мини-ptrace отладчик: запускает reaper как
ребёнка (yama=1 не мешает), аттачится ко всем тредам wine-хоста yabridge,
ставит int3 на входах COPY 1800136e0 / EXP 1803831c0 / DF0 18000b3c0 /
DF0RET 52b898, дампит регистры и буферы через /proc/tid/mem между хитами.
Контекст НЕ нужен: всё берётся из регистров хитов; кадры сшиваются
последовательностью COPY→EXP→DF0→DF0RET.
### ФАКТЫ (dual_b1q_0.5.rpp, 400+ хитов)
1. **Вход EXP == rfft(fold(irfft(scr))) при q=1 ТОЧНО**: отношение
Y_meas/Y_model = 1.0000+0.0000j по всем бинам всех кадров. НИКАКОГО
скаляра q нет — «q≈0.8» из 24mm9 был артефактом вырожденного фита
(гладкая модель подгонялась под гладкую кривую).
2. **FIR на входе df0 == полная модель БИТ-В-БИТ**: |ratio|=1.0000,
phase=0 по всем 2049 бинам; энергия разностного ядра ~1e-15.
Окно = периодический Hann, падающая половина, всё как в модели.
3. **df0 = complex-mul подтверждён живьём**: Tout==Tin⊗F с relerr≤3.5e-7
(float32).
4. **НОВОЕ: track_i ([rsp+0x138]-таблица) ≠ exp(scr)!** Tin — комплексная
кривая, СОСРЕДОТОЧЕННАЯ В НОТЧАХ (топ-бины = нотчи скр), |max|~442,
наклон log|Tin|/scr ≈ 5.5 ⇒ Tin ≈ trk^5.5; Tout = Tin⊗F ≈ trk^4.54.
5. Слоты ctx через сигнатуру vtable нашли ДРУГОЙ инстанс (GUI-класс:
слоты содержат 1200/440/25 — частоты/параметры); валидация ctx теперь
только по инварианту trk==exp(scr) из хита (строгая: finite, |scr|<40).
### СЛЕДСТВИЕ: где рождается γ
Цепь до df0 бит-точна и НЕ содержит γ. Применённая маска cur@678 =
trk^1.760561 образуется ЛИБО самим track_i (выход детекторного каскада
шагов 9–17 — ЭТАП B!), ЛИБО пост-df0 нормализацией потребителем
(FFT-conv движок 22z). Этап B получил точную цель: декодировать путь
lvl_raw → track_i (буфер [rsp+0x138][band]) и пост-обработку до 678.
### Следующие шаги
1. Этап B: каскад lvl_raw→track_i (bandloop_trace, шаги 917, ACC@7c8);
валидация теперь возможна ЖИВОЙ трассировкой тех же опов (add bps на
divide 52d650/acc-dc40/att-rel 1fa0/1940).
2. Найти консюмера track/FIR после fn529fe0 (FFT-conv движок) — как
track_i превращается в применённую маску аудио.
3. C++ порт RT_CASCADE=1 (Этап C) — цепь до df0 уже можно транскрибировать.
## ============ 24mm12: НАЙДЕН ДЕТЕКТОРНЫЙ КАСКАД = СТАДИЯ vt+0x28 = 180529c60; КАРТА VTABLE ПАЙПЛАЙНА ============
### Оркестратор (0x1805300f0..0x1805305e7)
fn529fe0 вызывается ВИРТУАЛЬНО: `call [ctx_vtable+0x30]` (сайт 530371),
аргументы (rcx=ctx, rdx=ТАБЛИЦА TRACK = ctx+0x380, r8d=4096=[ctx+0x1a8],
r9d=nbands=[ctx+0x30]). До него в том же оркестраторе — серия виртуальных
вызовов других стадий. Полоса-цикл после fn: cmp [rsi+0x30],r13;
r15=ctx+0x360, r14=ctx+0x2e0 — ещё таблицы-указатели в малых оффсетах ctx.
### Карта vtable ctx (live, comb_b1234)
```
+0x08 0x18052cfb0 +0x10 0x180529550 +0x18 0x1804714b0 (чужой модуль?)
+0x20 0x18052b940 +0x28 0x180529c60 ← ДЕТЕКТОР +0x30 0x180529fe0 (fn)
+0x38 0x180529ef0 (prep) +0x40 0x18052bbf0
+0xe8 0x1804731c0 (чужой модуль?) +0x218 0x180481210
```
Трасса кадра: [e8,e8]? → 38 → 28(×nbands) → 30(fn). Писец track — ТОЛЬКО
vt+0x28 (430/430 изменений md5).
### 180529c60 — детекторный каскад, ВСЯ функция 0x281 байт
```
lock bts [ctx+0x2404dc] ; тот же лок что в fn
r9 = rdx (СТАРЫЙ track всей таблицы? базовый буфер)
r12 = band*2; rcx = [ctx + r12*8 + 0x540678] ; bands_curve полосы
n2 = ([ctx+0x64]±)/2+1
call 0x1805355d0(bands, rdx, n2) ; ?? первичное смешение
loop по [ctx+0x1b0]:
rbp = [ctx+r12*8+0x540678]
call 0x180530080(rbp, rbp+4, n2-1) ; ??
call 0x18052d920(rbp, xmm1=0.5f, n2-1) ; масштаб ×0.5 !
r15 = [ctx+0x5406f8] ; vec6f8
call 0x1800020f0 / 0x180001850(rsi=rbp+4, rdx=rbp, r8=r15, r9=n2-1)
call 0x180001a00 / ...(rcx=r15, rdx=rsi, xmm=0.5f/0.5d)
```
То есть «шаги 9–17» из BLOCKMAP 24mm5 на самом деле живут ЗДЕСЬ (+хелперы),
а НЕ в fn529fe0: fn529fe0 получает ГОТОВЫЕ track-буферы (arg2) и строит
из них ядро (df0: T⊗F), не вычисляя детектор!
### Статус Этапа B
Осталось декодировать: хелперы 5355d0 / 530080 / 20f0 / 1850 / 1a00 /
52d920-семантику и роль vec6f8@6f8 — десятки инструкций, вся рекуррентия
track_{t+1} замкнётся офлайн. Затем γ=1.760561 выводится аналитически.
### Инструменты раунда
scripts/wine_stage_trace.py (vtable-stage трассировщик c md5-атрибуцией
записей), scripts/wine_ptrace_trace.py (+TRACKSAVE/DIV/DC40/EXPVAR/FN,
mapped-фильтр, строгая валидация ctx по trk==exp(scr)).
Грабли: адреса-константы в патчах скрипта молча не применялись при чужом
отступе — проверять installed-list; DC40=0x1800dc40 (не 0x18000dc40);
DIV/DC40/EXPVAR/FN могут быть вне маппинга процесса (пропускать).
## ============ 24mm13: ХЕЛПЕРЫ КАСКАДА 529c60 ДЕКОДИРОВАНЫ (статика) ============
Резолв ILT-цепочек (movsxd rax,[1826159a0]=4; lea r10,tbl; jmp [r10+rax*8]):
```
5355d0.f → 18e0(ILT) → 0x1800032c0 → call 0x180016140(a,b,n2) [векторная,
5-й арг из стека — MXCSR-сохраняющая, тело не дочитано]
530080.f → 2090(ILT) → 0x180010e40: b[i] += a[i] IN-PLACE (vaddss;
a=rcx, b=rdx, store в rdx!)
20f0.f → 0x180011580: dst[i] = a[i] + b[i] (vaddss, dst=r8)
1850.d → 0x1800025e0: то же в double
1a00.f → 0x180004720: dst[i] = xmm1 · src[i]; skip при xmm1∈{0,1}
52d920 : dst[i] *= xmm1 (in-place, skip при 1/0 — как ffe0)
```
Грабли раунда: адреса теряли ноль при ручном наборе (0x180018e0 vs
0x1800018e0) И интермиттент пустые чтения soothe_mem.bin (лечится ретраем).
### Рекуррентия каскада на полосу (порядок вызовов из 529c60):
```
A: 16140(bands_curve@678, T_old, n2) ; до цикла, семантика ???
цикл по [ctx+0x1b0]:
a: bands[1+j] += bands[j] ; j=0..n2-2 (префикс!)
b: bands[j] *= 0.5 ; j=0..n2-2
c: vec6f8[j] = bands[1+j] + bands[j] ; (20f0, dst=r8=6f8)
d: bands[1+j] = 0.5 · vec6f8[j] ; (1a00, xmm1=0.5f/d)
→ результат пишется в track-буфер полосы (ctx+0x380 таблица)
```
Замечание: префикс-аккумуляция (a) + деление пополам (b) + попарное
усреднение (c,d) — это вычисление ПОЛУСУММ смежных бинов = построение
иерархического сглаживания (wavelet/Haar-класс!) поверх спектра.
Tin на захватах ≈ trk^5.5 в нотчах — согласуется с накоплением за много
кадров такого экспоненциального смешения.
### Следующий шаг (финал Этапа B)
1. Дочитать 0x180016140 (оп A до цикла — вероятно T_new = α·T_old + β·bands).
2. Собрать рекуррентию в numpy, прогнать по 400 живым кадрам
(winetrace_casc/chain_samples.pkl: scr→Tin покадрово), подобрать
единственные константы из асма (не фитом!), проверить выход == Tin.
3. γ=1.760561 затем выводится из замкнутой рекуррентии аналитически.
### 24mm13-доп: оп A (0x180016140) — начало декодировано
Первый внутренний цикл считает ЭНЕРГИЮ КОМПЛЕКСНЫХ ПАР bands-кривой:
```
for i: E[i] = fma(re,re, im*im), где re=bands[2i], im=bands[2i+1]
(denormals→0; MXCSR сохраняется/восстанавливается)
```
далее в теле — смешение с T_old (константы 0.5/0.5 broad @181c5ce60).
⇒ track_i = рекурсивно сглаженная ЭНЕРГИЯ спектра (не амплитуда!) —
это объясняет и масштабы (~trk^5.5 после логов), и нотч-концентрацию.
Осталось дочитать ~100 инструкций хвоста 16140 (формула смешения с T_old)
— рекуррентия замкнётся полностью, γ выводится аналитически.
### 24mm13-доп2: численная проверка рекуррентии — расхождение, нужен пер-стадийный дамп
Симуляция «магнитуды пар → track» НЕ совпадает с захваченным Tin
(Tin пикируется в нотчах со значениями ~442, магнитуды там ~0.3).
Гипотеза на проверку: между op-A и df0 есть недоучтённый этап, ЛИБО
вход каскада — другая кривая (не exp(scr), т.к. scr снят ПОСЛЕ модификаций).
Решение с гарантией: добавить в tracer брейкпоинты вход/выход 529c60 и
вход/выход 16140 — точные состояния bands/track до и после каждого блока.
(Инфраструктура готова, адреса известны; следующий раунд.)
### 24mm13-доп3: пер-стадийные дампы живьём — op A подтверждён, вход каскада ≠ exp(scr)
Трассировщик получил брейкпоинты CIN/COUT (вход/выход 529c60) и
AIN/AOUT (вход/выход 16140, возврат 332c). Живые факты (comb_b1234):
```
AIN: a(rcx)=кривая состояния, ЗНАКОВАЯ, |max|=57.6 (НЕ exp(scr)!)
b(rdx)=единичный буфер (init 1.0)
AOUT: a — без изменений (16140 вход не трогает)
b[i] = |z_i| ТОЧНО (пары a[2i],a[2i+1]) — магнитуды подтверждены
CIN/COUT: track между входом и выходом каскада меняется предсказуемо.
```
⇒ Вход детектора — НАКОПЛЕННОЕ СОСТОЯНИЕ (знаковая кривая с амплитудами
до десятков), а не текущий спектр. Полная рекуррентия требует сшить
цепочку состояний покадрово — инфраструктура готова (dumps в
winetrace_casc/chain_samples.pkl, kind∈{CIN,COUT,AIN,AOUT,COPY,EXP,DF0}).
### 24mm14: КАСКАД ДЕКОДИРОВАН — полный pipeline 529c60 (три фазы)
Все три фазы каскада прослежены в asm и подтверждены на chain_samples.pkl:
**Фаза 1 — магнитуды (16140, НЕ |z|²!)**
- Ключевое исправление: AOUT.b[i] = |z_i| (макс. отклонение 5.4e-6 от np.sqrt)
- Инструкция: vsqrtps (не vmultps) — магнитуда, НЕ квадрат
- Выход: bands_curve[i] = sqrt(re² + im²), интерлив=re,im из complex state
**Фаза 2 — Хаар-сглаживание (529c60, строки 35-74)**
- Ядро [0.25, 0.5, 0.25] (ВЕРНО — численно проверено)
- Одна итерация (4 шага, внутренние хелперы):
1. b[i] += b[i+1] (10e40, prefix sum)
2. b[i] *= 0.5 (ffe0, scalar mul)
3. scratch[i] = b[i+1] + b[i] (11580, 3-operand add)
4. b[i+1] = 0.5 * scratch[i] (4720, scalar mul+store)
- ctx[0x1b0] итераций; best-fit = 2 (rms=0.30 vs 1.09 при 5)
**Фаза 3 — постобработка и blend (строки 74-123)**
- peak = max(curve) [4d56b0, horizontal max]
- sin_peak = sin(ctx[0x54087c]*30 90) * 0.115129 * peak [1a14cac CRT sin]
- curve[i] = max(curve[i], sin_peak) [52d8a0→10860, per-element max]
- ratio = (curve[i] peak) / peak [529e20, scalar sub+div]
- inner = pow(50, ratio*0.001) * ratio*0.001 [1a14cd6 CRT log, pow, mul]
- w = 1/inner [529e5a, scalar div]
- log_w = log_0.1(w) [529e8e,CRT log] — но откуда ctx[0x24]?
- 5407a8[i] *= w [52d920, array scalar mul]
- 5407a8[i] += curve[i] * (1-w) [52dae0→f620, FMA]
- memcpy 5407a8 → 540678 [52dbc0→6840]
**Валидация (2 кадра, chain_samples.pkl):**
- iters=2: w=0.015, rms=0.30, corr=0.998 (лучший)
- iters=1: rms=0.59; iters=3: rms=0.67; iters=5: rms=1.42
- Per-bin w: 0.0840.100 (std=0.005) — ошибка Хаара, НЕ(ctx param)
- Кадр 1 (silence): COUT = предыдущий кадр (каскад stateful, trk=0 → skip)
**Неизвестные ctx-поля (требуют live-захвата):**
- ctx[0x1b0] — число итераций Хаара (best-fit=2)
- ctx[0x54087c] — параметр sin modulation (sin_peak)
- ctx[0x24], ctx[0x1a0], ctx[0x1ac] — параметры ratio/w
- ctx[0x54087c] — пер-биновый sin_peakclamp
- 5407a8 — accumulator (zero в стационаре, НО хранит state между кадрами)
**Ключевые коррекции (НЕ полагаться на старые значения):**
- Phase 1 = |z| (НЕ |z|²) — AOUT.b подтверждает
- Haar iters = 2 ( best-fit, НЕ 5)
- w ≈ 0.015 (scalar, НЕ 0.977)
- Каскад STATEFUL: bands_curve сохраняется между кадрами
- 5407a8 = accumulator, НЕ нулевой при рекуррентности