Turn the order from shipping a withheld text into naming the hole, keep the money fact visible, let a raised ceiling finish the unit, and rebuild the two pins that redden by luck
This commit is contained in:
parent
c38cb1ad33
commit
14dc3d5f23
1 changed files with 94 additions and 18 deletions
|
|
@ -60,12 +60,42 @@
|
|||
ошибка наверх;
|
||||
- у флага **СВОЯ причина**, отличная от исчерпания регенераций: читатель и оператор обязаны отличать «мы
|
||||
перепробовали всё» от «денег не хватило на вторую попытку»;
|
||||
- текст попытки 0 **отгружается**;
|
||||
- волна **идёт дальше**.
|
||||
|
||||
**Решаешь сам и аргументируешь:** имя причины · где именно ставится деградация (в цикле `runStage` или
|
||||
внутри `runAttempt` — у обоих есть довод, назови свой) · как при этом НЕ тронуть попытку 0: её отказ
|
||||
по-прежнему ОСТАНАВЛИВАЕТ книгу, это ратифицировано и менять нельзя (`stagerun.go`, греп `mandatory`).
|
||||
⛔ **ЧЕГО В ЭТОМ СПИСКЕ БОЛЬШЕ НЕТ И ПОЧЕМУ — читай, это главное место пака.** Первая редакция промта
|
||||
требовала, вслед за `D39.204` п.4, чтобы «текст попытки 0 **отгружался**». **Это невыполнимо как написано,
|
||||
и поймал это опровергатель, а не я.** В цикл ретрая попадают ТОЛЬКО флагованные попытки ретраебельных
|
||||
причин — `length`/`empty` плюс эхо-реролл (`backend/internal/pipeline/disposition.go`, греп `retryable`).
|
||||
Значит «оплаченный текст попытки 0» **по построению** обрезан, пуст либо является эхом исходника. А
|
||||
флагованная диспозиция (кроме `FlagSanitizerStripped`) оставляет пустой финальный текст, следующая стадия
|
||||
скипается, и экспорт не отдаёт ничего — `backend/internal/pipeline/holes.go` называет это `withheld` прямо:
|
||||
«contaminated output never ships» (`D2`).
|
||||
|
||||
⇒ **настоящий выигрыш пака формулируется так, и он не меньше прежнего, а честнее:**
|
||||
**невидимая дыра `pending`** (строки нет · юнит заклинен · `exit 4`) **→ НАЗВАННАЯ дыра `withheld`**
|
||||
(строка есть · причина денежная и названа · волна идёт · прогон кончается штатно).
|
||||
⚠ **Отгрузка обрезанного текста — ОТДЕЛЬНОЕ продуктовое решение, и я задал его владельцу.** Придёт «да» —
|
||||
доедет релеем отдельным сообщением, и ты подтвердишь его эхом. Сам не строй.
|
||||
|
||||
⛔ **И ВТОРОЕ, без чего пак сделает читателю хуже: ДЕНЬГИ ОБЯЗАНЫ ОСТАТЬСЯ ВИДНЫ.** Сегодня отказ ретрая
|
||||
публикует денежный факт: событие `ceiling` + защёлка + `exit 4`, и платформа пишет прогону `paused` и
|
||||
просит пополнить. После деградации этот путь исчезает: терминальные ветки `flagged` и `clean` несут только
|
||||
объём, а `Money` висит на ошибочных (`backend/internal/pipeline/events.go`, греп `terminal`). **Читателю
|
||||
кончились деньги — и никто ему этого не говорит.** ⇒ **делай РОВНО так:** прогон, отказавший только РЕТРАЮ,
|
||||
**по-прежнему публикует денежный факт** — либо явно НЕ публикует, и тогда довод записан в отчёте и в коде.
|
||||
⚠ И рядом живёт комментарий, который твой пак сделает ложным, если факт пропадёт: `runevents.go`, греп
|
||||
`ITS PRESENCE RULE` — «правило присутствия — „потолок был достигнут“, а не „исход = ceiling“».
|
||||
|
||||
**Решаешь сам и аргументируешь:** имя причины · где ставится деградация. ⛔ **И вот ШТАТНЫЙ носитель,
|
||||
который первая редакция промта пропустила:** у `runAttempt` уже есть параметр **`mandatory`** — «позволено
|
||||
ли отказанной резервации ЖДАТЬ освободившихся денег»; волна зовёт его с `true`, а эскалационный хоп,
|
||||
под-шаг ремонта и терминология зовут с `false` и потому деградируют (`backend/internal/pipeline/stagerun.go`,
|
||||
греп `mandatory`; правило — `reservegate.go`, греп `waitNotAllowed`). Это ровно тот класс, под который
|
||||
механизм построен. ⚠ **Но у него есть цена, и её надо назвать прежде, чем брать:** `mandatory=false`
|
||||
отнимает не только остановку, но и ПРАВО ЖДАТЬ — ретрай деградирует даже там, где деньги освободились бы
|
||||
через миллисекунду сеттлом соседа. **Остановка и ожидание — два решения на одном флаге.**
|
||||
|
||||
⛔ **Попытку 0 не трогать:** её отказ по-прежнему ОСТАНАВЛИВАЕТ книгу — ратифицировано, менять нельзя.
|
||||
|
||||
⚠ **Гипотеза, которую надо ПРОВЕРИТЬ, а не принять:** деградация сама по себе закрывает и следствие (2) —
|
||||
у юнита появляется статус, значит дыры в непрерывном префиксе нет. Похоже на правду; предъяви замером.
|
||||
|
|
@ -73,10 +103,29 @@
|
|||
### 4.2 Пин, ради которого пак существует
|
||||
|
||||
**«Купленное доставлено ⇒ не `exit 4`».** Прогон, где каждый купленный юнит доставлен, а один из них
|
||||
доставлен ФЛАГОВАННЫМ из-за нехватки денег на ретрай, **обязан кончиться успехом**, а не кодом 4.
|
||||
доставлен ФЛАГОВАННЫМ из-за нехватки денег на ретрай, **обязан кончиться `exit 2`** (флаги есть, но прогон
|
||||
завершён), **а не `exit 4`**. ⚠ Не «успехом»: `exit 0` требует, чтобы флагов не было вовсе, а флаг здесь
|
||||
есть по построению — это и есть честный исход.
|
||||
|
||||
⛔ И **пин на саму незаклиниваемость**: после такого прогона резюм не делает НИ ОДНОГО свежего платного
|
||||
вызова по этому юниту и не умирает. Сегодня он умирает вечно.
|
||||
⛔ **И назови СУЖЕНИЕ, иначе будешь ловить недостижимое:** утверждение верно в ОКНЕ, когда остатка потолка
|
||||
хватает на попытку 0 каждого следующего юнита. Кончился потолок совсем — попытка 0 следующего юнита
|
||||
обязательна, отказ по ней штатно останавливает книгу, и `exit 4` возвращается ЗАКОННО. Фикстуру строй
|
||||
именно на этой развилке.
|
||||
|
||||
⛔ **ПИН НА РЕЗЮМ — И ЗДЕСЬ ПЕРВАЯ РЕДАКЦИЯ ПРОМТА ЗАПИНИЛА БЫ ОТМЕНУ РАТИФИЦИРОВАННОГО, не заметив.**
|
||||
Я требовал «после такого прогона резюм не делает НИ ОДНОГО свежего платного вызова». Но денежный флаг —
|
||||
единственная причина, которую ЛЕЧАТ ДЕНЬГАМИ: сегодня «поднял потолок → резюм → читатель получил хороший
|
||||
перевод» ратифицировано (`backend/internal/pipeline/escalation.go`, греп `durably pauses and resumes`,
|
||||
`D4`). Мой пин сделал бы юнит навсегда деградированным, лечимым только редрайвом.
|
||||
⇒ **делай РОВНО так: денежная причина ПЕРЕ-АТАКУЕМА на резюме** — как `FlagCancelled`, единственная
|
||||
причина, у которой `resolvedForResume` ложен именно потому, что это «оплачено, но не сделано»
|
||||
(`backend/internal/pipeline/cutcall.go`, греп `resolvedForResume`). Пинь ДВЕ вещи: **без поднятия потолка
|
||||
резюм не делает свежих платных вызовов и не умирает** · **после поднятия потолка резюм ДОДЕЛЫВАЕТ юнит**.
|
||||
|
||||
⚠ **Два гейта поймают тебя сами — назову, чтобы не терять круг:** `TestEveryFlagReasonIsRanked` потребует
|
||||
завести новую причину в `flagSeverity` (`backend/internal/pipeline/status.go`), а
|
||||
`TestEveryOperatorMessageIsCatalogued` — внести новое сообщение в
|
||||
`backend/internal/pipeline/testdata/operator-messages.txt`.
|
||||
|
||||
### 4.3 Платформенная половина — **твоё дело назвать, не построить**
|
||||
|
||||
|
|
@ -89,20 +138,47 @@
|
|||
записать прогону, который кончился флагом вместо `exit 4` · какой её пин это стережёт. Я передам это
|
||||
платформенной сессии, и **акт будет один на две половины**.
|
||||
|
||||
### 4.4 Приложение — фикстура, краснеющая по УДАЧЕ (ряд 379(б))
|
||||
### 4.4 Приложение — ДВА пина, краснеющих по УДАЧЕ (ряд 379, ОБЕ половины)
|
||||
|
||||
Отдельная, маленькая и не связанная с §4.1 работа; делай её ПОСЛЕ основной.
|
||||
Отдельная от §4.1 работа; делай её ПОСЛЕ основной. ⛔ **И мой диагноз здесь был НЕВЕРЕН — опровергнут
|
||||
замером, а не мнением. Читай, чем именно, иначе повторишь мою ошибку.**
|
||||
|
||||
Запись каталога `CUTCALL-a-refusal-pays-when-the-reply-outruns-the-write` стережёт самую дорогую половину
|
||||
денежного бита `delivered()` (`backend/internal/llm/attemptcut.go:189`=`answered && t.firstByte.Load()`). **Замер оркестратора 11.09:** на
|
||||
чистом дереве пин `TestARefusalIsNotAPurchaseEvenWhenTheReplyOutrunsTheWrite` даёт **8 зелёных из 8**, на
|
||||
своей посадке — **7 КРАСНЫХ ИЗ 8, один ЗЕЛЁНЫЙ**. Текст падения верный и про предмет; дыра в ФИКСТУРЕ:
|
||||
она шлёт ~6 МБ тела, сервер читает строку запроса, отвечает `401` и рвёт связь `SetLinger(0)` — и успеет ли
|
||||
транспорт записать `GotFirstResponseByte` раньше, чем `Do` вернёт ошибку записи, **решает гонка, а не
|
||||
построение**. ⇒ прежние RED этой записи были удачей.
|
||||
**Половина (б).** Запись каталога `CUTCALL-a-refusal-pays-when-the-reply-outruns-the-write` стережёт самую
|
||||
дорогую половину денежного бита `delivered()`
|
||||
(`backend/internal/llm/attemptcut.go:189`=`answered && t.firstByte.Load()`): провайдер ОТКАЗЫВАЕТ и рвёт
|
||||
коннект, пока наше тело ещё пишется — байт ответа есть, статуса в руках нет, и чтение «байт = доставка»
|
||||
оплачивает сметой каждый отказ (замер прежнего пака: 22 отказа из 25, один на $0.80).
|
||||
|
||||
**Задача:** перестроить фикстуру так, чтобы приход байта ответа был НЕИЗБЕЖЕН до обрыва, и предъявить
|
||||
**8 из 8 красных на посадке при 8 из 8 зелёных на дереве**. Способ выбираешь сам.
|
||||
**Два независимых замера на посадке (снятие `answered &&`), и они расходятся:** мой — **7 красных из 8**
|
||||
(снят на нагруженной машине, рядом шла батарея); опровергателя на спокойной — **8 из 8**, а на сорока
|
||||
процессах **39 FAIL / 1 PASS**. ⇒ пин краснеет по УДАЧЕ, это подтверждено обоими; частота зависит от
|
||||
нагрузки, и поэтому «восемь красных подряд» **не является критерием приёмки**: сегодня, без единой правки,
|
||||
восьмёрка выпадает примерно в 82 случаях из 100.
|
||||
|
||||
⛔ **А вот ПРИЧИНА не та, что я написал.** Я заказывал «сделать приход байта ответа НЕИЗБЕЖНЫМ до обрыва».
|
||||
Зонд опровергателя (40 итераций, печать того, что реально получил клиент) дал **39 × обрыв с отказом
|
||||
записи и 1 × ПОЛНЫЙ `401`**, и ни разу — «ни куска, ни статуса». То есть байт приходит практически всегда,
|
||||
а мутант выживает в ДРУГОМ случае: клиент успевает вычитать `401` ЦЕЛИКОМ, `Do` возвращает не ошибку
|
||||
записи, а ОТВЕТ, и `delivered()` не спрашивают вовсе — ошибка уходит статусной веткой. **Моё лекарство
|
||||
било по половине, которая и так держится, и увеличивало вероятность ровно того исхода, в котором мутант
|
||||
выживает.** (И «~6 МБ тела» тоже неверно: 11.0 МБ — Go не эскейпит кириллицу в JSON.)
|
||||
|
||||
**Задача — делай РОВНО так в части ЧТО, способ твой:**
|
||||
1. **Тест утверждает СВОЮ ПОСЫЛКУ и печатает её:** что `Do` вернул ошибку ЗАПИСИ и что трасса видела
|
||||
первый байт. **Сценарий не состоялся ⇒ тест КРАСНЫЙ**, а не зелёный «мимо предмета». Сегодня он зелен и
|
||||
на полном `401`, то есть на другом предмете.
|
||||
2. **Прямой табличный пин на сам `delivered()`** — он убивает посадку `answered &&` детерминированно, без
|
||||
гонки вообще.
|
||||
3. ⚠ У фикстуры `MaxAttempts: 3` — до трёх бросков кости на один `Complete`; **границу утверждай ПО
|
||||
ПОПЫТКЕ**, а не по итогу вызова.
|
||||
|
||||
**Половина (а) — её первая редакция промта не заказывала вовсе.** Тот же ряд 379 несёт вторую половину:
|
||||
две строки таблицы девяти в `backend/internal/pipeline/cutcall_test.go:402`=`time.Sleep(50 * time.Millisecond)`
|
||||
разводятся ОКНОМ СТЕННЫХ ЧАСОВ, и по какую сторону границы заголовков сел `cancel()`, не утверждается
|
||||
ничем — замер приёмки дал **2 красных из 8**. **Ряд закрывается ТОЛЬКО вместе с этой половиной.**
|
||||
|
||||
⛔ **Критерий приёмки берётся из самого ряда 379, он сильнее моего:** «каждый из двух пинов **ПЕЧАТАЕТ
|
||||
величину, доказывающую пройденную границу, и ПАДАЕТ, когда сценарий не состоялся»**.
|
||||
|
||||
## 5. Где этот пак мягкий — четыре места, назвал я, веер и глубину выбираешь ты
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue