Слово владельца, 2026-08-24: «давай поднимем принципы из ФИЛОСОФИИ на уровень молитвы перед началом любой работы… с просьбой тебя молитву озвучить перед каждой работой». Каденция уточнена владельцем 2026-08-28 (интервью 017, Q2 = B).
🔴 АГЕНТ: ПРОИЗНЕСИ ЕЁ В ЧАТЕ ЦЕЛИКОМ ОДИН РАЗ НА СЕССИЮ — при входе (
/resume, вход в цикл), дословно, пунктов не пропуская. ПЕРЕД КАЖДОЙ СЛЕДУЮЩЕЙ ЗАДАЧЕЙ — ОДНА СТРОКА: ТРИ принципа из шестнадцати, самых важных для этой задачи, своим выбором. Это не украшение: каждый пункт оплачен провалом; полный текст раз в сессию переносит его в решения дня, а выбор трёх под задачу — применение, а не декламация. Разбор каждого принципа —PHILOSOPHY.md.
- ПРОСТОТА ВЫШЕ ВСЕГО. Если долго — значит я усложнил, а не задача трудна. Застрял — заново понять задачу, а не громоздить.
- ОККАМ. Не умножаю сущностей. Из двух решений беру то, где меньше движущихся частей.
- ПАРЕТО. Ищу те 20 %, что дают 80 % пользы. «Сделано и работает» лучше «идеально и поздно».
- КОД ПРЕЖДЕ КОГНИЦИИ. Что может сделать скрипт — делает скрипт. Модели остаётся суждение.
- НАБЛЮДЕНИЕ ВМЕСТО ДОГАДКИ. Не помню — смотрю. Прогон, замер, источник вместо «должно работать».
- ТРИ ДВЕРИ. Пробел закрываю источником или вопросом владельцу. Выдумать — запрещено.
- ЛОШАДИ, А НЕ ЗЕБРЫ. Сперва проверяю самое простое и частое объяснение.
- МЁРФИ. Называю риски вслух и раскладываю по ярусам. Названный риск наполовину управляем.
- ЛУЧШИЕ ПРАКТИКИ. Почти всё решено до меня. Ищу проверенный путь, прежде чем изобретать.
- DRY. Один факт живёт в одном месте. Пару лучше УБРАТЬ, чем за ней следить.
- УЧУСЬ ОДИН РАЗ. Сверяюсь с опытом до работы, дописываю урок после. Дважды в один тупик не хожу.
- ЭЙЗЕНХАУЭР. Важное и срочное — сейчас; важное и не срочное — в план; прочее — вниз.
- БРИТВА ХЭНЛОНА. Не злой умысел, а недосмотр. Отлаживаю состояние мира, а не мотивы.
- КВАДРАТ ДЕКАРТА. На трудной развилке отвечаю на четыре вопроса, а не на два.
- ВТОРОЙ ПОРЯДОК. Думаю на три-пять ходов вперёд, а не о выигрыше прямо сейчас.
- КАРМА. Оставляю репозиторий лучше, чем взял. Не срезаю углы за счёт владельца и следующей сессии.
⚖️ И ОДНА ГРАНИЦА, ЧТОБЫ МОЛИТВА НЕ СТАЛА ОРУЖИЕМ ПРОТИВ ВЛАДЕЛЬЦА: Оккам и Парето действуют ВНУТРИ машинерии. На том, что владелец видит и слышит, агент не экономит — там судит его глаз, а не мой счёт сущностей.
Who depends on whom, and what breaks what. Read this before editing code, to know the blast radius. The layout of the tree is in
PROJECT_STRUCTURE_EXTERNAL_MAP.md.Living reference — never
DONE-tagged. Updated: 2026-08-22 20:5x +03:00 (R14d, the tag cloud).The caveat this header used to carry — «the orchestrator is designed, not yet written» — was FALSE for two weeks and is removed. It was written on 2026-08-09 and left standing while rules R14–R18 accumulated beneath it dated 2026-08-15…22 and the orchestrator grew past thirty modules: the body was maintained, the header lied about it. Found by the 2026-08-21 audit and filed as
bugs/25. The rules below describe machinery that RUNS, and each says what proved it.
engine.mjs ── the only module that decides
│
┌────────────────┼─────────────────┬──────────────────┐
▼ ▼ ▼ ▼
profile-manager stress-tester hardware-mon event-logger
(WRITES) (verdict) (telemetry) (fault detection)
│ │
┌────┴────┐ │
▼ ▼ Windows Event Log
nvidia-smi nvapi ← swappable backends (TDR/WHEA/BSOD)
backend backend
config.mjs ← read by everyone, depends on nothing
setup-desktop.mjs and desktop-shortcuts.mjs sit outside this loop: they consume finished
profiles and build the owner-facing surface. They never search and never test.
| # | Rule | Why it exists |
|---|---|---|
| R1 | profile-manager.mjs is the only module that writes to the GPU. |
One writer means one place to audit, and one place that owns rollback. |
| R2 | profile-manager.mjs is an interface; backends are swappable. |
Phase 2 ships nvidia-smi, phase 4 ships the NVAPI bridge, green-curve is the fallback. The owner's PDF hard-wires MSI Afterburner here — GOAL.md forbids it (researches/01). |
| R3 | config.mjs depends on nothing and holds every safety number. |
Voltages, step sizes, temperature ceilings and guardbands are safety parameters, not literals scattered through call sites. |
| R4 | A stability verdict needs THREE observations: the checksum, the event log, AND the throughput. | Crash detection alone misses silent data corruption, the majority failure mode (researches/02). The third was added 2026-08-10 from researches/04, and it closes a genuine blind spot: clock stretching (the card skips work while still REPORTING the locked clock) and memory error replay (GDDR7 carries internal ECC + CRC, so failed transfers are corrected or retried) both produce a CORRECT checksum and NO event. A profile suffering either would have been stamped PASS. The only observable is work-per-second against a stock reference — the same number that serves as the price in the owner's «снижаем, пока цена ≤ N» formula. |
| R4a-pulse | ЧЕТВЁРТОЕ НАБЛЮДЕНИЕ: пульс сэмплера — и ЛАГ ТЕЛЕМЕТРИИ ЕСТЬ ОТКАЗ, слово владельца. | Три наблюдения R4 смотрят на НАШУ работу (сумма, журнал событий, работа в секунду), и ни одно не смотрит на СИСТЕМУ. Край этой карты не портит числа — он душит систему (факт 39: 584 прожига, 0 SDC, 0 CRASH). Сэмплер телеметрии — ОТДЕЛЬНЫЙ процесс, не заблокированный прожигом: когда он теряет такт, встала система. Замерено 2026-08-23 на 2797 МГц: три безопасные ступени дают 0,11-0,13 с сверх обещания, последняя перед смертью машины — 4,49 с, и оракул на всех четырёх сказал PASS. ДЕЙСТВУЮЩЕЕ ПРАВИЛО (владелец, 2026-08-26, GOAL.md → «🛑 ЛАГ ТЕЛЕМЕТРИИ — ЭТО ОТКАЗ»): ступень с потерянным тактом закрывается ОТКАЗОМ — прибор РАЗЛИЧАЕТ без порога (фон 1008…1053 мс, предвестники 3042/4490 — между ними пусто). bugs/62): довод про n = 1 верен для выбора ТОЧНОГО порога и был подставлен как ответ про способность различать. Остановку полосы в реальном времени с 28.08 несёт предохранитель (эпик 51, судья-deadman N=60 мс → stopWhen). Проводка пульса в ВЕРДИКТ ступени СТОИТ с 2026-08-29 (bugs/61 DONE): runRung читает окно файла сэмплера после прожига (hardware-mon.maxSampleGapMs), зазор > config.PULSE_STALL_MS (2130 мс, правило «2 × максимум фона» по полному архиву — фон ≤ 1065, смерти 3042/3366) = вердикт ЗАВИС исходом hung; пол зависания и тормоз «двух подряд» видят его без правок, прибор без данных молчит (R4b). Доказано на закоммиченных записях обоих смертельных прогонов (benches/fixtures/pulse-windows/), мутации DA/DB/DD. Прибор — npm run pulse (plans/27). |
| R4b-signal | ПЯТЫЙ ВХОД: собственный канал ошибок драйвера (nvlddmkm) ГОЛОСУЕТ — серия его событий ПРЕКРАЩАЕТ СТУПЕНЬ (с 2026-08-31, bugs/79). researches/30: порог — два и более события в скользящем окне 120 с, форма взята у самой Windows (TdrLimitCount/TdrLimitTime — счёт в окне), ЧИСЛА свои (порог Microsoft 5 за 60 с не сработал бы на инциденте 30.08: там было три события за пять секунд). Реакция — СТУПЕНЬ, а не полоса: по снятому архиву (179 событий за 41 день, 21 вспышка) правило ловит 6 смертельных вспышек из 6 и молчит на всех 9 одиночках, но и 6 безобидных серий попадают под него — как остановка полосы это дало бы две ложные остановки за семь дней прогонов, как прекращение ступени даёт НОЛЬ (запись едет в накопитель bugs/80, решает накопление). ДВА ЯРУСА, ОДНО ПРАВИЛО (driver-voice.mjs): ярус 1 — граница ступени (runRung.driverEventsFn), работает всегда; ярус 2 — наблюдатель реального времени на EventLogWatcher, поднимается флагом --driver-voice-watch и убивает прожиг, задержка доставки 291/302/284 мс тремя замерами. 🔴 ЧЕСТНАЯ ГРАНИЦА: голос успевает не всегда — из четырёх смертей эпохи журнала развёртки вовремя в двух; 30 августа между первым криком драйвера и последней fsync-нутой пробой сэмплера было 0,134 с, и знак у этого окна отрицательный. Прежний класс means: 'SIGNAL' в config.FAULT_PROVIDERS НЕ ТРОНУТ — classifyEvent по-прежнему возвращает fault: false, и оба старых потребителя (stress-tester, graphics-load) канала не видят; голос берёт события ОТДЕЛЬНЫМ швом. |
Добавлено 2026-08-23 с plans/29. Второе наблюдение R4 («журнал Windows») было слепо ровно к тому каналу, по которому эта карта жалуется: Display даёт 4107 и ни одного 4101, WHEA-Logger пуст за всю историю, а nvlddmkm накопил 129 событий за 34 дня, две из них ВНУТРИ ступени, убившей машину, каждая за секунды до провала пульса (researches/15 §0). Но объявить его детектором запрещает разбор ВСЕХ двенадцати смертей: сигнал специфичен и НЕ чувствителен — канонический BSOD факта 39 не дал ни одной жалобы за двое суток, а одиночные срабатывания на тихих днях дали бы ложные стопы, которые ideas/10 §5.5 запрещает отгружать вовсе. Поэтому у config.FAULT_PROVIDERS появился ВТОРОЙ КЛАСС: means: 'CRASH' голосует через verdictFor, means: 'SIGNAL' читается, едет к вызывающему и печатается отдельным разделом. classifyEvent возвращает fault строго false для сигнала — поэтому оба существующих потребителя (stress-tester, graphics-load) не видят его даже случайно: они фильтруют по fault и читают только verdictFor. Различие держится не комментарием, а четырьмя блоками runClassInvariants на построенных данных, мутационно доказанными тремя способами. Пустой список ids означает «весь провайдер» на ОБЕИХ сторонах — запрос к Windows понимал это всегда, не соглашался только классификатор; список идентификаторов и есть механизм, которым проект ослеп в первый раз. Ворота превращения в вердикт — те же, что у R4a-pulse, и данных для них пока нет. |
| R4a | A read-back proves what was COMMANDED, never what was DELIVERED. | clocks.gr sitting on the locked point is evidence the command took (EXP-0014) — it is not evidence the card is doing that much work, precisely because of clock stretching. Anything claiming delivered performance must measure throughput. |
| R4c-progress | ШЕСТОЙ ВХОД: ПРОГРЕСС СОБСТВЕННОЙ РАБОТЫ — второе наблюдение предохранителя, проведено 2026-08-29 (plans/66, разведка researches/24). |
Вход 1 судьи-deadman смотрит на ЖИВОСТЬ системы (удары пробы, N = 60 мс). Вход 2 смотрит на ДРУГОЕ: отгружает ли карта нашу работу. Судья умел его с фазы 2 эпика 51 (armMMs, причина progress-stall, сторож progressWired: «источника нет» ≠ «застыл»), но кормить было нечем. Источник нашёлся там, где не искали: цикл --sustain прожига — ХОСТОВЫЙ (furnace.cu §311–347), и после cudaEventSynchronize + memcpy + сверки с эталоном хост ТОЧНО знает, что запуск отгружен. Отображённая память и чтение прогресса из работающего ядра не понадобились вовсе. Дорога: прожиг трогает файл сердцебиения раз в запуск (--progress-file, без флага — ни одного системного вызова) → проба читает его подвыборкой (PROGRESS_POLL_MS = 50 мс) и шлёт судье удар 0x02 → судья решает. Судья диска НЕ КАСАЕТСЯ — у него одна дверь, память и датаграммы (слово владельца «НЕ ДИСК РАЗ В СЕКУНДУ»). Порог M выводится ИЗ ФОРМЫ, а не константой: такт запуска различается в 400 раз (sdc_fma 0,80 · branchy 81,89 · furnace 330,68 мс — максимум двух независимых источников), множитель k = 3 взят у drm/i915 («timeout не ближе трёх тактов сердцебиения»), отсюда M = 993 · 246 · 3 мс. sdc_fma НЕ ВЗВОДИТСЯ ВОВСЕ и говорит почему (armMDecision): его порог мельче трёх тактов наблюдения — форма быстрее, чем файловая дорога способна разглядеть, и порог краснел бы на собственной дороге, а не на отказе карты (класс EXP-0165). Это РЕШЕНИЕ с причиной, не заявление о невозможности (EXP-0169). BURST_TIMEOUT_FLOOR_MS, единственное, что стояло на этой дороге, — ноль срабатываний за 1614 строк журнала) → ≈1000 мс. Репетиция end-to-end на двойнике: --rehearse-death progress-stall. Приоритет причин задан в judgeLiveness: beat-silence побеждает как более конкретный факт о карте. 🔴 ПОПРАВКА 2026-09-04 (сессия 81, bugs/101 находка 3): «проведено» здесь верно про ДВОЙНИК и про блоки — на ЖИВОМ пути развёртки вход 2 НЕ ПРОВЕДЁН. engine.mjs:11234 поднимает пробу без --progress-file, судья — без --arm-m, прожиг — без флага (runBurst), и в протоколе живости прогона 04.09 worstProgressSilenceMs = null во всех строках. Ядро ступени 2737 МГц / 820 мВ висело 165 с под 20 криками драйвера, и кончил его таймаут 60 000 мс — ровно та дорога, которую этот вход обещал заменить на ≈1000 мс. Класс ворот 6a («двигатель не на ракете»). Три точки проводки и порядок перепроверки (determinism прожига с флагом → двойник → блок на спаун без флага) — bugs/101, план починки, шаг 1. 🟢 ПРОВЕДЕНО НА ЖИВОЙ ПУТЬ 2026-09-04 (сессия 82, офлайн; bugs/101 находка 3, план с поправкой): прожиг (runBurst → --progress-file ВНЕ args, лицензия --sustain), проба (--progress-file), судья (--arm-m + --progress-file) — одной формой с двойником (fuse.progressRiderArgs → engine.liveFuseRiders, twin.riders); файл runs/death-watch/<штамп>-burn-progress.txt, тем же штампом, что протокол защиты. Уставка следует за НИЖНЕЙ частотой полосы (fuse.PROGRESS_TICK_REF_MHZ, armMDecision('furnace', { lowestMhz })): такт запуска обратен частоте — измерено в архиве на branchy (25,9 → 81,9 мс от 2797 к 900 МГц), а максимум furnace снят при 2820 МГц (все семь прогонов — 2805…2872 МГц), так что 993 мс на полосе до 900 МГц красили бы самые медленные здоровые запуски; полоса до 2692 → 1040 мс, до 900 → 3109 мс, при 2842 и выше — прежние 993. --progress-observe — наблюдение без трипа (калибровка такта на настоящей полосе). Блоки: fuse +5 · stress-tester +2 · vf-step +3 · engine +5; четыре мутации покрасили ровно свои блоки. Живого свидетеля нет (ворота 6a): первый прогон при владельце с 08.09, перед ним workloads:build с флагом (distinct=1); режим первого прогона — interviews/026 Q3. |
| R5 | Every write has its rollback in the same module. | A function that changes hardware and cannot undo itself does not ship. |
| R6 | Profiles carry the driver and VBIOS they were proved on. | A driver update can silently change voltage behaviour — it did in 595.71. A profile whose stamp no longer matches is invalid until re-validated. |
| R7 | Telemetry comes from nvidia-smi alone; no GUI monitoring app is ever a source. |
GOAL.md forbids a third-party GUI dependency, and the sensor HWiNFO64 was there for (hotspot / memory junction) is disabled at driver level on RTX 50 — this card returns N/A (researches/03 §3.5). |
| R9 | A GPU write that can take the display down is made only under an ARMED WATCHDOG. | Asked for by the owner (2026-08-10) before the first positive offset. Every rollback KAGO had was a finally, and a finally is worth exactly as much as the process running it: a hung, killed or driver-blocked process runs none. watchdog.mjs writes an armed record and spawns a SEPARATE detached process that returns the card to factory on a deadline or on the writer's death — proved live, 2.5 s from an abrupt death to a restored card. It introduces NO new writer (it calls profile-manager.resetToFactory, nvapi.writeVfOffset and nvapi.resetFansToAuto), so R1 is untouched: this module decides WHEN, never HOW. Its undo is TOTAL, not differential — after a crash nobody knows what was applied, so the only honest undo is "return to factory", which is idempotent and cannot be wrong. |
| R9a | The total undo covers every kind of state the project can write — and a new writable state EXTENDS the undo before its first write exists. | Added 2026-08-10 with fan control. The undo had three steps (curve offsets, NVML domain offsets, clocks + power limit) and the fans would have been a fourth kind of state with nothing to restore it: a writer that died holding MANUAL left the fans pinned, and this card's own manual floor is 30 %, so "pinned" means the owner's idle machine audibly changes with no path back. The order is the rule — the net before the jump: the undo learned fans, mutation-proved (the mutation that KEEPS the step but makes it pin a level instead of restoring AUTO reddens that block alone), and only then was the first fan write run. Corollary for the selftest: the undo's steps are asserted BY NAME, never by a count — a count-only check stays green when a step is deleted and another duplicated. |
| R10 | THREE OF THE FOUR ROLLBACK LAYERS REQUIRE A LIVE OPERATING SYSTEM — so at depth, STEP SIZE is the only protection, and it acts BEFORE the state exists. | Paid for on 2026-08-11: a band sweep applied a deep whole-curve undervolt at a pinned 1100 MHz, and the machine hung for ~5 h 40 min. The writer's finally never ran (its process was never scheduled again), the detached watchdog never ran (a guard needs the OS too), Windows TDR did not fire (the hang was harder than a display timeout). What restored the card was the FOURTH layer — volatility plus the owner's reboot. The generalisation, and it is not about GPUs: every undo this project owns is conditional on the machine surviving, and that condition is invisible until the day it fails. Consequences now in code: engine.pickAscentRungs() refuses a first step deeper than config.ASCENT_FIRST_STEP_MAX_MV and a step-to-step jump beyond ASCENT_STEP_MAX_MV, and it refuses BEFORE the first write (proved by a block that counts writes and a mutation that removes the pre-write check). Consequence in process: an unattended sweep is never run on machinery that has not completed one full attended run. Full record: bugs/03, EXP-0039. |
| R10a | A rollback with more than one duty is a LIST, never a chain. | Same incident, second face. The atom's finally held five duties in sequence — prove the pin, release the clock, zero the curve, disarm the watchdog, unload the driver — so the first throw cancelled everything behind it, and a ReferenceError on its first line did exactly that. Two of those duties sat outside every try, so a failed curve-zeroing would have left the watchdog ARMED, firing later on a card nobody was holding. vf-step.runUndo() now runs each duty in its own try; a throw becomes a red block, never an exit. Order expresses PREFERENCE (a read that needs the state precedes the release that destroys it), not dependency. 16 offline blocks, three mutations. EXP-0040. EXTENDED 2026-08-15 with plans/15 §4.3: every block runUndo emits carries undo: true, and a CALLER may not report work as successful while one of them is red. The sweep's rung is the first such caller — a rung whose rollback failed is reported unknown (a STOP), because the next rung would arm a watchdog and write to a card whose state nobody can describe, which is exactly what watchdog --recover exists to refuse building on. The field, not the block's NAME, is what callers test: a name match would be a truth↔mirror pair created deliberately and would go silent the first time a block is reworded. |
| R11 | A CEILING MUST BE HELD BY SOMETHING, AND THE RUN NAMES BY WHAT — the curve, the clock pin, or a refusal. | Added 2026-08-14 with bugs/02 step 1. A frequency ceiling is enforced by pushing the points above it DOWN, and that push is an offset bounded by the hardware's ±1000 MHz — so the curve cannot hold any cap below topMhz − 1000 (measured live: top 3157 → floor 2157 MHz). Silent Cold was designed at 2100, i.e. 57 MHz under that floor, and nothing in the stack would have said so: the profile applies cleanly and every read-back matches, the card simply reaches a clock the mode forbade. So buildRaiseAndCapVector now returns capEnforced / capLeakMhz / lowestEnforceableCapMhz, vf-step.chooseWriteShape turns them into the holder decision, and a run with NO holder REFUSES before writing. Corollary for the evidence: the ratchet record carries writeShape and capHeldBy as required-present fields — every record of the search that produced bugs/02 was well-formed and useless for catching it, because none of them said what had been written. |
| R12 | A PROPERTY THAT WAS A PROOF UNDER THE OLD SHAPE IS MEASURED UNDER THE NEW ONE — NEVER INHERITED. | Added 2026-08-15 with the profile's raise becoming a VECTOR (plans/12). Under a uniform raise the resulting curve min(F_i + Δ, F_top) cannot be non-monotone: that is a proof about the formula, and it is why nothing in the stack ever looked. A per-point vector removes the formula and with it the proof — raise point i more than point i+1 and a LOWER-voltage point offers a HIGHER frequency than its neighbour. The card has never been given such a curve and this project has not observed what it does with one, so buildRaiseAndCapVector now COMPUTES the order (monotone, firstInversionAt) and profile-manager REFUSES before the device write, naming the two points. The refusal is on introducesInversion, not on monotone — an inversion the card's factory curve already carries is not ours, and refusing on it would block writes that work today, i.e. a guard causing the regression it exists to prevent. The generalisation beyond curves: when a shape changes, walk the properties the OLD shape guaranteed and ask which are still proofs. A property silently demoted from proof to assumption is invisible — nothing fails, no test reddens, and the first evidence is on the owner's machine. |
| R13 | NEVER DRIVE THE CARD ABOVE THE CLOCK THE SPECIMEN ITSELF REPORTS — and judge what WE lifted, never what the factory table already offered. | The owner's rule, verbatim (GOAL.md → «⭐ ЧТО ТАКОЕ ТЮНИНГ VF-КРИВОЙ», 2026-08-15): «НИКОГДА НЕ ГНАТЬ КАРТУ ВЫШЕ ЭТОЙ ЧАСТОТЫ». Paid for by bugs/11: a raise proven only under a 2842 MHz ceiling was applied with the ceiling removed, the card was offered 3180 MHz, and Windows bugchecked in nvlddmkm.sys two minutes later on an idle desktop. Three numbers must not be confused, and all three were on screen at the time: the reference spec (2452 MHz — a FLOOR for this specimen), the specimen's own maximum (clocks.max.graphics = 3090, asked of the card, never remembered), and the V/F table's top entry (3172 here). The bound is REQUIRED, not defaulted: writeRaiseAndCap refuses when no maximum is passed, because a write whose ceiling is unknown is exactly what this guard exists to stop. And the judged quantity is highestRaisedOfferMhz, not highestOfferedMhz — this card's FACTORY table tops at 3172, i.e. above its own maximum, so a guard reading the whole curve's top would refuse a vector of all zeroes: a guard causing the regression it exists to prevent (the same trap R12 names, and the first version of this check fell into it — caught by running it against the live card, not by reading it). 6 blocks in profile --selftest, mutation-proved four ways, each reddening this block alone. EXTENDED 2026-09-01 with the owner's answer (interviews/025 Q1 = A · Q2 = A) — R13 GAINED ITS SECOND HALF, and the first half turned out to be only a MOMENT. A judge that speaks at write time cannot hold an invariant whose subject moves: offsets are written ABSOLUTELY, the card offers «factory table OF THE MOMENT + offset», and that table slides with temperature (R14b). Measured that morning: a write that was legally inside the envelope had three points offering 3097 MHz against a maximum of 3090 minutes later, after the card cooled — no clamp computed at write time can prevent that. So the rule now has TWO holders, both required: (a) the arithmetic bounds the raise at write time (buildRaiseAndCapVector's envelopeMhz, and it is gated by intentTopMhz — see below), and (b) a clock BOUND on the card (-lgc <ladder floor, card max>) makes «never above» continuous. The gate on (a) is the part paid for: the first version clamped ANY over-envelope raise and thereby DISARMED this very guard — the bugs/11 bomb (+592 with no cap) stopped being refused and started quietly landing at the card's limit, and the block above went red saying so. Clamping is therefore permitted ONLY when the vector's stated INTENT (its top raised offer against the basis it was computed for) is itself inside the envelope; an unstated intent, or one above the envelope, gets the refusal it always got. The distinction is structural rather than a magnitude threshold, because a threshold would be the agent's number and this owner has rejected agent-chosen thresholds (bugs/73). The BOUND is not a PIN (GPU_TUNING_RAILS.md §3): min < max keeps the card free downward, which is what the owner's own definition of tuning demands, and a shipped mode carrying min == max is caught by its own block in profile-store --selftest. The bound's mechanism was MEASURED on this card the same hour rather than trusted to the vendor's help text (fact 38 had it as «read, not measured»): a bound of 180…1500 MHz under a burn held 1492…1500 with zero samples above it, while the same burn sits at ~2887 MHz unbounded. Full record: bugs/99, plans/83. |
| R14 | curve-store.mjs IS THE TUNING CURVE DOCUMENT'S ONLY AUTHOR, THE DOCUMENT IS KEYED BY FREQUENCY, AND offsetMhz IS DERIVED ON LOAD — NEVER READ FROM THE FILE. |
Added 2026-08-15 with epic 02 phase 1 (plans/14). Three parts, each paid for. (a) One author: the document is the sweep's entire memory, so a second writer would be a second truth about what the silicon proved — the same shape R1 forbids for the card itself. Every save goes through writeJsonAtomic (temp + rename in the SAME directory; a cross-volume rename is a copy and a copy is not atomic), because the owner settled that a hang is a NORMAL event during the search (GOAL.md → «GOAL.md → «🔤 ТОЧЕК С НОМЕРАМИ НЕ СУЩЕСТВУЕТ») and, independently, the fix for EXP-0053/EXP-0068: the factory table slides along the FREQUENCY axis with temperature (≈ −1.7 MHz/°C) while the voltage axis stands still, so an index is a name and not an identity. «Frequency → serving voltage» does not move; the per-entry offsets the hardware wants DO, and they are computed at apply time from a live reading. (c) offsetMhz derived on load: a file carrying both a frequency and its offset records one fact twice, which is a pair to watch — recomputing makes the pair impossible instead. The status vocabulary is CLOSED (CURVE_STATUS, frozen); an unknown status is refused by name, and lever-limited exists specifically so a lever wall can never be reported as an edge. 40 blocks in curve --selftest; the R13 ceiling, the status vocabulary, the atomic save and the voltage-grid check were each re-proved by an independent judge mutation on 2026-08-15 21:2x, every one reddening its own block alone and the intact code reddening none. |
| R15 | THE SWEEP'S MEMORY IS A WRITE-AHEAD JOURNAL, THE INTENT IS fsynced BEFORE THE CARD IS TOUCHED, AND A HANG IS DERIVED FROM AN INTENT NOBODY CLOSED. |
Added 2026-08-15 with plans/15 §4.4, and it exists because the owner made a hang a NORMAL path rather than an accident (GOAL.md → «bugs/07 is what that costs when it is missing: the store's last word was the PASS of the rung BEFORE the fatal one, and the next session would have walked straight back onto it. Three parts. (a) Durability is the point, not the append: writeFileSync(…, 'a') returns when the data reaches the OS page cache, and a hang takes that cache with it — so the sequence is open → write → fsync → close, and the fs seam is injected because ORDER (intent before the card) is provable only by recording the calls. (b) The hang is DERIVED, never reported: config.VERDICT.HUNG (ЗАВИС, first-class beside SDC/CRASH by the owner's word) is the one verdict no oracle returns; the next launch reads an intent with no verdict and closes it. The closure is APPENDED rather than re-inferred each time — that is what makes «two in a row» countable at all. (c) Keyed by FREQUENCY + VOLTAGE, never a table index — the same reason as R14b: the factory table slides along the frequency axis with temperature while the voltage axis stands still. The one emergency stop the owner left is two CONSECUTIVE hangs on one rung; cumulative counting would delete a probabilistic edge, which this card has already shown (fact 28). Enforced where the card is touched (engine.runRung), from a set the caller computes once — within one process a rung can hang at most once, because the hang ends the process. 17 blocks in journal --selftest + 7 wiring blocks in engine --selftest; mutations 40, 42–48. |
| R16 | THE SWEEP IS A COMPOSER, THE DOCUMENT HAS ONE AUTHOR, AND THE PLAN IS THE RUN'S OWN COMPUTATION. | Added 2026-08-16 with plans/15 §4.5 and §4.7. Three parts, each paid for. (a) engine.sweepRange decides and composes; it never writes — the card is touched only through vf-step.runStep (R1), the document only through curve-store.closePoint (R14a). A sweep that grew its own writer would be a second truth about what the silicon proved, which is the shape R1 and R14a both forbid. (b) A rung is burned at its group's HIGHEST frequency and the result is inherited DOWNWARD. The card offers 127 voltage rungs for 389 frequencies, so neighbours share a voltage by construction; the direction is what makes inheritance safe rather than convenient — Vmin does not decrease with frequency, so a voltage PROVEN at a higher frequency is not optimistic at a lower one (E2-AC3: «not interpolation, the same measured fact»). The grouping key is the STOCK serving voltage, because the tuned one is the answer being searched for. A mutation burning the group's LOWEST frequency reddened NOTHING at first — the document came out identical — and the cause was a truth↔mirror pair created by accident INSIDE one function: two places named the rung's frequency. Collapsed to one; the block now asserts WHICH frequencies were burned (EXP-0077). (c) The dry run and the run are ONE computation (planFrequency), not two kept in agreement. bugs/09 is what two cost: the plan advertised −250 mV while the run stopped at −30, and that plan is the artifact rail S2 makes the operator read BEFORE writing to the owner's card — so a plan that lies launders a guess into an authorization. A pair that can be REMOVED beats a pair that must be watched. |
| R17 | AN INVERSION IS A CONTRADICTION BETWEEN TWO MEASUREMENTS — A ROW AT ITS FACTORY VALUE IS NOT ONE. | Added 2026-08-16, and it is a CORRECTION of curve-store.firstInversion rather than a new rule. The guard was written for a FINISHED document, where every row carries a measurement; a sweep walks top-down, so between the frequency it just closed and the ones it has not reached there is ALWAYS an apparent inversion — the closed row dropped to its measured voltage while its lower neighbours still hold the higher factory value. The guard therefore reddened on the NORMAL operating state of the machinery it protects and stopped the sweep at its first write: a guard causing the very regression it exists to prevent, the trap R12 and R13 both name and which R13's own first version fell into. Narrowed to measurements only; a finished document has no unmeasured rows, so nothing it could catch before is lost, and a contradiction ACROSS an unmeasured gap is still caught by its own block. The half that was removed is not dropped, it is REASSIGNED: a partially swept document is CONSISTENT but not APPLICABLE — the card serves a clock with the lowest entry that reaches it, so a promise made for a frequency nobody has measured cannot be enforced once a HIGHER frequency has been made cheaper. That check belongs to the phase that APPLIES documents (epic 02 phase 5), not to the one that writes them. Where two measurements genuinely contradict — the rare case the owner named himself — closePoint ratchets the higher frequencies UP and NAMES every one it moved (plans/13 §4: «поднятые храповиком частоты названы»); raising is the safe direction and invents nothing, while shipping the higher frequency at a voltage a lower one demonstrably failed at would be shipping a known failure. Generalisation: a guard written for an artifact at REST will fire on the states the work passes THROUGH, and the tell is the timing — a guard that reddens on the first legitimate operation is describing an unwritten assumption, not catching a defect (EXP-0076). |
| R14d | THE ROW CARRIES A TAG CLOUD, THE VOCABULARY IS CLOSED, EVERY TAG HAS A CLASS, AND THE LEGACY status IS DERIVED — NEVER STORED. |
Added 2026-08-22 with epic 04 phase 1 (plans/23, plans/24), on the owner's word: «облаго тегов, описывающих судьбу, историю, свойства точки» · «чтобы код в будущем понимал, что за точка, и как с ней быть по её тегам». Why the single field had to go, in this project's own receipts: it was caught lying to the owner on 2026-08-17 — 54 of 54 rows closed that night said «предел рычага» and NOT ONE had hit the lever, because one word was answering three independent questions (what stopped the descent · how deeply the row is proved · where its number came from). The remedy then was to add a word (depth-capped); words multiply combinatorially and that does not scale. Worse, the field was LOSSY: long-burn-proved overwrote edge-found, so a frequency could not say it had found its edge AND held the long burn — while the owner's convergence loop is built on accumulating exactly that. Four parts. (a) Classes, not a flat bag: every tag is class:value, and a class is EXCLUSIVE (stop — at most one per row) or CUMULATIVE (burn, origin). This answers the one real objection to tag sets — a flat bag cannot express «exactly one of these» (researches/13 §2.2) — without giving up the cloud. (b) The vocabulary stays CLOSED and refuses by name, exactly as the status always did: free-form tags are the documented failure mode of this model, and the closure is what makes a reader trust the document. (c) status left ROW_KEYS and is a NON-ENUMERABLE derived view (attachDerivedStatus) — the same shape R14c uses for offsetMhz, so consumers migrate one at a time and the field CANNOT be written back to disk: the truth↔mirror pair is prevented rather than watched. (d) The format's own module reads the STORED tags, never the view — paid for during the migration itself: closePoint copies rows with {...r}, a spread carries only ENUMERABLE properties, so every internal check written against r.status silently read undefined and the ratchet would have raised untouched factory rows. Hence isUnmeasured and claimsBurnProof. Proved: the production document round-trips byte-exact (389 rows) and the dry run over 2887…2700 MHz is line-identical before and after; 9 blocks in curve --selftest, mutations M1–M4 each reddening their own blocks. The hand-copied vocabulary subset in engine.seedFor was REMOVED rather than migrated — it asks claimsBurnProof now, so the vocabulary lives in one place. |
| R18 | A RECORDED HANG IS A WALL ON THE DESCENT AND THE FREQUENCY'S EDGE — ONE HANG, NOT TWO. | Added 2026-08-17 with bugs/23. The owner made ЗАВИС a verdict of the FIRST class (GOAL.md → «ЗАВИС names for that frequency (sweep-journal.hangFloors → descentLadder), and the SEED is cancelled by it too, because a seed is a jump that would reach the fatal rung before any ladder existed. (b) The closure: a descent stopped by the floor closes edge-found through refineEdge — the hang is the failure's OUTER bracket, the deepest PASS the inner one — so the owner's margin is applied by the one function that owns it and his rule «a coarse failure is refined before the margin» is obeyed for free. The witness DISTINGUISHES a hang from an oracle verdict: one is a measurement of numbers, the other a machine that stopped existing. No PASS above the floor → a STOP with nothing shipped, never an invented voltage. (c) It SUBSUMES the two-consecutive-hangs brake on the sweep path, in the safe direction — the brake had to reach the SECOND hang, i.e. one protected rung cost two reboots; the floor closes it after the first. Trap T5 measures exactly that on a real process kill: attempt 1 exits 70, attempt 2 exits 0. The brake is kept with its own block at runRung, because subsumption is a property of today's caller. Corollary that cost a filter: the ONLY other site choosing a voltage — the rebase off the proven ground — cannot reach the floor by arithmetic (it always moves the target UP), so the guard written there was unreachable and was replaced by the end-to-end property with a drifting ground (EXP-0073). 256 blocks in engine --selftest, 31 in journal --selftest, mutations 68–72 and 74–76. |
| R8 | The workload build locates its own toolchain. | nvcc does not find an MSVC host compiler by itself, and a machine's PATH is not KAGO's to assume — toolchain.mjs resolves it via vswhere, with the x86-hosted cross compiler as a proven fallback (researches/03 §2.1). |
| Editing… | Also affected | The check |
|---|---|---|
config.mjs |
everything — it is the shared constant table | re-run the last profile validation; a changed guardband invalidates measured profiles |
profile-manager.mjs or any backend |
engine.mjs (search results), setup-desktop.mjs (applied profiles), the tray reset path |
write → read back → compare; refuse the profile if they differ |
stress-tester.mjs |
every past verdict | golden references were captured by the old code — a changed comparison invalidates them; recapture the baseline |
event-logger.mjs |
the crash half of every verdict | mutation-prove it: it must go red against a known TDR event, or it is not a detector |
desktop-shortcuts.mjs / setup-desktop.mjs |
the owner's Desktop and Task Scheduler | these touch the owner's environment — never run them to "see what happens" |
curve-store.mjs or card-grids.mjs |
every consumer of the tuning curve: profile-store (the curveRef and curveSnapshot branches), the applier's offset arithmetic (ONE path for both sources, profile-manager.effectiveCurveSetting), the battle snapshots in curves/battle/ (their format gate delegates the body to validateCurveDoc, so a changed row rule changes what a snapshot may contain — plans/99), and — from phase 2 on — the sweep's own memory |
npm run curve -- --selftest (40 blocks, offline) THEN npm run curve -- --verify against the live card: the second is the truth↔mirror pair and the first cannot replace it. A changed row shape also invalidates every stored document, because ROW_KEYS is an exact-match list and an unknown field is a refusal, not a warning |
BUILT — phase 3 closed 2026-08-14 12:4x (judge: VERIFIED WITH CAVEATS,
plans/06§4.6). The design below is now standing machinery: 4 desktop.lnk(owner's names verbatim, Fluent Emoji 3D icons — his verdict after the render), 5 elevated apply tasks +\KAGO\boot-apply(logon re-apply through the same gates) +\KAGO\tray(unelevated, passive NotifyIcon reading the remembered-state file on a 2 s mtime timer). Kill-safety proven live: P3-AC4 = 0 settable diffs of 29 fields. Draft modes REFUSE until phase 6 qualifies them. The one open meter: P3-AC2's five natural logons, collecting inruns/shell/boot-apply.jsonl.
Settled by the owner, 2026-08-09 (chat): "в трее делаем без кнопок, а просто показ статуса, а сброс до заводских настроек — по третьему ярлыку с записью в автозагрузку".
The design is now three shortcuts and a passive tray:
SUPERSEDED 2026-08-10 18:5x — there are FOUR shortcuts, not three. The owner split the modes by their
objective functions (GOAL.md → «Четыре режима»; the long form is MASTER_PLAN.md). What changed
structurally: the old Max Optimal was one profile trying to serve two different optima, and it becomes
two modes. None of them uses a clock lock.
AND AT 19:1x THE SAME EVENING THE APPLIER GAINED A SECOND LEVER, so the line "nothing in the applier
changes" no longer holds and is corrected here rather than left standing. The owner sharpened
Optimised: FPS within 5 % of Max Perfomance, bought with a hard reduction in watts, heat and noise,
«чтобы она молотила не на 300 Вт, а сильно ниже, и выше не поднималась». A raised curve with a clock cap
bounds consumption only indirectly, so Optimised additionally sets a power limit — which means the
applier composes the NVAPI backend (the curve) with the nvidia-smi backend (-pl) in one profile. R1 is
untouched (profile-manager.mjs remains the only writer, and it already owns both backends); what changes
is that a profile is no longer a single-backend artifact, and its rollback must undo BOTH parts — the same
totality rule R9a states for the watchdog. Range, measured: -pl moves 300 → 250 W only.
| Shortcut | Applies | Becomes the remembered boot state |
|---|---|---|
| 🚀 Max Perfomance | curve raised, ceiling at the curve's TOP — the gain goes into clock | yes |
| ⚖️ Optimised | curve raised, ceiling at the stock operating clock, AND a power limit through -pl — the only mode that uses two backends' levers at once |
yes |
| ❄️ Silent Cold | curve raised, ceiling well below stock — the cold mode, ~10 % paid deliberately | yes |
| 🔄 Stock Default | factory — every offset to 0, -rgc, power limit back to default |
yes |
The tray icon displays the active profile and nothing else. No menu, no buttons, no click actions. It reads state; it never writes it.
What this supersedes, stated plainly rather than dropped. GOAL.md asks: "Если убить её —
профиль сбрасывается, GPU переводится в режим по умолчанию". With a status-only tray that owns no
state, killing it no longer resets anything — the profile stays applied until a shortcut changes it.
The owner's later instruction is the more specific one and governs. A killed tray now means the
owner loses the indicator, not the profile, and the deliberate way back to stock is the third
shortcut.
🆕 AMENDED 2026-08-23 ~15:3x +03:00 BY THE OWNER, AND THE AMENDMENT SPLITS THE CASE IN TWO. His words: «пункт Exit в контекстном меню KAGO должен сбрасывать карту до завода, и закрывать трей-приложение KAGO». So the tray gains ONE state-changing action, and only one.
⚠️ NOT BUILT as of 2026-09-25 (automation-engine/tray.ps1:8«no menu, no buttons, no click actions»;lib/tray-autostart.mjs:205«the Exit item … is not built yet») — this section is the DESIGN. And the task it would call,\KAGO\apply-factory, did not zero the V/F curve until 2026-09-25 (bugs/140: fixed in code that morning —applyNeedsCurveBackend; live witness pending).
how the tray ends resets the card? why Exit from the right-click menu YES — through \KAGO\apply-factory, i.e. the same elevated task the🔄 Stock Defaultshortcut uses, so R1 is untoucheda human chose it, and he says that is what he wants killed from Task Manager / crashed / logged off NO — unchanged no exit handler runs, so detection would need a heartbeat or a Job Object: a second moving part whose failure mode is resetting the GPU when nothing was wrong. That is precisely why the paragraph above exists, and it still holds The tray therefore remains an INDICATOR that owns no state — with one exception that is an explicit human command and is executed through the existing writer, never by the tray itself. Design detail and the ordering rule (reset first, exit only if the reset succeeded) live in
plans/10§1.2.
Why this is the better design, and not merely the easier one: a process killed by Task Manager runs no exit handler, so kill-detection would have needed a heartbeat, a watchdog, or a Job Object — a second moving part whose failure mode is resetting the GPU when nothing was wrong. An explicit shortcut has no failure mode at all. The safety property that actually matters is untouched: profiles live in volatile GPU memory, so a reboot or a driver reload still returns the card to stock without anyone doing anything.
Consequence for the applier: every shortcut, reset included, writes the same "remembered state" record that the boot task reads. Reset is a profile like the other two — the stock one — not a special case in the code.
| Contour | Boundary | Quality gate |
|---|---|---|
| Search | engine.mjs, stress-tester.mjs, event-logger.mjs — finds the safe voltage per point |
a point is closed only with a three-way verdict and a sized guardband |
| Apply | profile-manager.mjs and its backends — puts a profile on the card |
write → read back → match, else refuse |
| Watch | run-dashboard.mjs (the pulse a run writes · a separate read-only server · the owner's own browser window) · curve-map.mjs (ONE renderer of the tuning curve: facts from the journal's pure readers, geometry, SVG) · the built page assets/dashboard/sweep.html = the accepted mockup homeworks/03 + _wiring.js + _sound.js, assembled by tools/build-dashboard-page.mjs · the static map assets/curve-map.html by tools/build-curve-map.mjs (plans/20, plans/85) |
the window READS and never writes (no card, no journal, no document; the journal only through readJournal · provenRungs · hangFloors · corrections, never resumeState) · the page computes nothing about the curve — it shows the SVG the server drew (E26-AC1) · data paths are seams (--pulse · --telemetry · --curve · --journal), so the twin and the bench feed the window their own files (E26-AC3) · the alarm stays outside every switchable widget (E26-AC4) · a card-writing sweep refuses to start without an open window (viewersWatching) · the built page is fresh or npm run check reddens |
| Surface | setup-desktop.mjs, desktop-shortcuts.mjs, the tray — what the owner touches |
the owner can always reach factory state without the agent |
| Safety net | watchdog.mjs — the armed record, the detached guard, the total undo, the stale-record recovery |
four layers, and each one's coverage is stated rather than assumed: the writer's finally · this guard (a hung/killed writer) · Windows TDR (defaults verified in the registry, deliberately unchanged) · volatility + reboot. The drill must fire it for real before any of it is believed. See R10 — three of the four need a live OS, and 2026-08-11 proved it |