From 0781b1be8c6bceb37d969bc2134eadd5d674faa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Fri, 7 Aug 2026 05:08:17 +0300 Subject: [PATCH] =?UTF-8?q?fix(=D0=BD=D0=BE=D1=87=D1=8C):=20=D0=B8=D0=B7?= =?UTF-8?q?=20=D1=87=D0=B5=D1=82=D1=8B=D1=80=D1=91=D1=85=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D1=8A=D0=B5=D0=B7=D0=B4=D0=BE=D0=B2=20=D0=BD=D0=B0=D1=81?= =?UTF-8?q?=D1=82=D0=BE=D1=8F=D1=89=D0=B8=D0=B9=20=D0=BE=D0=B4=D0=B8=D0=BD?= =?UTF-8?q?=20=E2=80=94=20=D0=B7=D0=B0=D0=BA=D1=80=D1=8B=D1=82;=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=87=D0=B8=D0=BD=D0=BA=D0=B0=20=D0=BF=D1=8F=D1=82=D0=BE?= =?UTF-8?q?=D0=B3=D0=BE=20=D0=BB=D0=BE=D0=BC=D0=B0=D0=BB=D0=B0=20=D1=87?= =?UTF-8?q?=D1=83=D0=B6=D0=BE=D0=B3=D0=BE=20=D1=81=D1=82=D0=BE=D1=80=D0=BE?= =?UTF-8?q?=D0=B6=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Находка М-405, правила 242-243. Смена 26 назвала четыре разъезда (правило 239: обёртка есть, а работа идёт мимо). Проверил каждый замером — НАСТОЯЩИЙ ОДИН, три ложные тревоги. Ровно та же доля, что и в разборе 33 долгов: список, собранный беглым взглядом под верным правилом, оказался наполовину чужим. - `readEvents` — ❌ обвинённые делают ДРУГУЮ работу: судья ленту вовсе не читает (только проверяет, есть ли файл), а `zhiv-li-progon.mjs` разбирает её своим путём НАРОЧНО — `readLines` порванную строку глотает молча, а ему она обязана значить «неизвестно». Свёл бы «как велено» — сломал бы нарочную защиту; - `vorotaVetkiNochi` — ✅ настоящий, закрыт этим коммитом; - `schyotZovushchih` — ❌ общее уже вынесено в `tolkoKod`+`zovyImeni`, обе дороги через него; - читалки `schyot-zamerov.mjs` — ❌ живой дороге нужны порванные строки, читалкам нет. ЧТО ПОЧИНЕНО. `sverkaNastroek` делала «спросить хранилище и разобрать ответ» своими руками — тем же телом, что лежит внутри ворот `vorotaVetkiNochi`. Дороги уже начали расходиться МОЛЧА: у ворот умолчание «спрашивать каждый раз», у сверки — «помнить ответ на заход». Сегодня это не видно ничем, потому что сверка всегда передаёт свой `sprosit` явно, — но поправь кто-нибудь ворота, и починка до живой дороги не доехала бы. Доказано вырезанием: разъезд возвращён — краснеет ровно одна, посчитал ДО прогона, сошлось. Страховка починки отдельной проверкой: ворота и прежняя прямая пара отвечают одинаково на обоих исходах, включая бросок хранилища, — поведение не изменилось ни на знак. 🔴 ГЛАВНОЕ, ЧТО КУПИЛА СМЕНА, И КУПЛЕНО ЭТО СВОЕЙ ОШИБКОЙ. Замер нашёл рядом пятый разъезд на вид настоящий: имя ленты `events.jsonl` написано РУКАМИ в трёх местах, хотя обёртка `eventsPath` заведена ровно затем, чтобы оно жило в одном. Свёл — и полный прогон дал две красных, ОБЕ У ЧУЖОГО СТОРОЖА, ни одной у моего. `nadziratel-obyavlyaetsya-a-pribor-chitaet.test.mjs` (сеть 3) требует ПРОТИВОПОЛОЖНОГО: путь к журналу не берёт себе никто, кроме дома ленты, — потому что взявший однажды начнёт в журнал ПИСАТЬ мимо единственной пишущей руки `logEvent`, и сети, считающие её зовы, ослепнут молча. А от них зависит, не запустят ли второй прогон на те же файлы. Разъезд же имён он закрывает не сведением, а СВЕРКОЙ: читает оба написания и краснеет, если разошлись. ⇒ Беда, которую я шёл закрывать, была уже закрыта — другим способом, которого я не увидел. Откачено целиком, чужого сторожа не тронул ни знаком, своего убрал и оставил на его месте записку следующей смене, чтобы она не потеряла тот же час. 242. КРАСНОЕ НА ЧУЖОМ СТОРОЖЕ ПОСЛЕ ТВОЕЙ ПРАВКИ — НЕ ПОМЕХА, А ОТВЕТ: место, которое ты счёл беззащитным, охраняется, и не так, как ты собирался его чинить. 243. У СПИСКА, СОБРАННОГО ПОД СВЕЖИМ ПРАВИЛОМ, ПРОВЕРЬ КАЖДУЮ СТРОКУ ОТДЕЛЬНО: правило проверяют мыслью, список — замером, и это две разные работы. ПОПУТНО: два реза сведены в один дом. `bezPrimechaniy` перенесён к грубому `tolkoKod` с развилкой «какой брать». Врозь они и стоили смене 26 сторожа, который физически не мог покраснеть: искала команду, живущую строкой, а взяла рез, который строки режет (правило 234). 🪤 Мелочь, стоившая ложной тревоги: копия утренней бумаги помечена временем МИРОВЫМ (`toISOString`), а часы на машине московские. Разница три часа — и след моего же прогона выглядел работой чужой смены, пришедшей после конца предыдущей. Проверок 2927 в 108 файлах (было 2924 в 107), ноль красных, код 0. Co-Authored-By: Claude Opus 5 --- .../zamer/2026-08-02-ZAMER-metoda.md | 60 +++++++++ .../zamer/2026-08-18-razbor-33-dolgov.md | 18 +++ ...mechanie-ne-rashoditsya-s-pravdoy.test.mjs | 36 +++--- .../night/rabota-idyot-odnoy-dorogoy.test.mjs | 115 ++++++++++++++++++ tools/night/schyot-zovushchih.mjs | 26 ++++ tools/night/sudya-nochi.mjs | 3 + tools/night/sverka-nastroek-s-resheniyami.mjs | 17 +-- tools/night/zhiv-li-progon.mjs | 6 + 8 files changed, 252 insertions(+), 29 deletions(-) create mode 100644 tools/night/rabota-idyot-odnoy-dorogoy.test.mjs diff --git a/docs/superpowers/zamer/2026-08-02-ZAMER-metoda.md b/docs/superpowers/zamer/2026-08-02-ZAMER-metoda.md index e29e78a7..18fd3946 100644 --- a/docs/superpowers/zamer/2026-08-02-ZAMER-metoda.md +++ b/docs/superpowers/zamer/2026-08-02-ZAMER-metoda.md @@ -10768,3 +10768,63 @@ const s = `ушло ${dollary(x)} денег`; → после чистки: `zadachaKonchena`: «**зовут его двое**». Живого зова нет ни одного. При этом в `supervisor.mjs` про то же самое сказано честно — «ИМЕННО ЭТА СТРОКА заменяется на зов», в будущем времени. 🔑 **Разница между враньём и честностью тут — одно время глагола.** + +--- + +## М-405. Смена 27: правило было верным, а список под ним — нет + +**07.08.2026.** Развилка окупилась **седьмой раз подряд**: новой ночи не было, все шесть +приборов годны. Взялся за пункт 3 промта — «четыре разъезда», найденных сменой 26. + +> 🔴 **ГЛАВНОЕ ЧИСЛО СМЕНЫ. Из четырёх разъездов настоящим оказался ОДИН.** +> Три из четырёх — ложные тревоги, ровно как 14 из 33 в смене 26. + +| кого смена 26 назвала разъездом | что показал замер | +|---|---| +| `readEvents` | ❌ обвинённые дороги делают **другую работу**: судья ленту вовсе не читает, а `zhiv-li-progon.mjs` разбирает её своим путём **нарочно** (`readLines` порванную строку глотает молча, а ему нужен ответ «неизвестно») | +| `vorotaVetkiNochi` | ✅ **настоящий** — тело повторено дословно, и умолчания уже разошлись | +| `schyotZovushchih` | ❌ общая работа уже вынесена (`tolkoKod` + `zovyImeni`), обе дороги идут через неё | +| читалки `schyot-zamerov.mjs` | ❌ живой дороге нужны порванные строки, читалкам нет — это **разные работы** | + +**242. 🔑 КРАСНОЕ НА ЧУЖОМ СТОРОЖЕ ПОСЛЕ ТВОЕЙ ПРАВКИ — НЕ ПОМЕХА, А ОТВЕТ.** +Оно говорит: место, которое ты счёл беззащитным, **охраняется — и не так, как ты собирался +его чинить**. Спроси сперва, что этот сторож бережёт, и лишь потом решай, кто из вас прав. + +Куплено живой ценой. Замер показал: имя ленты `events.jsonl` написано руками в трёх местах, +хотя обёртка `eventsPath` заведена ровно затем, чтобы оно жило в одном. Свёл — и полный +прогон дал две красных, **обе у чужого сторожа, ни одной у моего**. Оказалось, +`nadziratel-obyavlyaetsya-a-pribor-chitaet.test.mjs` требует ПРОТИВОПОЛОЖНОГО: + +- путь к журналу не берёт себе никто, кроме дома ленты, — потому что **взявший однажды + начнёт в журнал писать** мимо единственной пишущей руки, и сети, считающие её зовы, + ослепнут молча (а от них зависит, не запустят ли второй прогон на те же файлы); +- разъезд имён он закрывает не сведе́нием, а **сверкой**: читает оба написания и краснеет, + если они разошлись. + +⇒ Беда, которую я шёл закрывать, была уже закрыта — **другим способом**. Откатил целиком, +чужого сторожа не тронул ни знаком, своего убрал. + +**243. 🪤 У СПИСКА, СОБРАННОГО ПОД СВЕЖИМ ПРАВИЛОМ, ПРОВЕРЬ КАЖДУЮ СТРОКУ ОТДЕЛЬНО.** +Правило 239 записано верно, а четыре примера под ним собраны беглым взглядом — и три +оказались чужими. 🔑 Верное правило не делает верным список, собранный под него: правило +проверяют мыслью, список — замером, и это две разные работы. + +### 🪤 Мелочь, стоившая тревоги: имя файла в чужом поясе + +Копия утренней бумаги помечена `…prezhnyaya-2026-08-07-013624.md`, а смена 26 кончилась +в 23:25 — то есть кто-то трогал бумагу ПОСЛЕ неё. Чужой смены не было: имя пишется через +`toISOString()`, то есть **в мировом времени**, а часы на машине московские. Разница ровно +три часа, след оставил мой же прогон в 04:36. +🔑 Датчик, читающий такое имя как местное время, обвиняет несуществующую смену. + +### Что сделано + +🟢 **Настоящий разъезд закрыт.** `sverkaNastroek` делала «спросить хранилище и разобрать +ответ» своими руками — тем же телом, что лежит внутри ворот `vorotaVetkiNochi`. Дороги уже +начали расходиться молча: у ворот умолчание «спрашивать каждый раз», у сверки — «помнить +ответ на заход». Теперь дорога одна. +**Доказано вырезанием:** разъезд возвращён — краснеет ровно одна, названная заранее. + +🟢 **Два реза сведены в один дом.** `bezPrimechaniy` перенесён к грубому `tolkoKod` +с развилкой «какой брать». Врозь они и стоили смене 26 сторожа, который физически не мог +покраснеть: искала команду, живущую строкой, а взяла рез, который строки режет. diff --git a/docs/superpowers/zamer/2026-08-18-razbor-33-dolgov.md b/docs/superpowers/zamer/2026-08-18-razbor-33-dolgov.md index 3c29a536..657d8b15 100644 --- a/docs/superpowers/zamer/2026-08-18-razbor-33-dolgov.md +++ b/docs/superpowers/zamer/2026-08-18-razbor-33-dolgov.md @@ -52,6 +52,24 @@ app/vitest.config.tools.mjs:56 → globalSetup: ['../tools/night/storozh-boevo 🪤 **Четыре из них — один и тот же новый род:** «работа делается, но мимо обёртки». Две дороги к одному файлу могут разъехаться молча — это мелкий долг, но не мёртвый код. +> ## 🔴🔴 ПОПРАВКА СМЕНЫ 27: ИЗ ЧЕТЫРЁХ РАЗЪЕЗДОВ НАСТОЯЩИЙ ОДИН +> +> Список выше собран беглым взглядом. Смена 27 проверила каждую строку замером: +> +> | кого назвали | правда | +> |---|---| +> | `readEvents` | ❌ обвинённые делают **другую работу**: судья ленту не читает вовсе, а `zhiv-li-progon.mjs` разбирает её своим путём **нарочно** — ему нужен ответ «неизвестно» на порванной строке | +> | `vorotaVetkiNochi` | ✅ **настоящий**, закрыт сменой 27 | +> | `schyotZovushchih` | ❌ общее уже вынесено в `tolkoKod` + `zovyImeni`, обе дороги идут через него | +> | читалки `schyot-zamerov.mjs` | ❌ живой дороге нужны порванные строки, читалкам нет — разные работы | +> +> 🔑 **Правило 243:** верное правило не делает верным список, собранный под него. +> Правило проверяют мыслью, список — замером. Это две разные работы. +> +> 🔴 И ещё дороже: замер нашёл рядом настоящий на вид разъезд (имя `events.jsonl` руками +> в трёх местах) — а починка его сломала **чужого сторожа**, который то же место охраняет +> наоборот. Полностью откачено. **Правило 242** — в `2026-08-02-ZAMER-metoda.md`, М-405. + ### 🔴 Настоящие долги — 19 **А. Механизм «спросить владельца и принять ответ» — 11 имён, мёртв С ОБЕИХ СТОРОН** diff --git a/tools/night/primechanie-ne-rashoditsya-s-pravdoy.test.mjs b/tools/night/primechanie-ne-rashoditsya-s-pravdoy.test.mjs index 3c10c14a..a83ff0ff 100644 --- a/tools/night/primechanie-ne-rashoditsya-s-pravdoy.test.mjs +++ b/tools/night/primechanie-ne-rashoditsya-s-pravdoy.test.mjs @@ -38,27 +38,21 @@ import { REPO_ROOT } from './paths.mjs'; const NOCH = join(REPO_ROOT, 'tools', 'night'); const chitat = (imya) => readFileSync(join(NOCH, imya), 'utf8'); -/** - * Вырезать ТОЛЬКО примечания, оставив строковые значения. - * - * 🔴 ПОЧЕМУ НЕ ЧУЖОЙ `tolkoKod`, ХОТЯ СПЕРВА ВЗЯЛ ИМЕННО ЕГО — И ЭТО БЫЛА ОШИБКА. - * Он вырезает и примечания, И СТРОКИ. Замерено: - * `case 'answer': return otvet();` → `case : return otvet();` - * А команда `cli.mjs` живёт ИМЕННО строкой. То есть сторож, почищенный им, не увидел бы - * заведённую команду НИКОГДА и остался бы вечно зелёным по ложной причине — сторож, - * который физически не может покраснеть, не сторожит ничего. - * ⇒ Правило 234 своими руками: у датчика, который что-то вырезает перед счётом, спрашивай - * не «что он режет», а «не режет ли он вместе с шелухой зерно». - * - * 🪤 Чего стоит этот рез, называю вслух: `//` внутри строкового значения (ссылка `https://`) - * обрежет остаток строки. Для трёх слов, которые тут ищутся, это безразлично, а полного - * разбора языка сторожу не нужно. - */ -export function bezPrimechaniy(text) { - return String(text ?? '') - .replace(/\/\*[\s\S]*?\*\//g, ' ') - .replace(/\/\/[^\n]*/g, ' '); -} +// 🔴 ПОЧЕМУ НЕ ЧУЖОЙ `tolkoKod`, ХОТЯ СПЕРВА ВЗЯЛ ИМЕННО ЕГО — И ЭТО БЫЛА ОШИБКА. +// Он вырезает и примечания, И СТРОКИ. Замерено: +// `case 'answer': return otvet();` → `case : return otvet();` +// А команда `cli.mjs` живёт ИМЕННО строкой. То есть сторож, почищенный им, не увидел бы +// заведённую команду НИКОГДА и остался бы вечно зелёным по ложной причине — сторож, +// который физически не может покраснеть, не сторожит ничего. +// ⇒ Правило 234: у датчика, который что-то вырезает перед счётом, спрашивай не «что он +// режет», а «не режет ли он вместе с шелухой зерно». +// +// 🆕 Смена 27 перенесла сам рез в `schyot-zovushchih.mjs` — К ГРУБОМУ `tolkoKod`, чтобы оба +// стояли рядом с развилкой «какой брать». Врозь они и стоили смене 26 этой ошибки. Проверка +// 1Б ниже стережёт его по-прежнему, откуда бы он ни ввозился. +import { bezPrimechaniy } from './schyot-zovushchih.mjs'; + +export { bezPrimechaniy }; /** * Сходится ли примечание с правдой. Оба довода — текстом, чтобы правило можно было diff --git a/tools/night/rabota-idyot-odnoy-dorogoy.test.mjs b/tools/night/rabota-idyot-odnoy-dorogoy.test.mjs new file mode 100644 index 00000000..56cac13d --- /dev/null +++ b/tools/night/rabota-idyot-odnoy-dorogoy.test.mjs @@ -0,0 +1,115 @@ +// 🔴🔴 РАЗЪЕЗД: ОБЁРТКА ЕСТЬ, А РАБОТА ИДЁТ МИМО НЕЁ (правило 239, смена 26). +// +// Заведено сменой 27 после замера, который поправил саму смену 26. Она назвала четыре +// разъезда; глазами проверили каждый — настоящий оказался ОДИН, и вот он: +// +// `vorotaVetkiNochi` (`vetka-nochi-ne-otstayot.mjs:146`) — спросить хранилище и разобрать +// ответ. Ровно то же самое СВОИМИ РУКАМИ делала `sverkaNastroek` +// (`sverka-nastroek-s-resheniyami.mjs`): свой `try/catch`, свой зов `razborVetkiNochi`. +// Тела совпадали до знака. +// +// 🪤 ПОЧЕМУ ЭТО ХУЖЕ, ЧЕМ ПРОСТО ЛИШНИЕ СТРОКИ, И ПОЧЕМУ ЛОВИТЬ НАДО СТОРОЖЕМ, А НЕ ГЛАЗОМ. +// Две дороги к одному месту уже начали расходиться, и молча: у ворот умолчание +// `sprosit = sprosItHranilishche` (спрашивает хранилище КАЖДЫЙ раз), у сверки — +// `sprosItHranilishcheRazVZahod` (помнит ответ на один заход). Сегодня это не видно ничем: +// сверка всегда передаёт свой `sprosit` явно, и умолчание ворот до неё не доезжает. Но +// поправь кто-нибудь ворота — и починка не доедет до живой дороги, потому что живая дорога +// через ворота не идёт. Ровно этот класс правило 239 и называет: «не мёртвый код, а разъезд». +// +// 🔴 ЧТО ЭТОТ СТОРОЖ НЕ ЛОВИТ, ГОВОРЮ ВСЛУХ. Разъезд сегодня ЧИСТО СТРУКТУРНЫЙ: на всяком +// входе обе дороги отвечают одинаково (проверка 2 это и замеряет). Значит поведенческим +// сторожем его поймать нельзя — он был бы зелёным вслепую и не доказывал бы ничего. +// Поэтому проверка 1 читает исходник. Слабость приёма называю честно: он стережёт ИМЯ, +// а не смысл — заведи кто-нибудь третью дорогу под другим именем, сторож промолчит. +import { describe, it, expect } from 'vitest'; +import { readFileSync } from 'node:fs'; +import { join, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { tolkoKod, zovyImeni } from './schyot-zovushchih.mjs'; +import { razborVetkiNochi, vorotaVetkiNochi } from './vetka-nochi-ne-otstayot.mjs'; + +const DIR = dirname(fileURLToPath(import.meta.url)); + +// 🪤 ПРАВИЛО 234 НА ЭТОМ САМОМ МЕСТЕ. `tolkoKod` режет не только примечания, но И СТРОКИ — +// смена 26 обожглась об это, сделав сторожа, который физически не мог покраснеть. Здесь он +// годится, и вот почему: ищем ИМЯ СО СКОБКОЙ (`razborVetkiNochi(`), а имя функции внутри +// строки не живёт. Ищи мы команду или ключ, живущий строкой, — брать его было бы нельзя. +const RODNOY = 'vetka-nochi-ne-otstayot.mjs'; +const IMYA = 'razborVetkiNochi'; + +function zovyRazbora(fayl) { + return zovyImeni(tolkoKod(readFileSync(join(DIR, fayl), 'utf8')), IMYA); +} + +describe('работа «спросить ветку и разобрать» идёт ОДНОЙ дорогой', () => { + it('1. никто, кроме самих ворот, не зовёт razborVetkiNochi напрямую', () => { + const zovov = zovyRazbora('sverka-nastroek-s-resheniyami.mjs'); + expect( + zovov, + `\n🔴 РАЗЪЕЗД: sverka-nastroek-s-resheniyami.mjs зовёт ${IMYA}() напрямую (${zovov} раз),` + + `\nминуя ворота vorotaVetkiNochi(), которые ровно это и делают.` + + `\nЧинить так: позвать vorotaVetkiNochi(imya, { sprosit, zhivoyZapusk }) вместо своего` + + `\ntry/catch с ${IMYA}. Родной файл ворот — ${RODNOY} — зовёт по праву, он не в счёт.`, + ).toBe(0); + }); + + // 🔴 ВСТРЕЧНЫЙ СТОРОЖ. Без него проверка 1 может стать зелёной оттого, что датчик ослеп + // (переименовали функцию, сломался рез примечаний), — и «ноль зовов» означало бы не + // «дорога одна», а «я ничего не вижу». Ноль обязан быть замеренным, а не пустым. + it('2. ВСТРЕЧНЫЙ: датчик вправду видит зов — в родном файле ворот он его находит', () => { + expect( + zovyRazbora(RODNOY), + `\n🔴 Датчик ОСЛЕП: в родном файле ${RODNOY} зов ${IMYA}() есть заведомо` + + `\n(им живут сами ворота), а датчик его не видит. Значит ноль в проверке 1` + + `\nничего не доказывает.`, + ).toBeGreaterThan(0); + }); + + // Страховка починки, а не сторож разъезда — называю честно. Она была зелёной ДО починки + // и обязана остаться зелёной после: доказывает, что дорога стала одна, а ответ не изменился + // ни на знак. Проверяются оба исхода, включая тот, ради которого стоит `try`. + it('3. ворота и прямая пара отвечают ОДИНАКОВО — починка поведения не меняет', () => { + const otvet = { vetkaUgla: 'feat/noch-proba-1', otstavanie: 0, vperedi: 0 }; + for (const zhivoyZapusk of [false, true]) { + expect( + vorotaVetkiNochi('feat/noch-proba-1', { sprosit: () => otvet, zhivoyZapusk }), + ).toEqual(razborVetkiNochi('feat/noch-proba-1', otvet, { zhivoyZapusk })); + + // Хранилище не ответило вовсе — тот самый случай, ради которого у обеих дорог стоит + // `try`: бросок обязан превратиться в «не спросили», а не в обвал. + expect( + vorotaVetkiNochi('feat/noch-proba-1', { + sprosit: () => { throw new Error('хранилище молчит'); }, + zhivoyZapusk, + }), + ).toEqual(razborVetkiNochi('feat/noch-proba-1', null, { zhivoyZapusk })); + } + }); +}); + +// ━━━ 🔴🔴 ЗАПИСКА СЛЕДУЮЩЕЙ СМЕНЕ: ЗДЕСЬ БЫЛ ВТОРОЙ СТОРОЖ, И Я ЕГО УБРАЛ ━━━ +// +// Не поленись прочесть, иначе пойдёшь той же дорогой и потеряешь тот же час. +// +// Смена 27 замерила: имя ленты `events.jsonl` написано РУКАМИ в трёх местах, хотя обёртка +// `eventsPath` заведена ровно затем, чтобы оно жило в одном. Замер верен. Вывод «значит +// это безнадзорный разъезд, надо свести» — НЕВЕРЕН, и цена ошибки была бы велика. +// +// 🔴 Место уже охраняется, просто ИНАЧЕ, чем я ждал. Сторож +// `nadziratel-obyavlyaetsya-a-pribor-chitaet.test.mjs` (сеть 3) требует ПРОТИВОПОЛОЖНОГО: +// · путь к журналу не берёт себе НИКТО, кроме дома ленты, — потому что взявший однажды +// начнёт в журнал ПИСАТЬ мимо единственной пишущей руки `logEvent`, и сети, считающие +// её зовы, ослепнут молча (а от них зависит, не запустят ли второй прогон на те же файлы); +// · а разъезд имён он закрывает не сведе́нием, а СВЕРКОЙ: читает оба написания и краснеет, +// если они разошлись. +// +// Моя починка ломала эту защиту: полный прогон дал две красных — обе у него, не у меня. +// +// 🔑 ПРАВИЛО 242, КУПЛЕННОЕ ЗДЕСЬ: КРАСНОЕ НА ЧУЖОМ СТОРОЖЕ ПОСЛЕ ТВОЕЙ ПРАВКИ — НЕ ПОМЕХА, +// А ОТВЕТ. Оно говорит, что место, которое ты счёл беззащитным, охраняется, и охраняется +// не так, как ты собирался. Спроси сперва, что этот сторож бережёт, и лишь потом решай, +// кто из вас двоих прав. Своего сторожа я убрал, чужого не тронул ни знаком. +// +// 🟡 Осталось открытым и ждёт слова владельца (вопрос 9 промта): развести намерения — +// «читать путь можно, писать мимо `logEvent` нельзя». Это правка ЧУЖОГО сторожа, берегущего +// дорогое, и самовольно я её не делаю. diff --git a/tools/night/schyot-zovushchih.mjs b/tools/night/schyot-zovushchih.mjs index 7d7ba77e..e9b48f7a 100644 --- a/tools/night/schyot-zovushchih.mjs +++ b/tools/night/schyot-zovushchih.mjs @@ -101,6 +101,32 @@ function obrazetsLiTut(vydano) { return PERED_OBRAZTSOM.test(t) || SLOVA_PERED_OBRAZTSOM.test(t); } +// ━━━ 🔴🔴 ДВА РЕЗА, И ОНИ НЕ ВЗАИМОЗАМЕНИМЫ. РАЗВИЛКА — ЗДЕСЬ ━━━ +// +// Стоят рядом НАРОЧНО. Смена 26 обожглась ровно оттого, что они лежали в разных файлах: +// искала команду, живущую строкой (`case 'answer':`), взяла грубый `tolkoKod` — и своими +// руками сделала сторожа, который физически не мог покраснеть. Правило 234. +// +// | что ищешь | какой рез | +// |---|---| +// | ИМЯ СО СКОБКОЙ (зов, `имя(`) | `tolkoKod` — грубый: срежет примечания, строки и образцы | +// | СТРОКУ (`'events.jsonl'`, команду, ключ) | `bezPrimechaniy` — режет ТОЛЬКО примечания | +// +// 🔑 Спрашивай у реза не «что он режет», а «не режет ли он вместе с шелухой зерно». + +/** + * Вырезать ТОЛЬКО примечания, оставив строковые значения нетронутыми. + * + * 🪤 Чего стоит этот рез, называю вслух: `//` внутри строкового значения (ссылка `https://`) + * обрежет остаток строки. Полного разбора языка сторожам не нужно, а эта краевая грубость + * им безразлична — но знать про неё обязан тот, кто возьмёт рез для нового дела. + */ +export function bezPrimechaniy(text) { + return String(text ?? '') + .replace(/\/\*[\s\S]*?\*\//g, ' ') + .replace(/\/\/[^\n]*/g, ' '); +} + export function tolkoKod(text) { let out = ''; let i = 0; diff --git a/tools/night/sudya-nochi.mjs b/tools/night/sudya-nochi.mjs index a01fc963..4d1d028d 100644 --- a/tools/night/sudya-nochi.mjs +++ b/tools/night/sudya-nochi.mjs @@ -143,6 +143,9 @@ export function ulikiProgona(runDirPath, { koren = REPO_ROOT } = {}) { const slova_nochi = estLiFayl(slovaPut) ? slovaPut : null; if (!slova_nochi) chego_net.push('слов, которые ночь написала о себе, нет — сводки строк не осталось'); + // 🪤 Имя ленты набрано руками НАРОЧНО — см. то же примечание в `zhiv-li-progon.mjs`: + // путь к журналу себе не берут, чтобы никто не начал писать в него мимо `logEvent`. + // Судья ленту и не читает вовсе: он только проверяет, есть ли она, и отдаёт путь наружу. const lentaPut = join(runDirPath, 'events.jsonl'); const lenta = estLiFayl(lentaPut) ? lentaPut : null; if (!lenta) chego_net.push('ленты событий прогона нет — по минутам ночь восстановить нечем'); diff --git a/tools/night/sverka-nastroek-s-resheniyami.mjs b/tools/night/sverka-nastroek-s-resheniyami.mjs index 57498c39..6882f50c 100644 --- a/tools/night/sverka-nastroek-s-resheniyami.mjs +++ b/tools/night/sverka-nastroek-s-resheniyami.mjs @@ -61,7 +61,11 @@ // настройки может не быть в файле вовсе (тогда ночь тихо возьмёт СВОЁ запасное число, никак // не сверенное с бумагой), и в настройке может лежать мусор. import { existsSync, readFileSync } from 'node:fs'; -import { razborVetkiNochi, sprosItHranilishcheRazVZahod } from './vetka-nochi-ne-otstayot.mjs'; +// 🪤 Ввозятся ВОРОТА, а не половинки. Прежде здесь стоял `razborVetkiNochi`, и «спросить +// хранилище и разобрать ответ» делалось своими руками — тем же телом, что уже лежит в самих +// воротах. Две дороги к одному месту начали расходиться молча (разные умолчания `sprosit`), +// и разъезд этот сторожит `rabota-idyot-odnoy-dorogoy.test.mjs` — правило 239. +import { vorotaVetkiNochi, sprosItHranilishcheRazVZahod } from './vetka-nochi-ne-otstayot.mjs'; // Путь к протоколу — печатается владельцу в каждом отказе, поэтому имя вынесено в постоянную: // набери его строкой по месту — и переименование протокола разъехалось бы со сторожем молча. @@ -726,13 +730,10 @@ export function sverkaNastroek(cfg = {}, { return [...polya, ...smysly, ...osnovaniya, ...pary, ...chuzhieChisla]; } - let otvet = null; - try { - otvet = sprosit(imya); - } catch { - otvet = null; // разбор сам скажет «спросить не удалось» — своими словами, а не молчанием - } - return [...polya, ...smysly, ...osnovaniya, ...pary, ...chuzhieChisla, razborVetkiNochi(imya, otvet, { zhivoyZapusk })]; + // Спросить и разобрать — одним зовом ворот. Свой `try/catch` тут стоял дословной копией + // того, что лежит внутри ворот: бросок хранилища они превращают в «не спросили» сами, + // и разбор говорит об этом своими словами, а не молчанием. + return [...polya, ...smysly, ...osnovaniya, ...pary, ...chuzhieChisla, vorotaVetkiNochi(imya, { sprosit, zhivoyZapusk })]; } // То, что обязано остановить работу. `musor` и `net-v-fayle` падают тем же порядком, что diff --git a/tools/night/zhiv-li-progon.mjs b/tools/night/zhiv-li-progon.mjs index afcaf24d..86e144f3 100644 --- a/tools/night/zhiv-li-progon.mjs +++ b/tools/night/zhiv-li-progon.mjs @@ -110,6 +110,12 @@ export const VIDY_ZAPISEY_NADZIRATELYA = ['supervisor_start', 'resume_start']; // объявят мёртвым, а ворота откроют второму на те же файлы. Порванная строка — это // «неизвестно», и ответ у неё отдельный. export function nadzirateliProgona(dirPath) { + // 🪤 Имя ленты набрано РУКАМИ, и это НАРОЧНО, а не недосмотр. Смена 27 попробовала свести + // его к `eventsPath` из дома ленты — и покраснел сторож `nadziratel-obyavlyaetsya-a-pribor- + // chitaet.test.mjs` (сеть 3). Он охраняет вещь дороже опрятности: в журнал прогона пишет + // ОДНА рука — `logEvent`, и путь к журналу никто себе не берёт, потому что взявший однажды + // начнёт в него писать мимо неё. А разъезд имён у него закрыт иначе: он сверяет написанное + // здесь с написанным в доме ленты и краснеет, если они разошлись. const put = join(dirPath, 'events.jsonl'); if (!existsSync(put)) return { ok: true, pids: [], porvano: 0 }; let tekst;