56 KiB
Changelog
2026-09-12 — этап 15 одиннадцатого аудита (fix audit-14)
Устранены остаточные расхождения одиннадцатого статического аудита
(Git HEAD 9349164): игнорирование отказа снятия checkpoint.marker в
основном экспорте, повторная выдача новой сессии каталога с частичным
остатком прерванного экспорта (только samples/events) и остаточная
принудительная перерисовка при клике по чужому объекту графика внутри
открытого измерительного окна.
Прежние 126 условий проходят; новая регрессия этапа 15 (SESS-03):
RequestLatencyTests PASS=127 FAIL=0 TOTAL=127,
сборка 4 exe 0 errors / 0 warnings.
- R15-B1 (P1): ExportRun проверяет результат FileDelete при инвалидации checkpoint.marker (как ExportCheckpoint) — при отказе пара samples/events НЕ открывается на перезапись, экспорт повторяется на таймере; результатом удаления является false (MQL5 FileDelete [D1]).
- R15-B2 (P1): NewSessionId считает каталог занятым по ЛЮБОМУ известному файлу отчёта сессии (SessionDirUsed: samples/events/schedule/deals/summary/ histogram/offset_signs/comparisons/market_windows/market_ticks/checks/ experiment_manifest), а не по трём служебным именам — частичный остаток прерванного экспорта не маскируется новой сессией.
- R15-S1 (P2): клик по чужому объекту графика в OnChartEvent не вызывает принудительную перерисовку внутри открытого окна измерения (тот же безопасный режим, что в ветви занятого Start).
2026-09-12 — этап 14 десятого аудита (fix audit-13)
Устранены расхождения десятого статического аудита (Git HEAD 148e7a7):
повторное использование каталога сессии LOCAL_ONLY, действующий marker после
повреждения пары основных файлов экспортом и остаточная принудительная
перерисовка внутри отдельных открытых окон.
Прежние 123 условия проходят; новые регрессии этапа 14 (SESS-01, SESS-02,
WIN-02): RequestLatencyTests PASS=126 FAIL=0 TOTAL=126,
сборка 4 exe 0 errors / 0 warnings.
- R14-B1 (P1): идентификатор запуска отделён от измерительной шкалы — NewSessionId выдаёт каталог по МОНОТОННОМУ счётчику сессий (курсор не сбрасывается между вызовами) с проверкой существования каталога с данными сессии (intents/manifest/checkpoint.marker): переустановка EA и повтор после отказа первого INTENT получают НОВЫЙ session_id, перезапись прежнего отчёта исключена; при исчерпании кандидатов — ошибка до записи/торговли.
- R14-B2 (P1): финальный marker публикуется ТОЛЬКО после полной записи и контрольного чтения всей таблицы экспорта (единый PublishCheckpointMarker); основной экспорт инвалидирует опубликованный marker ДО перезаписи пары samples/events — обрыв между стадиями не оставляет действующий «успех» над повреждённой парой.
- R14-S1 (P2): InMeasurementWindow учитывает и активный cleanup (не только основную последовательность); отклонённый клик восстанавливает нажатый вид кнопки БЕЗ принудительной перерисовки внутри открытого окна (ChartRedraw откладывается до паузы).
2026-09-12 — этап 13 девятого аудита (fix audit-12)
Устранены остаточные расхождения девятого статического аудита (Git HEAD 37b3090):
сохранность незавершённого синтетического прогона, единый gate финализации,
изоляция окон повторной E3-сессии, проекция состояния панели из контроллера и
запрет принудительной перерисовки внутри измерительного окна.
Прежние 119 условий проходят; новые регрессии этапа 13 (START-03, START-04,
RESTART-01, CHECK-01): RequestLatencyTests PASS=123 FAIL=0 TOTAL=123,
сборка 4 exe 0 errors / 0 warnings.
- R13-B1 (P1): отказ SyntheticDispatch (durable-запись INTENT/SEND_RETURN) больше НЕ стирает контекст незавершённой сессии — RunSynthetic финализирует её (FINISHED + termination_reason SYNTHETIC_DURABLE_WRITE_FAILED), StartRun возвращает true и направляет вызывающий код в экспорт частичного отчёта (run_status=INCOMPLETE); резерв ДО T0 снимается (ReleaseReservation) — он не является выполненным наблюдением; прерванная после T1 запись сохраняется как DISPATCH_UNCERTAIN; ExportRun/ExportCheckpoint гарантируют каталог сессии (FolderCreate) даже при отказе на первом INTENT.
- R13-B2 (P1): финализация — ЕДИНЫЙ проверяемый результат: FinalizeRun() требует успешный финальный checkpoint (ExportCheckpoint(true) возвращает bool и подтверждает marker контрольным чтением) И основной экспорт; повторяется именно неуспешная стадия; FINISHED и разблокировка кнопки только после полного набора. Иные завершения (DriveNext/EndMainCycle) используют ту же финализацию — marker обязателен для любого пилота.
- R13-B3 (P1): ResetForRestart и StartRun очищают оконный контекст E3 прежней сессии (m_windows/m_window_count, счётчики и недописанные оконные ссылки) — старые окна не выгружаются в market_windows.csv новой сессии с её session_id.
- R13-S1 (P1): панель хранит НАМЕРЕННОЕ состояние кнопки (m_started) и RestoreStartedState() восстанавливает нажатый вид после того, как OBJ_BUTTON сам переключил OBJPROP_STATE при отклонённом клике; терминальный BLOCKED отображается сразу (без зависимости от latch команды) и запрещает торговлю.
- R13-S2 (P1): SyncPanelPhase не вызывает ChartRedraw внутри открытого измерительного окна (обновляется только текст панели; отрисовка — в паузе).
2026-09-12 — этап 12 восьмого аудита (fix audit-11)
Исправлены четыре группы функциональных расхождений восьмого статического аудита
(Git HEAD 9465fe6): повторный запуск с накопленными счётчиками/пропуском экспорта,
двойной старт одного клика (timer + OBJECT_CLICK), ложный FINISHED при ошибке
сохранения и зависимость финального checkpoint от 60-секундного порога.
Прежние 117 условий проходят; новые регрессии этапа 12 (RUNN-01, START-02):
RequestLatencyTests PASS=119 FAIL=0 TOTAL=119, сборка 4 exe 0 errors / 0 warnings.
- R11-B1 (P1): повторный запуск после финализации — независимые счётчики прогона (CExperimentRunner::Init обнуляет MainDispatched/WarmupDispatched/CleanupDispatched/ PrecheckRejected/DispatchUncertain), ExtExportDone сбрасывается перед StartRun; вторая сессия получает полный комплект отчётов (manifest/summary/market_ticks), а не накопленные 400/40. Регрессии RUNN-01, START-02.
- R11-B2 (P1): один физический клик = один StartRun — независимый опрос OBJPROP_STATE для запуска убран (источник истины — latch ExtStartPressed, выставленный синхронно в OnChartEvent, потребляется таймером ровно один раз); двойной клик и клики во время прогона игнорируются и не отменяют текущую сессию.
- R11-B3 (P1): ошибка экспорта не маскируется под FINISHED — пока отчёт не сохранён, кнопка остаётся нажатой/заблокированной, повторный запуск запрещён, статус EXPORT_FAILED с повторной попыткой на таймере; ResetForRestart разрешён только после успешного экспорта.
- R11-S1: финальный checkpoint отделён от периодического — ExportCheckpoint(force) пишет маркер всегда (короткий пилот не зависит от порога 60 с синтетического времени); ошибка SyntheticDispatch (durable-запись) теперь возвращает StartRun=false и состояние READY вместо ложного FINISHED с неотправленными резервами.
- Панель: SyncPanelPhase — статус фазы WARMUP/MAIN обновляется со счётчиками диспетчеризации при смене фазы (лёгкая перерисовка только при изменении).
2026-09-12 — этап 10 седьмого аудита (fix audit-10)
Устранены четыре группы функциональных расхождений седьмого статического аудита
(Git HEAD a281c07): потеря ручного Start, неверное восстановление повторного
INTENT после отмены, раннее закрытие cleanup без ожидаемых DEAL-callback и
повреждённый формат архива тиков E3. Прежние 65 контрольных условий проходят;
новые регрессии этапа 10: RequestLatencyTests PASS=117 FAIL=0 TOTAL=117,
сборка 4 exe 0 errors / 0 warnings.
- R10-B1 (P1): ручной Start захватывается СИНХРОННО в OnChartEvent (latch команды), а не опросом OBJPROP_STATE в OnTimer - клик больше не теряется. Кнопка остаётся нажатой/заблокированной весь прогон (CLatencyPanel::SetStarted), в Status выводятся фаза и итог; после финализации кнопка отпускается и работает повторный запуск (CAppController::ResetForRestart FINISHED->READY, новая сессия) либо ExpertRemove оператором. Терминальный BLOCKED также отпускает кнопку и показывает причину. Регрессия START-01.
- R10-B2 (P1): CountUncertainDurableIntents сопоставляет INTENT_CANCELLED РОВНО с одной попыткой того же sequence (хронологическая пара, массив cancel_used): повторный INTENT после отмены без SEND_RETURN остаётся неопределённым (n_dispatch_uncertain+1); прежняя отмена не маскирует новую попытку. Регрессии DURA-09 (cancel->retry->crash => 1) и DURA-10 (cancel->retry->SEND_RETURN => 0).
- R10-B3 (P1): DriveCleanup принимает решение о закрытии коллекции cleanup по СВЕЖЕЙ сверке (snapshot + SyncReconcile + CompletedCheck ДО условия закрытия) по единой политике CompletedCheck: измерительные точки полны И полнота DEAL-callback (T4/T5/callback_coverage_complete) подтверждена для операций с ожидаемой сделкой (POSITION_CLOSE); PENDING_DELETE без сделки DEAL не ждёт; неполноту закрывает grace. Вспомогательный предикат CleanupCollectionReady. Регрессия CLN-02.
- R10-B4 (P1): FlushWindowTicks пишет market_ticks.csv с ЗАГОЛОВКОМ (session_id,window_id,window_seq,time_msc,bid,ask,flags,volume) при создании/пустом файле; разделитель строк - НАСТОЯЩИЙ CRLF (вместо литерального текста \r\n); точность bid/ask - %.17g (полный round-trip double). Для каждой сессии гарантируется наличие файла с заголовком (EnsureMarketTicksFile в ExportRun); сбой записи - fail-closed. Статические форматтеры MarketTickHeader/FormatMarketTickLine выделены для round-trip теста. Регрессия WINDOW-02.
- R10-S1 (P1): SyntheticDispatch формирует СОГЛАСОВАННЫЙ объём DEAL-callback - единственная сделка полного объёма плана (T4=T5); дубль deal с нулевым объёмом не создаёт рассогласование callback_volume/coverage. Локальный прогон пишет устойчивый журнал намерений (INTENT до T0, SEND_RETURN после T1) - intents.csv сессии существует и CountUncertainDurableIntents работает и на LOCAL_ONLY (критерии пилота: intents.csv, checkpoint.marker, market_ticks.csv).
- Тесты: TestAudit10Regressions (DURA-09, DURA-10, CLN-02, WINDOW-02, START-01).
2026-09-11 — этап 9 шестого аудита (fix audit-9)
Устранены функциональные блокеры R9-B1..B4 и существенные ограничения R9-S1..S4
по результатам шестого статического аудита (Git HEAD 4b16006). Повторные 48
контрольных условий аудита 8 на новом коде проходят; основные серии 5x100
разблокированы для пилота.
- R9-B1 (P1, E3): отказ по свежести контекста (code 8) БОЛЬШЕ не оставляет неотправленный резерв в tracker — добавлен RequestTracker::ReleaseReservation: удаляется запись без T0, повтор той же sequence слота проходит без дубликата ключа (не code 6), фантомный MAIN в samples не экспортируется (n_attempted растёт только по факту входа в транспорт). Откат выполняется и на pre-T0 отказах journal/durable-INTENT (code 61/63). Регрессия REL-01.
- R9-B2 (P1): DriveCleanup закрывает collection по ЕДИНОЙ политике MeasurementPointsComplete (T2 и T3 по операции; REJECTED без ордера освобождает T3) — T2 без T3 больше не завершает наблюдение cleanup раньше времени; неполноту закрывает grace, ноль остатка не подменяет готовность измерения. Регрессия CLN-01.
- R9-B3 (P1): ConfirmDurableSendReturns теперь возвращает успех; все вызывающие ветви (CompletedCheck, OnTimer, EndMainCycle, DriveCleanup) ПРЕРЫВАЮТСЯ при сбое durable-flush и НЕ перезаписывают терминальный BLOCKED; SendCleanup имеет собственный durability-gate (code 7) — служебная отправка запрещена при нарушении сохранности; QueueDurableSendReturn при нехватке буфера — fail-closed BLOCKED (а не молчаливый возврат). Регрессия DURA-07 (Directory-as-file отказ).
- R9-B4 (P1): checkpoint.marker инвалидируется ДО ЛЮБЫХ перезаписей данных (samples.csv/events.csv), результат FileDelete проверяется; при неуспехе файлы не трогаются и отправки блокируются (CheckpointState=false + BlockRun). Прерывание на любой границе больше не оставляет ложный «успех» старого поколения.
- R9-S1 (P1): LoadSamples проверяет ВСЕ 68 имён заголовка (цикл hi<68): подмена market_window_id/market_window_seq больше не принимается молча. Регрессия READER-08 (good=1, bad=-1 code 32).
- R9-S2 (P1, E3): поставлена ПОВТОРНАЯ проверка свежести ВЫБРАННОГО контекста (возраст наблюдения И возраст якоря окна относительно текущей котировки) НЕПОСРЕДСТВЕННО перед T0 (после синхронных записей durable-INTENT). При застое durable-INTENT явно отменяется (INTENT_CANCELLED), резерв откатывается (R9-B1), слот ставится в очередь — без фантомного send. CountUncertainDurableIntents учитывает INTENT_CANCELLED (пара = не неопределённость). Регрессия DURA-08.
- R9-S3 (P1, E3): Е3-окно не полагается больше на «границы+checksum+CopyTicksRange» — сырые тики окна удерживаются В ПАМЯТИ (ComputeWindowRawTicks) и выгружаются в market_ticks.csv в safe-фазе ПОСЛЕ закрытия окна (синхронная запись внутри измерительной фазы по-прежнему запрещена R8-B3); checksum остаётся проверкой. ExportRun дописывает оставшиеся тики при остановке. Формат описан в CSV_SCHEMA.
- R9-S4: новой E3-проверке присвоен отдельный ID REG-02 (не дублирует REG-01).
- R9-ДОП (NULL-сессия): guard'ы сессии (InitRun, AppendDurableIntent, FlushPendingSendReturns, FlushWindowTicks) сравнивали m_session_id только с "" — в MQL5 неинициализированная строка равна NULL, условие не срабатывало, и durable-записи уходили в корневой tests\intents.csv вне каталога сессии; когда этот путь занимал каталог (остаток Directory-инъекции DURA-07), flush падал с code 66 «durable line open failed». Все 4 guard'а переведены на NULL||"": сессия гарантированно создаётся в InitRun, каталог сессии используется по назначению. Регрессия DURA-03 (before=2 flush=1 load=1 pend=0 err=0, sess =tests_E1_S01_*).
Валидация: 4 exe 0 errors/0 warnings (MetaEditor 6191 avx2); RequestLatencyTests PASS=112 FAIL=0 TOTAL=112 (5 новых проверок R9); EOL CRLF (bareLF=0 по 6 файлам); CSV_SCHEMA.md обновлён (market_ticks.csv).
Ограничение тестирования, закрытое вручную: ветвь ReleaseReservation готова и покрыта регрессией; ветви E3ContextStale по якорю окна и реально затянутого durable-INTENT требуют живого терминала/диска — закрыты код-ревью и контрольными пробами аудита (stale->refresh->retry->1 SEND).
2026-09-11 — этап 8 пятого аудита (fix audit-8)
Устранены функциональные блокеры R8-B1..B4 и существенные ограничения R8-S1/S2/S3
по результатам пятого статического аудита (Git HEAD 22ce0ff):
- R8-B1 (P0, E3): после терминальной остановки E3_WINDOW_CAPACITY_EXCEEDED / E3_WINDOW_STORAGE_FAILED новая отправка недостижима: UpdateMarketRegime при переполнении/ошибке хранения окна НЕ выводит режим (regime=UNKNOWN, m_last_regime сбрасывается) и останавливает; DriveNext повторно проверяет состояние после UpdateMarketRegime; в PrepareAndDispatch добавлен гейт code 7 перед транспортом для FINISHED/BLOCKED. Регрессия REG-01.
- R8-B2 (P1): единая политика полноты измерительных точек CollectionCloseAllowed (REQUEST T2; ORDER_ADD T3 по операции, кроме однозначного отказа без ордера) применяется в CompletedCheck, пост-T6 ветви OnTimer и cleanup: одинаковое событие «callback-покрытие полное» больше не закрывает коллекцию раньше T2/T3 (grace закрывает позже). Регрессия T2-01.
- R8-B3 (P1): SEND_RETURN durable больше не пишется между T1 и обработкой callbacks — факт возврата буферизуется (QueueDurableSendReturn) и дописывается в safe-фазе после закрытия окна (FlushPendingSendReturns; вызовы после каждого CloseCollection и в ExportRun); сбой дописывания — fail-closed (BLOCKED). Регрессия DURA-03.
- R8-B4 (P1): CountUncertainDurableIntents — подтверждённые sequence собираются динамически (без cap 256): парный журнал 440/1000 попыток даёт 0 неопределённых; FileOpen INVALID_HANDLE различает отсутствие (0) и недоступность существующего файла (sentinel ULONG_MAX); короткое чтение FileReadArray и сбой ArrayResize — sentinel, а не частичный разбор; LoadDurableContent проверяет прочитанные байты. Регрессии DURA-04/05/06.
- R8-S1 (P1): общий quote-aware счётчик логических записей CCsv::CountCsvRecords использован и в ReadBackVerifyFile (multiline-экспорт не отвергает сам себя); capacity в LoadSamples — число НАБЛЮДЕНИЙ (заголовок не расходует); ParseRow отклоняет незакрытую кавычку; ParseCsvUlong проверяет диапазон 20 знаков; LoadUtf8 проверяет число прочитанных байт (FileReadArray возвращает uint [D3]). Регрессии READER-05/06/07.
- R8-S2 (P1, E3): в UpdateMarketRegime сначала фиксируется факт РЕАЛЬНО нового тика (монотонный time_msc), затем проверяется возраст — polling-путь восстанавливает контекст после паузы; перед T0 возраст контекста перепроверяется (отказ code 8 без durable-INTENT); в samples добавлены market_window_id/market_window_seq (68 колонок), в market_windows — ticks_checksum (FNV-1a 64 по time_msc/bid/ask валидных тиков) — набор тиков воспроизводится CopyTicksRange(from_msc,to_msc) и сверяется суммой; сырые тики в send-пути на диск не пишутся (синхронная запись внутри измерения запрещена по R8-B3). Регрессия WINDOW-01.
- R8-S3: FinalizeTransaction пишет ЕДИНОЕ exit_us один раз (без повторного SetExitTime); инструментальная граница длины обработчика описана честно (хвост финализации не включён); checkpoint.marker содержит поколение и удаляется до перезаписи файлов.
Валидация: 4 exe 0 errors/0 warnings (MetaEditor 6191 avx2); RequestLatencyTests PASS=107 FAIL=0 TOTAL=107 (10 новых проверок R8); EOL CRLF (bareLF=0 по 8 файлам); CSV_SCHEMA.md обновлён (68 колонок samples, ticks_checksum, read-back, intents).
Ограничение, оставшееся осознанно: недоступность durable-журнала (sentinel ULONG_MAX) не инъецируется в песочнице MQL5 (блокировка файла средствами языка невозможна) — ветвь покрыта регрессией только до границы «существует/пуст», а недоступные ветви — код-ревью и manual-тестом на реальном диске.
2026-09-11 — этап 7 четвёртого аудита (fix audit-7)
Блокирующие расхождения R7 устранены (демо-пилот и основные серии 5x100 — только после повторного статического аудита; см. также следующий контрольный запуск):
- R7-B1 — устойчивый журнал намерений:
AppendDurableLineпишет ровно n-1 полезных байт с индекса 0 (FileWriteArray(handle,array,start,count);StringToCharArrayс WHOLE_ARRAY копирует завершающий ноль — прежний вызов писал с последнего элемента и блокировал торговую отправку до T0). Настоящий файловый round-trip INTENT/SEND_RETURN без NUL и отказ записи — DURA-01/02. - R7-B2 — сборка callback-меток: раннее закрытие collection — только при
подтверждённой полноте ожидаемых точек T4/T5 (
callback_coverage_complete), а не по объёму из истории (snap.coverage_complete); снимок сhistory_scan_failedполноту T5 по подмножеству тикетов НЕ повышает (SyncReconcile); при доказанном покрытии после T6 коллекция закрывается в OnTimer, запоздавшие в окне DEAL_ADD вносят исходные метки без пересчёта финального исхода. - R7-B3 — прогрев: квота — только по фактическим отправкам (
WarmupQuotaMet); расписание, исчерпанное с недобором фактических отправок (систематический precheck-отказ), — терминальныйWARMUP_INSUFFICIENT_DATAна ВСЕХ переходах в MAIN (единыйReturnToSchedule), а не только в ветви DriveNext(WARMUP). - R7-B4 — CSV-reader: деление на ЛОГИЧЕСКИЕ записи (кавычки/встроенные переводы
строк/CRLF), терминатор снимается один раз; пустые числовые ячейки сверяются с
present_mask(несоответствие — отказ code 40);offset_signs_rebuilt— схема 10 колонок как онлайн;histogram_rebuilt/offset_signs_rebuiltстроят группы условий ИЗ ДАННЫХ + combined (одинаковые данные — одинаковая схема таблиц онлайн/rebuild). - R7-B5 — свежесть котировки:
NoteQuoteObserved(quote.time_msc)обновляет время наблюдения ТОЛЬКО при новом тике Рабочего символа (InpSymbol); повторное чтение прежней котировки застой не маскирует; OnTick опрашивает рабочий символ, а не символ графика; UpdateMarketRegime требует монотонного роста time_msc. - R7-B6 — E4: обычный анализ принимает ТОЛЬКО допустимое экспериментальное
происхождение (по умолчанию
DEMO;SYNTHETIC— отдельный синтетический режим проверки отчёта, code 41);data_originпереносится во все производные файлы; конфигурация СТРОК сверяется с manifest серии (code 42); вsummary_rebuilt_e4.csvдобавлены показатели полноты (n_attempted/n_applicable/ отказы/пропуски/deadline) по сериям и pooled. - R7-S1 — применимость метрик: неустановленный исход без сделки — отдельная UNKNOWN-категория (не APPLICABLE/MISSING); доказанное отсутствие исполнения (CANCELED_NO_FILL/EXPIRED_NO_FILL/PENDING_DELETED) — NOT_APPLICABLE, а не «потеря callback»; CONFLICT/INTERRUPTED учитываются в summary ДО проверки has_value (конфликт без числа не засчитывается MISSING).
- R7-S2 — comparisons: delta = B−A и относительное изменение (B−A)/A для mean/median/p95 (ТЗ §7, стр.419); единая схема online и rebuild.
- R7-S3 — сохранность: cleanup-отправки тоже пишутся в intents.csv (INTENT до T0,
SEND_RETURN после T1); SEND_RETURN durable перенесён ВНЕ измеряемой фазы;
нечитаемость/повреждение durable-журнала даёт sentinel-неопределённость (не 0);
исчерпание протокола окон E3 — обязательная остановка
E3_WINDOW_CAPACITY_EXCEEDED. - R7-S4 — единая метка выхода обработчика для events и metadata (одно exit_us); переполнение реестра сделок блокирует дальнейшие отправки сразу (OnTransaction, CheckIntegrity code 68), а не только итоговой RUN-DEAL-02; RegisterHistoryDeal учитывает потери аналогично MarkDealAdd.
Регрессии: 97 проверок RequestLatencyTests (14 новых R7: DURA-01/02, WARM-02/03, T5-03, DL-05, READER-03/04, CMP-02, EVAL-08/09/10, QUOTE-01, E4-03). Компиляция 4 exe 0 errors/0 warnings (MetaEditor 6191 avx2). EOL CRLF.
2026-09-11 — этап 6 третьего аудита (fix audit-6)
Блокирующие расхождения R6 устранены (полное соответствие ТЗ проверяется демо-пилотом после контрольной сборки; основные серии 5x100 не запускать):
- R6-B1 — сквозная достоверность T5: вид сверки определяется ЯВНЫМ признаком
ConfirmationSnapshot.light_snapshot, а не числом сделок (световой снимок с count>0 и обнулёнными тикетами больше не бьёт по нулевым тикетам в SyncReconcile); первый реальный callback ПОСЛЕ history-регистрации учитывается ровно один раз (deal_count/callback_volume не теряются);RegisterHistoryDealдополняет уже известную callback-сделку историческими атрибутами без потери происхождения; history_volume наполняется только полным сканом; сверка полноты callback-меток выполняется и после установки T6 (CheckTriggered/OnTimer) без переписывания исхода/T6. - R6-B2 — единая аналитическая семантика online/offline: rebuild-путь
восстанавливает RequestMetadata и считает метрики той же
CRequestTracker::EvaluateMetric(все категории/применимость/срок), а не второй реализацией; WARMUP исключается одинаково; histogram/offset_signs/ comparisons/E4 используют ту же валидность; deadline-счётчики (n_deadline, denominator, n_timestamp_missing_at_deadline) идентичны онлайну;source_set_id/population/observation_unit одинаковы. - R6-B3 — своевременность знаковой T2-T4 по ОБЕИМ точкам: max(T2,T4)<=deadline
(поздняя T2 при ранней T4 — LATE, и наоборот);
SetFinalфиксируетdeadline_exceededпри поздней фактической T6 независимо от порядка callback и таймера (sticky); общий флаг не переносится в пригодность остальных метрик. - R6-B4 — планировщик:
MainComplete— по фактическим отправкам и терминальным состояниям слотов, а не high-watermark индекса (E3 не завершается при неотправленной второй ветви); блоки формируются ДО перемешивания (каждый из 10 блоков: 10A+10B, 5Buy+5Sell на ветвь); прогрев учитывается по фактическим отправкам (warmup-only жизненный цикл статусов, requeue/отказы), при систематическом отказе подготовки запуск завершается неполным статусом WARMUP_INSUFFICIENT_DATA. - R6-B5 — согласование CompletionPolicy/контроллер:
PENDING_DELETEDне подтверждается приhistory_scan_failed; доказанный исход без права установить T6 (UNEXPECTED_ACTIVATION) сохраняется черезRecordOutcome, а остаточная позиция закрывается адресно; определённый REJECT без ордера трактуется как известное состояние (нет экспозиции); cleanup UNKNOWN после grace завершается конечным BLOCKED, а не бесконечным DRAINING. - R6-B6 — сохранность: тяжёлый checkpoint выполняется ТОЛЬКО в безопасной фазе
(
CanCheckpoint: нет активной записи и cleanup), результат записи проверяется и при ошибке останавливает новые отправки (BLOCKED), маркерcheckpoint.markerпишется последним; добавлен устойчивый журнал намеренийintents.csv(INTENT до T0, SEND_RETURN после T1); INTENT без SEND_RETURN учитывается как неопределённая отправка в manifest (CountUncertainDurableIntents). - R6-B7 — E4: пять источников должны иметь manifest (отсутствие = отказ), run_status=FINISHED и n_main_dispatched>=квоты; нормализованная конфигурация (configuration_id) и символ равны МЕЖДУ всеми пятью сериями; каждая строка принадлежит сессии серии; ключи sequence уникальны внутри файла.
Существенные (R6): S1 — CSV-reader проверяет полный заголовок из 66 имён, числовые поля и уникальность sequence; S2 — монотонный возраст последнего наблюдённого обновления котировки (застой рынка TimeCurrent не обнаруживает); S3 — handler_exit_us и длительность снимаются ПОСЛЕ SetExitTime (включая поиск события журнала); S4 — переполнение реестра сделок — явный отказ со счётчиком потерь и проверкой RUN-DEAL-02.
Регрессии в RequestLatencyTests (TestAudit6Regressions): EVAL-05/06/07, DL-01..04, OFF-01/02, E3-02, BLOCK-01, WARM-01, PDEL-04, PEND-04, READER-01/02, E4-02.
2026-09-11 — этап 5 повторного аудита (fix audit-5)
Блокирующие расхождения R5 (полное соответствие ТЗ не подтверждено до контрольной сборки; торговые серии 5x100 не запускать):
- R5-B1 (P0) — автомат WARMUP->MAIN->CLEANUP->MAIN замкнут: EndMainCycle больше
не переводит в MAIN при
m_cleanup_in_flight(единственный владелец перехода — DriveCleanup после подтверждения нулевой остаточной экспозиции); прогрев строго последователен (одна операция в работе, пауза); закрытие collection для cleanup не зависит от наличия T6 (поздний REQUEST и grace закрывают коллекцию); раннее закрытие в CompletedCheck ждёт ВСЕ ожидаемые точки (T2 всегда, T3 для операций с ордерной точкой);ReturnToSchedule()выбирает WARMUP/MAIN по фазе расписания. - R5-B2 — финализация/журнал/запись: intent проверяется ДО OrderSend* (переполнение журнала -> BLOCKED, слот в очередь); FINISHED повторяет экспорт до первого успеха; штатное завершение переводит контроллер в FINISHED (manifest run_status=FINISHED) только без незавершённого cleanup; OnDeinit экспортирует журнал/записи; добавлен периодический checkpoint (60 с) samples/events вне callbacks.
- R5-B3 — категория LATE по фактическому концу метрики против
observation_deadline_us(online и offline одинаково): ранние T4 остаются VALID без T6; поздние T2/T6 — LATE независимо от порядка callbacks/таймера; флагdeadline_exceededостаётся информационным. - R5-B4 — раздельные признаки:
callback_coverage_complete(полнота локальных DEAL_ADD callbacks) иdeal_coverage_complete(торговый результат); T5-метрика использует callback-покрытие; сделки из истории регистрируются в реестр (deals.csv) с происхождением черезSyncRecoveredDeals; результаты каждой проверки переносятся в metadata (executed_volume/покрытия) — событийный full-fill больше не остаётся с нулевым executed_volume. - R5-B5 — RebuildReport: единая 41-колоночная схема summary_rebuilt (как онлайн); устранены дублирующиеся ключи (c-loop 0..1 + combined); контрольное чтение — от реально созданной таблицы (не константа 25); LoadSamples проверяет заголовок, полную схему (66 колонок) и ёмкость — повреждённый набор отвергается; n=1 допустим (stddev пуст).
- R5-B6 — E3: возраст признаков на ОДНОЙ календарной шкале (TimeCurrent vs
quote.time_msc; GetMicrosecondCount не смешивается), контроль устаревания якоря
после CopyTicksRange; режим/окно/calibration_id закрепляются за записью при
отправке (не при late callback); калибратор добирает >=5 сессий (ёмкость 20000),
не сохраняет невалидный набор (INSUFFICIENT_DATA), выгружает период и исходные
окна (
<id>_windows.csv); TryDispatchByRegime выбирает первую подходящую возможность нужной ветви (слот другой ветви не блокирует). - R5-B7 — RebuildE4: 5 РАЗНЫХ каталогов, уникальные source session_id, ровно
expected_mainMAIN B-ASYNC на серию (входInpE4ExpectedMainPerSeries), статус исходных запусков из manifest (INCOMPLETE/BLOCKED отвергаются), единый символ; warmup/PILOT/SYNTHETIC исключаются. - R5-B8 — CompletionPolicy: FILLED/EXPIRED не подтверждают удаление
(PENDING_DELETED только CANCELED+нет активного+0 объёма; FILLED с нулевым объёмом —
противоречивый снимок; EXPIRED — не команда отмены); PARTIAL_CANCELED/EXPIRED
подтверждаются по отсутствию активного остатка (исторический неисполненный объём
не смешивается с активным); pending-create требует точного
expected_order_type.
Существенные замечания R5-S1..S6:
- R5-S1 — универсальные построители расписания: малые чётные пилоты (per_condition=4/10/40) дают валидные слоты без планов-пустышек; нечётные/нулевые значения отвергаются в Init.
- R5-S2 — нулевые enum (ORDER_TYPE_BUY=0, ORDER_FILLING_FOK=0) пишутся как
0(признакactual_known); configuration_id переносится из Preflight в экспорт. - R5-S3 — первичный журнал фиксирует SEND_START/SEND_RETURN MAIN с фактическими данными (action/symbol/volume/type, retcode/request_id/order/deal).
- R5-S4 — CollectDealsByOrder с ограничением буфера и явным неполным исходом (truncated -> history_scan_failed), бюджет сканирования не выдаётся за полноту.
- R5-S5 — группы исходов ALL/SUCCESS/REJECTED; n=1 допустим в summary (stddev пуст).
- R5-S6 — handler_exit_us штампуется в конце FinalizeTransaction (длительность охватывает весь путь включая поиск записи журнала).
Регрессии в RequestLatencyTests.mq5: EVAL-01..04 (LATE по концу метрики), T5-01/02 (callback vs trade coverage), PDEL-02/03, PART-01, PEND-03, PILOT-01, ENUM-01, REBUILD-01 (сквозной tracker->samples->RebuildReport->73 строки), E4-01 (повтор каталога отвергается). Сборка MetaEditor 6182 avx2: 0/0 для всех 4 exe (RequestLatencyLab, RequestLatencyTests, LatencyReport, MarketCalibration).
2026-09-10 — этап 4 повторного аудита (fix audit-4)
Блокеры
- R4-B1: cleanup — в RequestPlan сохраняется полный фактический контракт (volume/type/filling/deviation/price-тикет/comment); потеря записи cleanup и неопределённое состояние DriveCleanup -> BLOCKED; остаточная экспозиция не разрешает следующий MAIN.
- R4-B2: событийная сверка — callback volume (лоты) конвертируется в units один раз на границе tracker/snapshot (CStateReader::LotsToUnits); regression UNITS-01..03.
- R4-B3: закрытие коллекции ждёт T2 (REQUEST) для всех операций; поздний REQUEST сохраняет метку после T6/закрытия; CORRELATION_LINK фиксирует deferred-привязку.
- R4-B4: MarketCalibration считает количество отдельных торговых сессий (уникальные даты валидных окон); generate->save->load->valid покрыт CAL-01/02.
- R4-B5: полные t.bid/t.ask (флаги не обнуляют вторую сторону); единое окно [anchor-60000, anchor-1]; anchor = quote.time_msc до T0; контроль возраста признаков (feature_max_age_ms); window/sequence/calibration/dataset трассировка.
- R4-B6: E4 — report-only workflow (LatencyReport InpE4Mode): ровно 5 E1 ASYNC datasets, проверка совместимости, pooled-статистика из 500 первичных записей + per-series таблица со ссылками на исходные session_id (без копирования samples).
- R4-B7: WAIT/precheck-reject возвращают слот в очередь (не расходуют квоту); DISPATCHED/квота E3 — только после фактического OrderSend/OrderSendAsync; недобор фактических send -> INSUFFICIENT_DATA (run_status=INCOMPLETE).
- R4-B8: samples.csv — пустые поля для отсутствующих значений; actual_type/actual_filling/request_price фактического запроса; SyncReconcile объёмов после полной сверки; T6 evidence (order state, объёмы, активный остаток, позиция); summary: исключение CLEANUP, outcome_group ALL/REJECTED, combined A+B, EvaluateMetric-семантика применимости; histogram без знаковой метрики; offset_signs.csv и comparisons.csv экспортируются; rebuilt-зеркало в ReportBuilder.
Существенные
- R4-S1: pending-delete — отсутствие активного ордера только при LAB_READ_ABSENT_CONFIRMED.
- R4-S2: pending-create — подтверждение размещения со сверкой symbol/type/magic/volume/price ожидаемого контракта.
- R4-S3: initial/remaining_volume_units в снапшоте конвертируются в units.
- R4-S4: handler exit фиксируется в журнале и для unresolved (seq==0).
- R4-S5: StartRun проверяет init journal/tracker/runner; экспорт fail-closed (read-back участвует в статусе, повторная попытка); run_status=INCOMPLETE при stop_reason.
Регрессии Tests (>50 проверок)
UNITS-01/02/03, COLL-03, CAL-01/02, VOLU-01, QUOTA-01/02, PEND-01/02, PDEL-01, CSV-03, HIST-02, CMP-01 (плюс предыдущие).
2026-09-10 — этап 3 повторного аудита (fix audit-3)
Устранение блокеров B1-B10 и существенных S1-S6 третьего аудита.
Блокеры (10)
- B1: cleanup переведён в полноценную запись tracker с role=CLEANUP: отдельный lifecycle (precheck -> reserve -> T0/T1 -> correlation -> T6 -> подтверждение нулевой экспозиции -> пауза -> следующий MAIN); DriveCleanup в OnTimer; однократный учёт dispatch; отказ/остаток -> BLOCKED (безопасность).
- B2: отложенная корреляция ранних ORDER_ADD/DEAL_ADD — буфер PushDeferred с исходной callback-меткой; ReconcileDeferred после появления точного моста заполняет T3/T4 исходными временами.
- B3: коллекция не закрывается до собранного ожидаемого REQUEST (T2) для market; поздний REQUEST после T6 не теряет T2-T4.
- B4: 4754 = «ордер не найден» -> ABSENT_CONFIRMED; 4756 и пр. остаются FAILED; no_active исключает FAILED; коды ошибок сохранены в snapshot.
- B5: событийная сверка адресная и короткая (light, объём из callback); полный История-скан вынесен в таймер/DriveCleanup.
- B6: проверка bool HistorySelect и HistoryDealsTotal; history_scan_budget вместо жёстких 100000; сбой выборки -> не «нет сделок».
- B7: однозначный финальный reject (IsFinalRejection) подключён к T6; неоднозн. TIMEOUT/CONNECTION/LOCKED/ERROR не превращаются в reject.
- B8: E4 запрещён для торгового runtime (PREFLIGHT/StartRun); reuse=1 в experiment_manifest (анализ 5 серий E1 без повторной торговли).
- B9: статусы PLANNED->INTENT_SAVED->DISPATCHED; PRECHECK_REJECTED/WAIT отдельно; счётчик фактических вызовов растёт только после OrderSend*; убран двойной MarkPrecheckRejected.
- B10: проверка результатов SaveUtf8 в ExportRun, EventSetMillisecondTimer, integrity-блок при потере журнала (records_lost -> BLOCKED).
Существенные (6)
- S1: фактическое deviation/comment из настроек в запросе; поля в RequestPlan.
- S2: рыночный контекст (bid/ask/spread/tick_time_msc) фиксируется при отправке и экспортируется в samples.csv (+ actual_type/filling/deviation/comment).
- S3: пустые статистики summary при n<2 (пустые вместо нулей/stddev=0).
- S4: LatencyReport повторно строит и histogram_rebuilt.csv; experiment_id и series_id заполняются из выборки.
- S5: калибровка E3 требует совпадения символа, >=5 отдельных торговых сессий (trading_session_count); MarketCalibration считает число сессий.
- S6: market cleanup заполняет type_filling/deviation и проходит PreCheck.
1.00 (черновик, 2026-09-08)
Первая рабочая структура кода RequestLatencyLab по ТЗ (черновик).
Добавлено
- Основной советник
RequestLatencyLab.mq5с автоматом IDLE→PREFLIGHT→READY→WARMUP→MAIN→DRAINING→EXPORTING→FINISHED и режимами LOCAL_ONLY / PENDING_CREATE_DELETE / MARKET_ORDER. - Модули
Include/RequestLatencyLab/*: Models, Configuration, TimeSource, Statistics, EventJournal, MarketRegime, StateReader, CompletionPolicy, RequestTracker, ExperimentRunner, CsvStorage, ReportBuilder, LatencyPanel, AppController. - Legacy-модули (адаптация статьи 1):
Legacy/BenchmarkStatistics.mqh,Legacy/TradeRequestTools.mqh,Legacy/LifecycleAdapter.mqh. - Исходники статьи 1 (SHA-256 совпадают с ТЗ) используются по ссылке из
соседнего каталога
mql5-execution-microstructure; каталогDependenciesисключён (снимки не копируются). - Скрипты:
MarketCalibration.mq5,LatencyReport.mq5. - Автотесты:
Tests/RequestLatencyTests.mq5(LOCAL_ONLY, пишет checks.csv). - Документация: README, CHANGELOG, CSV_SCHEMA, Docs/DependencyChanges, Docs/RequestLatencyLab_TZ_RU.md, dependencies.lock.json.
Ключевые решения
LatencySampleсохранена без изменений (10 редакторских полей, порядок/типы неизменны).- T0–T6 по
GetMicrosecondCount; только REQUEST задаётretcodeструктуры; код RETURN хранится вsend_retcode. - Единый последовательный протокол: один запрос в работе, пауза ≥1000 мс, резервный таймер 20 мс, сроки [T0, T0+5000 мс] / +1000 мс.
- Севдофиксация конфигурации через
configuration_id(без дат и случайности). - Park–Miller (seed) + Fisher–Yates; прогрев на отдельном состоянии PRNG.
Известные ограничения (следующие шаги)
- CLEANUP-записи в live-цикле журналируются событиями и счётчиком; полная отдельная LatencySample-строка для CLEANUP — предмет пилота (ДЕМО).
- Реглом-гейтинг E3 (
TryDispatchByRegime) реализован, но приоритетный диспетчер MAIN использует последовательные слоты; E3-сбор подтверждается пилотом. - Проверки, требующие DEMO_PILOT / AFTER_PUBLICATION — NOT_RUN до проведения.
- Публикация на MQL5 Forge не выполнялась (см. Docs/RequestLatencyLab_TZ_RU.md §10). Сборка зависит от абсолютного пути к соседнему каталогу mql5-execution-microstructure.
2026-09-10 — повторный аудит (fix audit-2)
- B1: детерминированный HistorySelect перед CollectDealsByOrder (StateReader).
- B2: неизвестный REQUEST больше не получает fallback-привязку (0 + unresolved).
- B3: collection_closed реально управляет cleanup: разделение T6 и закрытия, grace-период.
- B4: событийная адресная сверка T6 в OnTransaction (HISTORY_ADD/ORDER_DELETE/DEAL_ADD); таймер - watchdog.
- S5: E3 формально завершается INSUFFICIENT_DATA (лимит окна кампании InpE3CampaignLimitMin).
- S6: preflight проверяет чистоту символа (позиции/ордера).
- S7: привязка позиции через trans.position/DEAL_POSITION_ID вместо PositionGetTicket(0).
- S8: RUN-T6-01 проверяет completed=>T6; отсутствие T6 у incomplete не ошибка.
- S9: регрессии CORR-09, COLL-01/02, POS-01, UNRES-01; CORR-07 обновлён.