Issue the second backend fix prompt: the bank flag becomes a flag in the engine itself, which is the half of backlog row 191 that was deferred
This commit is contained in:
parent
fa511e65b5
commit
3a719b442f
2 changed files with 534 additions and 1 deletions
533
docs/BACKEND_SEAM_FIX2_SESSION_PROMPT.md
Normal file
533
docs/BACKEND_SEAM_FIX2_SESSION_PROMPT.md
Normal file
|
|
@ -0,0 +1,533 @@
|
|||
# Промт: БЭКЕНД ДОФИКС-2 «ВХОДНАЯ ДВЕРЬ ШВА» — флажок становится флажком, точка фиксации отчёта, фикс-лист приёмки
|
||||
|
||||
> Выдан оркестратором №19, 25.08.2026. Активный промт зоны бэкенда — один; этот заменяет
|
||||
> `BACKEND_SEAM_FIX_SESSION_PROMPT.md` (отработан, уезжает в архив при лендинге).
|
||||
> Параллельно законен только `platform/docs/PLATFORM_P8_REVIEW_SESSION_PROMPT.md` (read-only, пересечений нет).
|
||||
|
||||
## 1. Какая проблема и что решит твой результат
|
||||
|
||||
Продукт — издательский перевод больших книг мультиагентным пайплайном. Центральная ценность —
|
||||
**банк памяти**: сквозной глоссарий имён и терминов, держащий консистентность на всю книгу.
|
||||
|
||||
Две предыдущие сессии построили **входную дверь**: `tmctl bank-apply` принимает решения владельца
|
||||
данными, а не правкой YAML руками. Дофикс закрыл блокер формата и восемь мажоров. Приёмка прошла и
|
||||
снова не приняла — но главная её находка не в двери.
|
||||
|
||||
**Продуктовая модель, ратифицирована D39.144 прямым словом владельца:** стоп банка — это **флажок**.
|
||||
Опущен — прогон не останавливается, неподписанные строки едут редактору с пометкой. Поднят — полный
|
||||
останов, пользователь говорит «ОК», прогон продолжается. Пер-термной подписи в продукте **нет**:
|
||||
владелец подписывает банк целиком либо правит один термин, и правка — отдельная способность,
|
||||
доступная всегда, в том числе после перевода.
|
||||
|
||||
**Движок этой модели не реализует.** Стоп гаснет, только когда КАЖДАЯ предложенная поверхность
|
||||
промотирована или отклонена. Продукт ведёт себя правильно исключительно потому, что **платформа
|
||||
снимает флаг при возобновлении** своей персистентной колонкой.
|
||||
|
||||
⚠ **Это НЕ новое открытие, и провенанс записан — прочти его прежде, чем проектировать.** Формула
|
||||
«стоп гаснет, когда каждый терм промотирован или отклонён» родилась В ДВИЖКЕ 19.07 как лечение
|
||||
ливлока (отклонённый терм переспрашивался каждый прогон), то есть как условие выхода из паузы
|
||||
ОПЕРАТОРА CLI. Контрактная линия три недели спустя переписала её дословно и вывела продуктовое
|
||||
правило, которого никто не заказывал. D39.144 гейт сняла, но адресовала только КОНТРАКТ — движковая
|
||||
половина осталась без явной отмены и сегодня ОБОЙДЕНА, а не устранена. Носитель — строка бэклога
|
||||
**191(б)**, эррата — в шапке журнала решений (D39.153 п.7б).
|
||||
|
||||
⚠ **Слово владельца 26.08, ПЯТЫЙ и решающий носитель:** «стоп на банке памяти — это просто флажок.
|
||||
Юзер поднял флаг — полный останов до его ОК; опустил — перевод не останавливается. Всё». Канонизации
|
||||
в жесте «ОК» НЕТ: он значит «продолжай», а не «сделай предложенное каноном».
|
||||
|
||||
⚠⚠ **И РАЗБЕРИСЬ С ОДНИМ ПРОТИВОРЕЧИЕМ ДО КОДА, иначе ты встанешь на нём по §11.** Строка бэклога 191
|
||||
говорит: «ОСТАТКА-РАТИФИКАЦИИ НЕТ… гейт проверяет полноту ФАЙЛА решений, а не подписей, и ОДИН файл
|
||||
со всем банком его снимает — конфликта с моделью владельца нет». Это **не ошибка строки и не
|
||||
опровержение промта** — она отвечала на ДРУГОЙ вопрос. Сверялось составное поведение: платформа
|
||||
снимает флаг, движок уходит по авто-ветке, зависания нет. Верно. Но её же живой остаток записан там
|
||||
дословно — «снять обход в платформе», — и **снятие обхода возвращает границу паузы в несущие**.
|
||||
Её пункт (б) заказывал «проверить/ослабить границу самой паузы»; исполнено было только «проверить».
|
||||
Ты делаешь отложенное «ослабить», и делаешь его в движке, потому что по п.1 закона поведение движка
|
||||
принадлежит движку, а не колонке чужой базы. Эррата к строкам 191 и 203(з) — на оркестраторе, при
|
||||
лендинге; тебе это знать, чтобы не встать.
|
||||
|
||||
⚠ **Модель ПЕРЕ-ОПРЕДЕЛЕНА пятью носителями — не выводи её заново, ни из кода, ни из разговора.**
|
||||
Нота D39.144 · продуктовый реестр `docs/product-requirements.md`, строка **ПТ-24** («ОДИН ОК всему
|
||||
банку, не пер-термная масс-подпись») · экран банка во фронте, где прямо написано, что пер-термного
|
||||
состояния подписи на экране нет СОЗНАТЕЛЬНО и колонка «подписано» спорила бы с продуктом · надгробие
|
||||
снесённой ручки на платформе. Две сессии и два консилиума выводили её из кода и оба раза ошиблись.
|
||||
|
||||
⚠ **И гардрейл оттуда же, ПТ-24, дословно:** пост-ридинговые точечные правки с пере-генерацией по
|
||||
вхождениям — «механика **после полигона**». Значит **не проектируй** ничего про то, как правки
|
||||
работают ПОСЛЕ прочтения книги: ни глубины, ни отдельного цикла, ни новых полей под это. Смежный
|
||||
механизм точечной ре-редактуры уже существует и срабатывает на сдвиг банка — трогать его не надо.
|
||||
|
||||
**Твой результат: флажок работает как флажок в самом движке**, без участия чужой зоны, и вместе с
|
||||
этим закрывается точка фиксации отчёта, из-за отсутствия которой четыре раунда ревью подряд находили
|
||||
новую ветку одной дыры.
|
||||
|
||||
⚠ **Дерево двух предыдущих паков НЕ закоммичено и лежит в рабочем каталоге.** Ты продолжаешь его.
|
||||
|
||||
## 2. Зона записи и git
|
||||
|
||||
Пишешь ТОЛЬКО в `backend/`. Читать можешь всё; `platform/`, `frontend/`, `eval/`, `docs/` — чужие зоны,
|
||||
правки в них запрещены. **Единственное исключение:** пинги и итог сессии — в `docs/PROGRESS.md`, секция
|
||||
«Бэкенд». **Ты не коммитишь** — дерево готовишь и передаёшь на лендинг оркестратору (канон git-норм —
|
||||
`CLAUDE.md`). `git add -A`, `git add .`, `git commit -a` запрещены в любом случае. В дереве живёт
|
||||
незакоммиченная работа параллельных сессий — не трогай её и не «прибирай».
|
||||
|
||||
## 3. Карта чтения (пять позиций)
|
||||
|
||||
1. **`docs/architecture/05-decisions-log.md`, нота D39.144** целиком, **и эррата к ней в шапке
|
||||
журнала** (D39.153 п.7б). Это ратифицированная модель и история вопроса. ⚠ Читать ДО кода: две
|
||||
сессии подряд восстанавливали этот провенанс из кода, потратив на это раунды.
|
||||
2. **`docs/PROGRESS.md`, строка БЭКЛОГА 191** ⚠ ID строки ТАБЛИЦЫ, брать грепом `^| 191 |`. Носитель
|
||||
темы, открытый ровно под твою работу.
|
||||
3. **`docs/architecture/17-seam-inbound-law.md`** — закон входной двери. П.1 («движок владеет своим
|
||||
поведением») — то, что сегодня нарушено.
|
||||
4. **`backend/docs/SEAM_PACK_FINDINGS.md`** — доказательная база двух паков. Вход — §26. ⚠ Секции
|
||||
0–13 — улика первой приёмки, не трогай.
|
||||
5. **`docs/architecture/12-go-style-notes.md`** — норматив общности.
|
||||
|
||||
**Код первичен.** Все `file:line` ниже — отправные точки приёмки и сплошного чтения; проверяй сам.
|
||||
|
||||
## 4. Состав работы
|
||||
|
||||
Тринадцать пунктов (`grep -cE '^### 4\.'` → 13). §4.1–§4.4 — семантика флажка, §4.5–§4.8 — точка фиксации и полоса, §4.9–§4.12 —
|
||||
фикс-лист. Комплектность сверяется механически (§7).
|
||||
|
||||
### 4.1 «Остановиться один раз» становится родным для движка — ДЕЛАЙ РОВНО ТАК инвариант, РЕШИ САМ форму
|
||||
|
||||
Движок заводит персистентную **память «предъявленного стопом»** — поверхности, за которые флаг уже
|
||||
заплатил остановкой. Стоп срабатывает, только если в текущем наборе есть поверхность **вне
|
||||
запомненного**. Предикат — «есть ли новое», **не равенство наборов**: равенство остановило бы снова
|
||||
на подмножестве уже виденного после первой же правки.
|
||||
|
||||
⚠⚠ **Домен предиката задан жёстко, и промахнуться тут дорого.** «Набор» — это **содержимое КАРТЫ
|
||||
этого стопа, обе секции, ПОСЛЕ всех потолков**; память — кластеры этого содержимого. Прочтение «набор
|
||||
= ранжированный пул ДО потолка» превращает флажок в ВЕЧНЫЙ стоп: постоянно невидимые за потолком
|
||||
поверхности (§4.4) делают «есть новое» истинным на каждом прогоне навсегда.
|
||||
|
||||
**Проектные решения, каждое с доводом — они выведены сплошным чтением, не догадкой:**
|
||||
|
||||
- **Ключ — нормализованная поверхность** (`text.NormalizeSourceKey`, тот же, что у отказов и двери),
|
||||
**а не пара (поверхность, перевод)**: предложенный перевод двигается от подписи СОСЕДНИХ термов
|
||||
(`terminologist.go`, ранжирование вариантов через `approvedNeighbours`), и память по паре дала бы
|
||||
вечные стопы.
|
||||
- ⚠ **Эмиссия работает КЛАСТЕРАМИ, а не поверхностями.** Представитель кластера — первый в
|
||||
ранжированном пуле, и при росте книги он может смениться на алиас той же сущности. Память по одной
|
||||
поверхности этого не переживёт — лишний стоп на том же термине. Клади в память кластер (`Src` и
|
||||
`Aliases`, они уже посчитаны) и спрашивай про пересечение, а не про одну поверхность.
|
||||
⚠ Остаток у кластерной памяти ДВУСТОРОННИЙ, и записать надо обе стороны, а не только удобную.
|
||||
**Мягкая:** сущность вернётся под написанием, которого в памяти нет — один лишний стоп, потерь нет.
|
||||
**Вредная:** подлинно НОВАЯ сущность, делящая поверхность-алиас с запомненным кластером (родной
|
||||
пример репозитория — одно прозвище на двух разных персонажей), пересечением пометится виденной и
|
||||
**не будет предъявлена молча**. Смягчено тем, что терм всё равно поедет редактору авто-строкой, но
|
||||
направление противоположное. Обе — ПРИНЯТЫЕ ОСТАТКИ, обе в отчёт.
|
||||
- **Где живёт.** Состояние КНИГИ, в store. ⚠ Прецеденты, которые я называл в прошлой редакции
|
||||
промта, **прецедентами не являются**, и я это снимаю: список отказов — ФАЙЛ рядом с книгой, а
|
||||
`unitOnceKey` живёт в `events_outbox`, который сам себя называет БУФЕРОМ, а не архивом, и чистится.
|
||||
Форму долговременного состояния книги выбираешь ты и аргументируешь.
|
||||
- ⚠ **Цена миграции названа заранее.** Новая ТАБЛИЦА (`CREATE TABLE IF NOT EXISTS`) — дешёвая форма;
|
||||
`ALTER` существующей упирается в известный долг «шаги v8+ не идемпотентны» (строка 49а). Любая
|
||||
миграция двигает голову схемы, а `OpenReadOnly` отказывает при несовпадении — то есть все
|
||||
непере-мигрированные книги встают, и это ровно дедлок, который закрывали глаголом `tmctl migrate`.
|
||||
Порядок деплоя это покрывает, но в отчёте назови явно.
|
||||
- Книга без базы: отсутствие базы уже трактуется как «ничего не решено» — память унаследует «ничего
|
||||
не предъявлено», и это правильно.
|
||||
- **Политика роста: НЕ обрезать.** Память ⊆ намайненного словаря книги — тот же закон роста, что у
|
||||
списка отказов, который никто не обрезает. Без этой строки исполнитель изобретёт TTL и тем вернёт
|
||||
повторные стопы через заднюю дверь.
|
||||
|
||||
### 4.2 Порядок и момент записи — ДЕЛАЙ РОВНО ТАК
|
||||
|
||||
**Сначала карта (атомарно), потом память.** Падение между — лишний доброкачественный стоп на
|
||||
следующем прогоне; обратный порядок — поверхности помечены предъявленными, а карты нет: молчаливая
|
||||
потеря навсегда.
|
||||
|
||||
⚠ **Это зависит от §4.10: карта сегодня пишется НЕ атомарно.** Порядок работ не свободен —
|
||||
атомарность карты идёт первой.
|
||||
|
||||
⚠ Между картой (файл) и памятью (SQLite) общей транзакции нет. Реши явно и назови: валит ли отказ
|
||||
записи памяти уже состоявшийся стоп, или стоп остаётся, а память допишется на следующем.
|
||||
|
||||
**Память пишется в момент СТОПА, не в момент «ОК».** Тогда возобновление остаётся вызовом без
|
||||
полезной нагрузки, и нового глагола не нужно. ⚠ **Никакого «подтверди карту» в дверь не заводить:**
|
||||
согласия, которое надо якорить, в модели владельца не существует — это была ошибка приёмки, снята.
|
||||
|
||||
⚠ Ветка «только черновая волна»: карта пишется, стопа нет — памяти по букве тоже нет. Доброкачественно,
|
||||
но назови.
|
||||
|
||||
### 4.3 Авто-провод обязан работать при ПОДНЯТОМ флаге — ДЕЛАЙ РОВНО ТАК
|
||||
|
||||
Сегодня авто-провод закрыт условием «флаг НЕ поднят»: в этой ветке пишется авто-банк, пере-сидируется
|
||||
банк, обновляется экспорт. С поднятым флагом — ничего этого нет.
|
||||
|
||||
Сегодня не кусает только потому, что платформа флаг снимает. **Ты этот сброс отменяешь** — значит
|
||||
прогон с поднятым флагом, который НЕ остановился (нового нет), обязан идти дальше **полноценно**:
|
||||
записать авто-банк, пере-сидировать, обновить экспорт. Иначе «неподписанные строки едут редактору»
|
||||
отваливается ровно в том режиме, ради которого всё делается.
|
||||
|
||||
Перестрой ветвление так, чтобы решение «останавливаться ли» и решение «проводить ли неподписанное»
|
||||
были РАЗНЫМИ решениями. Сегодня это одно `if`.
|
||||
|
||||
⚠ И назови в записке ВТОРУЮ половину, которую этот пункт словами не покрывает: пишет ли авто-банк
|
||||
прогон, который ОСТАНОВИЛСЯ. Через чекпоинты терминолога сходится в обе стороны, поэтому решение
|
||||
должно быть НАЗВАННЫМ, а не случайным.
|
||||
|
||||
### 4.4 Хвост за потолком — НЕ ЛЕЧИТЬ, а честно назвать — ДЕЛАЙ РОВНО ТАК
|
||||
|
||||
⚠ **Прежняя редакция этого промта заказывала фильтр карты как лекарство от голода. Заказ СНЯТ —
|
||||
он стоял на моей ошибке, и вот факт, который её опровергает.**
|
||||
|
||||
Потолок эмиссии (200) применяется **ДО** фильтров пригодности, сида и отказов, а детектор кандидатов
|
||||
сида и отказов не видит вовсе. Репозиторий это про себя знает: «*applied BEFORE the emission filters,
|
||||
so seed and declined terms do not free their slots*». Замерено сплошным читателем на синтетическом
|
||||
корпусе: 2110 ранжированных, 442 годных во всём алфавите, 117 внутри окна потолка, **325 невидимы
|
||||
постоянно**; отклонение всех 117 не подняло ни одного из 325.
|
||||
|
||||
Значит: **хвост за потолком недостижим при любом решении владельца, и это верно СЕГОДНЯ**, а не
|
||||
станет верным от твоей правки. Цитата про «пере-предлагается once these are signed or declined»
|
||||
относится к ОБРАТНОЙ секции, где фильтры действительно стоят до потолка.
|
||||
|
||||
**Заказ:** ничего не лечить. Назвать это в отчёте и **пингом** как отдельный предмет: «майнерский
|
||||
хвост за потолком структурно недостижим; двигать потолок — трогать фрозен-паритет, отдельное решение».
|
||||
⚠ **И не заводить фильтр карты «чтобы освободить хвост»** — он не освободит, а сломает три вещи:
|
||||
карта пишется на КАЖДОМ прогоне до проверки флага; отказы фильтруются на общем списке, из которого
|
||||
кормятся и карта, и авто-банк, и кандидаты терминолога (ветки после него нет); а смена состава
|
||||
кандидатов промахивается мимо чекпоинтов терминолога и **пере-оплачивает платную роль**.
|
||||
|
||||
### 4.5 Единая точка фиксации отчёта — ДЕЛАЙ РОВНО ТАК инвариант, РЕШИ САМ форму
|
||||
|
||||
**Класс, из-за которого четыре раунда ревью находили новую ветку одной дыры.** Отчёт рождается до
|
||||
того, как исход вызова существует, и каждая ветка выхода правит свой кусок руками. Ветка отказа
|
||||
откатывает три поля предупреждения; ветка прерывания откатывает режим, флаг и список — и **не
|
||||
откатывает `signature`**, поэтому вызов, не записавший ни байта, печатает «не решено: 0». А ветка
|
||||
записи не правилась никогда: **при отказе записи наружу уходит отчёт успешной формы**. Приёмка это
|
||||
воспроизвела: `EXIT=1`, отчёт `mode=apply changed=true`, оба решения `applied`, на диске дельта
|
||||
записана, реджекты пусты.
|
||||
|
||||
**Заказ — два движения, нужны оба:**
|
||||
|
||||
**(а) Разделить отчёт по природе полей.** *Вердикт о запросе* (что принято, что отвергнуто и почему,
|
||||
индексы, `replaced`, `preexisting`, `depth`, `files`) — факт о решениях против состояния ДО; его на
|
||||
диске нет и не будет. *Исход* (режим, `changed`, предупреждения о пере-рендере, `signature`) — факт о
|
||||
мире ПОСЛЕ.
|
||||
|
||||
**(б) Один конструктор на одном выходе.** Эффектная фаза возвращает ЯВНОЕ значение исхода — проекция ·
|
||||
отказ · no-op · прерывание · записано · запись не удалась — и единственная функция заполняет исходные
|
||||
поля свитчем по нему. Для «записано» пост-состояние — **перечитанные** файлы. Новая ветка тогда не
|
||||
сможет забыть поле: ей негде забывать. Пин — тест, перечисляющий исходы и проверяющий происхождение
|
||||
каждого поля.
|
||||
|
||||
⚠ Сильная форма «глагол вообще не сочиняет отчёт» НЕВЕРНА для вердиктной половины: причины отказов и
|
||||
история `replaced` на диске не лежат, и дверь потеряла бы собственный продукт.
|
||||
|
||||
### 4.6 `signature.undecided` пере-документируется, а не удаляется — ДЕЛАЙ РОВНО ТАК
|
||||
|
||||
Сегодня контракт поля говорит: «*Undecided > 0 значит, что стоп НЕ погаснет, и это факт, не догадка*».
|
||||
После §4.1 это **ложь**: стоп теперь зависит от памяти, а не от полноты решений. При этом канон
|
||||
понизил счётчик до информационного, а не до несуществующего — **не удаляй**.
|
||||
|
||||
Пере-документируй честно: что поле считает и чего оно больше не обещает. ⚠ И учти, что дверь
|
||||
открывает базу только на чтение — если ответ теперь требует памяти, реши, читает ли она её и на каком
|
||||
основании, или поле перестаёт отвечать на вопрос о стопе вовсе.
|
||||
|
||||
### 4.7 Полоса отказов получает два яруса — ДЕЛАЙ РОВНО ТАК
|
||||
|
||||
- **Пол полосы** переформулируется из «ничего не произошло» в **«нет работы, которую надо откатывать;
|
||||
повтор безопасен»**. «Повтор безопасен» = «не навредит», НЕ «поможет».
|
||||
- **Каждый класс поверх пола объявляет свой, более сильный инвариант.** Конфиг, источник, лок и
|
||||
отвергнутые решения сохраняют «ничего не произошло» как клаузу КЛАССА.
|
||||
- **Гардрейл:** разрушительное действие ключуется **только на классе**, никогда на принадлежности
|
||||
полосе. Сегодня истинно де-факто (проверено приёмкой) — становится буквой без миграции.
|
||||
- **Один новый класс на «запись не завершена»** — и для «не легло ничего», и для «легла половина»:
|
||||
потребитель ветвится одинаково, различие несёт пофайловый отчёт. Не сворачивать в класс конфига.
|
||||
- **Класс отвергнутых решений однофóрмен:** отказ по капу тоже печатает отчёт. Сегодня он печатает
|
||||
только строку в stderr, и контракт разошёлся между двумя своими носителями — свести к одному.
|
||||
|
||||
### 4.8 Подготовка обоих файлов, потом два переименования — ДЕЛАЙ РОВНО ТАК
|
||||
|
||||
Подготовить ОБА временных файла целиком (запись + синк), и только потом два переименования подряд.
|
||||
Тогда весь класс отказов среды ловится **до первого сдвинутого байта**, и репро §4.5 падает, ничего
|
||||
не записав.
|
||||
|
||||
⚠ **Не заявляй шире сделанного:** это атомарность **против ошибок среды**, не против смерти процесса —
|
||||
окно между переименованиями остаётся, и против SIGKILL атомарность пары требует журнала, механизма,
|
||||
которого дверь не заслужила. Остаток покрыт замеренной сходимостью (приёмка померила: повтор после
|
||||
половинной записи сходится и ПРАВИЛЬНО различает половины), а убитый процесс отчёта не печатает.
|
||||
|
||||
⚠ Отдельно: запись синкает файл перед переименованием, но не синкает КАТАЛОГ после. Файлы решений —
|
||||
слова пользователя: либо синк каталога, либо явная оговорка про долговечность.
|
||||
|
||||
### 4.9 `Clean` в резолве и конвенционные пути вместо ключей — ДЕЛАЙ РОВНО ТАК
|
||||
|
||||
**(а)** Попарная проверка путей сравнивает СТРОКИ, а резолв возвращает абсолютный путь без
|
||||
`filepath.Clean`. Приёмка обошла гард и воспроизвела **исходный блокер целиком**: два ключа на
|
||||
`<dir>/shared.yaml` и `<dir>/./shared.yaml` → `exit 0`, оба решения `applied`, на диске только
|
||||
reject-лист, одобрение исчезло молча, следующий вызов включая `--dry-run` падает `exit 10`.
|
||||
|
||||
**(б) Убрать оба ключа конфига: пути только конвенцией.** Тогда путь есть функция от каталога и
|
||||
`book_id`, и межкнижная гонка недостижима по построению. Цена замерена: из 42 `book.yaml` ни один не
|
||||
объявляет читаемый путь, отличный от конвенции. Миграция громкая и дешёвая: строгий декодер уронит
|
||||
книгу с объявленным ключом, лечение — удалить две строки.
|
||||
|
||||
### 4.10 Карта подписи: атомарная запись и конверт — ДЕЛАЙ РОВНО ТАК
|
||||
|
||||
Карта пишется голым `os.WriteFile` в обход атомарной записи — единственный артефакт стопа без неё,
|
||||
при том что её читает другая сторона, а операционное правило платформы прямо говорит «на живом
|
||||
прогоне брать нельзя». С §4.2 это перестаёт быть гигиеной.
|
||||
|
||||
И у карты **нет никакой идентичности** — ни версии, ни хеша: единственный артефакт шва вне п.3 закона.
|
||||
Заведи конверт с версией и идентификатором, выведенным из СОДЕРЖИМОГО.
|
||||
|
||||
⚠ **Карту не превращать в накопитель:** комментарий в коде предупреждает, что слияние старой карты в
|
||||
новую изменило бы содержимое банка, сдвинуло версию памяти и пере-оценило редакторскую волну.
|
||||
|
||||
### 4.11 Слепые пятна гейта — ДЕЛАЙ РОВНО ТАК
|
||||
|
||||
Каждое — место, где приёмка посадила мутацию и **батарея осталась зелёной**; все пере-проверены во
|
||||
всех четырёх кандидатных пакетах пина.
|
||||
|
||||
| что не сторожится | мутация, которую пин обязан поймать |
|
||||
|---|---|
|
||||
| нормализация, суженная до одного триггера вместо класса | `normText`: `TrimSpace` → `TrimLeft(s, "\n")` |
|
||||
| субъект проблемы схлопывается до класса | `subjectOf` возвращает только `class` |
|
||||
| субъект теряет окно глав | `subjectOf` без `since`/`until` |
|
||||
| абсолютность путей в отчёте `bank-apply` (в статусе та же гарантия запинена) | убрать приведение к абсолютному |
|
||||
| границы обоих капов | `>` → `>=` |
|
||||
| граница проверки перевёрнутого окна | `>` → `>=`, отвергает законное одноглавное окно |
|
||||
|
||||
⚠ **И самое неприятное: сегодня семантическое изменение §4.1 не краснит НИ ОДИН тест бэкенда.**
|
||||
Это само по себе находка. Твой пак обязан завести пин, который краснеет от возврата к старой
|
||||
семантике, — иначе следующая сессия вернёт её молча.
|
||||
|
||||
### 4.12 Наследие отменённой модели — снести СПИСКОМ — ДЕЛАЙ РОВНО ТАК
|
||||
|
||||
⚠ Список, а не память сессии: починишь гейт и оставишь сообщение — следующий читатель движка выучит
|
||||
отменённую модель из его же слов.
|
||||
|
||||
- **Гейт «стоп гаснет от полного набора решений»** — снимается §4.1.
|
||||
- **Операторское сообщение стопа**, дословно учащее «промотируй ИЛИ отклони КАЖДЫЙ терм, потом
|
||||
возобнови — стоп погаснет, когда решён каждый». Переписать под модель флажка.
|
||||
- **Комментарии `mining.go` в шапке функции стопа и у `unsignedEngineSurfaces`; `waverun.go`;
|
||||
рендер CLI** — сплошной читатель называет их поимённо, пройди по ним.
|
||||
- ⚠ **Новое состояние, которого раньше не было: «дельта непустая, нового нет».** Сегодня флаг меняет
|
||||
лишь уровень лога на пустой дельте; теперь оператор с поднятым флагом может не получить ничего, и
|
||||
молчание будет неотличимо от «майнинг не сконфигурирован». Нужна явная строка.
|
||||
- **Цепной тест** `TestTheStopClearsWhenTheOwnerDecidesTheWholeSignatureMap` — ⚠ **не удалять до
|
||||
§4.1** (подгонка зелени под доктрину). Он пройдёт и после §4.1, но по другой причине — потому что
|
||||
память погасит стоп, а не потому, что подписи что-то значат. **Перепиши его под новую семантику и
|
||||
назови замену явно.**
|
||||
- **ПИНГИ ЧУЖИМ ЗОНАМ, не правки:** у платформы умирает сброс флага, особый случай в спавне и
|
||||
персистентная колонка · во фронте и в полигоне есть потребители карты подписи, и смена её жанра их
|
||||
задела бы. Выпиши пингом в свою секцию журнала.
|
||||
⚠⚠ **И назови в пинге ПОРЯДОК, потому что опасная половина пишется легче.** Сброс флага платформой
|
||||
может умереть ТОЛЬКО ПОСЛЕ того, как §4.3 залендится в движке. Обратный порядок — и в день
|
||||
лендинга каждая книга с поднятым флажком перестаёт писать авто-банк и пере-сидироваться ровно в
|
||||
том режиме, ради которого флажок существует. Порядок деплоя «движок первым» это обеспечивает, но
|
||||
зависимость обязана быть НАПИСАНА, а не выведена.
|
||||
- **Миграционная нота:** после апгрейда пустая память даёт один доброкачественный стоп. Назвать.
|
||||
|
||||
### 4.13 Деньги: платных вызовов НОЛЬ — ДЕЛАЙ РОВНО ТАК
|
||||
|
||||
Санкции нет и не запрашивается. Всё проверяется юнит-тестами, фейковым провайдером и пробой на копии
|
||||
книги стенда. Упёрся в место, где без денег не доказать, — **пинг с названной суммой, не трата**.
|
||||
Рантайм-вердикт по платному пути остаётся PLAUSIBLE.
|
||||
|
||||
⚠ **Гипотеза о побочном выигрыше — НЕ выгода, пока не предъявлен механизм.** Есть подозрение, что
|
||||
подписание сегодня промахивается мимо чекпоинтов терминолога и пере-оплачивает платную роль (ключ
|
||||
чекпоинта — хеш отрендеренных сообщений, а состав кандидатов меняется от дельты и отказов). Память
|
||||
предъявленного эти входы **не трогает**, поэтому «память чинит перерасход» механизмом не подтверждено
|
||||
и в отчёт как выигрыш идти не должно. Если увидишь механизм — покажи `file:line`; если перерасход
|
||||
существует сам по себе — это отдельный предмет и **пинг**, не твой заказ.
|
||||
|
||||
## 5. Мандат самопроверки ИСПОЛНЕНИЕМ
|
||||
|
||||
Не «перечитал» — **исполнил**. Минимум:
|
||||
|
||||
- **Батарея целиком, ИЗ КАТАЛОГА `backend/`**, после каждой содержательной правки: `go build ./...`,
|
||||
`go vet ./...`, `go test ./... -count=1`, `make lint`. ⚠ `go.mod` в корне репозитория НЕТ.
|
||||
⚠ **И `make battery-stand` минимум один раз в конце.** Ожидаемая картина: всё зелено, кроме парити
|
||||
на отсутствующем jieba-контрасте (вне git по построению, строка 123 — не твой дефект).
|
||||
Красный тест не «подгоняется»: править или удалять тест, голден или гейт ради зелени — **НЕДОПУСТИМО**.
|
||||
⚠ В `internal/store` два пред-существующих `-race`-флейка, оба меряют ВРЕМЯ; приёмка доказала тремя
|
||||
путями, что они не от паков. Красное именно в них — шум.
|
||||
- **Каталог мутаций расширяется:** `cmd/tmmutate` + `mutations.json` несут 36 записей; каждая правка
|
||||
§4 обязана получить свою. ⚠ Инструмент честен — приёмка подсунула ему несобирающуюся посадку, он
|
||||
назвал её `NOTHING`, а не «поймано»; не сломай это свойство. ⚠ Посадка называет ПАКЕТ, в котором
|
||||
ищется пин, — не тот, где лежит правка.
|
||||
- **Живая проба на копии книги стенда**; в `books/` не писать вовсе — чужой git-репозиторий.
|
||||
- **Субагенты РАЗРЕШЕНЫ явно** — на ревью своего кода, на поиск дефектов вне карты, на опровержение
|
||||
твоих же выводов. ⚠ Соразмеряй параллельность с ресурсами: агенты, одновременно гоняющие полную
|
||||
батарею, топят друг друга, а упавший от нагрузки выглядит как отсутствие находок.
|
||||
- **Артефакт-находки обязателен:** дописывай `backend/docs/SEAM_PACK_FINDINGS.md` новой секцией, не
|
||||
переписывая старые — они улика двух приёмок.
|
||||
|
||||
### 5.1 Обязательное для кодового пака
|
||||
|
||||
- **Последний абзац отчёта — план или обещание? Сделай его СЕЙЧАС.**
|
||||
- **Дифф `^func Test` — исполнением.**
|
||||
- **Интервальная самоверификация субагентом** против явных критериев в середине работы.
|
||||
- **Перед отчётом сверь каждый клейм с результатом инструмента ЭТОЙ сессии.**
|
||||
- ⚠ **Закрытие проверяется ОТДЕЛЬНО от починки и не тем, кто чинил.** Предыдущая сессия вывела это
|
||||
правило сама: её собственная проверка закрытия нашла три незакрытых пункта из 28, а приёмка — ещё
|
||||
два частично закрытых, один из которых вернул исходный дефект.
|
||||
- ⚠ **И правило, которое стоило этому проекту трёх раундов подряд: прежде чем проектировать —
|
||||
прочти ратифицированное.** Две сессии и два консилиума восстанавливали из кода то, что лежало
|
||||
записанным в журнале решений. Твоя карта чтения начинается с ноты не случайно.
|
||||
|
||||
## 6. Оси ревью (три)
|
||||
|
||||
1. **Семантика флажка** — делает ли движок то, что описано в D39.144, **без участия платформы**.
|
||||
Проверяется прогоном движка напрямую, а не через её код.
|
||||
2. **Единая точка фиксации** — для каждой ветки выхода: откуда взято каждое поле отчёта, и может ли
|
||||
новая ветка забыть поле. Если может — конструктор не сделан.
|
||||
3. **Слепота гейта** — какой мутацией сторожится каждая правка и краснеет ли пин НА САМОМ ДЕЛЕ.
|
||||
|
||||
Ты вправе ЗАМЕНИТЬ любую ось своей с аргументом.
|
||||
|
||||
## 7. Записка-план
|
||||
|
||||
До кода — короткая записка `backend/docs/SEAM_FIX2_PLAN.md`: что делаешь, в каком порядке, какие
|
||||
развилки видишь. Комплектность против §4 сверяется МЕХАНИЧЕСКИ: `grep -cE '^### 4\.'` обязан дать **13**, а не глазами.
|
||||
|
||||
⚠ **Пак большой.** Если считаешь, что семантика флажка (§4.1–§4.4) и точка фиксации (§4.5–§4.8)
|
||||
должны ехать разными паками — скажи это аргументом, это законный ответ по §11. Мой довод за один пак:
|
||||
обрамление отчёта умирает в обоих, и разделение повторило бы ровно ту патологию «починить одну ветку»,
|
||||
из-за которой четыре раунда находили новую.
|
||||
|
||||
## 8. Заявление = команда
|
||||
|
||||
Каждое число и каждая категорика в отчёте — **с командой, которой получены, прямо рядом**. Приёмка
|
||||
пере-раняет выборочно.
|
||||
|
||||
⚠ Прошлый пак дал повод: довод к правке общего гейта в `backend/Makefile` называет **558 с** на
|
||||
`internal/pipeline` под `-race` — «93 % дефолта». Приёмка померила дважды: **92.8 с** в батарее и
|
||||
**97.6 с** изолированно. Явление настоящее, правку не откатывай — но **довод перепиши на верные числа
|
||||
и без привязки к машине**: репозиторный файл не должен говорить «на этой машине».
|
||||
|
||||
## 9. Эхо-протокол старта
|
||||
|
||||
ДО работы — не больше десяти строк: скоуп как ты его понял · инварианты, которые не тронешь · что
|
||||
делать НЕ будешь.
|
||||
|
||||
## 10. Что НЕ удалось
|
||||
|
||||
Обязательная секция отчёта. «Не проверено» ≠ «работает». Вердикт о рантайме без живого прогона —
|
||||
максимум PLAUSIBLE.
|
||||
|
||||
## 11. Канал вопросов
|
||||
|
||||
Конфликт промта с кодом или доками — **пинг через владельца, не интерпретация**. Ты вправе сказать
|
||||
«этого делать не надо» с аргументом. §4.2, §4.4, §4.6 и §7 прямо приглашают такой ответ.
|
||||
|
||||
---
|
||||
|
||||
## Приложение: что приёмка и сплошное чтение ПОДТВЕРДИЛИ — не чини заново
|
||||
|
||||
- **Блокер формата закрыт на уровне инварианта:** round-trip держится на всех текстовых полях обоих
|
||||
документов на девяти неудобных значениях.
|
||||
- **Каталог мутаций воспроизведён** оркестратором: 36 посадок, 0 неожиданных исходов, дерево чистое.
|
||||
- **Оба капа работают**; **цепь** доходит до редакторской волны; **батарея зелёная**, линтер 0 issues;
|
||||
стенд-батарея красна ровно на парити.
|
||||
- **Рукописные поля владельца переживают решение** — род, тип, склонение с формами, алиасы, голоса.
|
||||
- **Идемпотентность работает в отказе:** после половинной записи повтор сходится и правильно различает
|
||||
половины.
|
||||
- **Мины со снапшотом с этой стороны НЕТ:** ни карта, ни таблицы, ни новая таблица store в версию
|
||||
памяти не входят — предупреждение в коде касается накопления в авто-банке.
|
||||
- **Ключ по поверхности, а не по паре** — подтверждён сплошным чтением с доводом сильнее исходного.
|
||||
- **Отказы и память не дублируются:** отказ гасит кластер и работает ещё на входе в банк и в обратной
|
||||
секции; память — только про стоп. Слить их нельзя: отклонённый терм поедет редактору.
|
||||
|
||||
## Приложение: пинги, которые дофикс-2 НЕ исполняет
|
||||
|
||||
- **Майнерский хвост за потолком структурно недостижим** (§4.4) — отдельный предмет.
|
||||
- **Банк-экспорт на стопе ПУСТ** (замерено сплошным читателем: `total=0`), при том что комментарий
|
||||
рядом называет стоп «границей, которую читает экран подписи», а машинную таблицу стопа не читает
|
||||
никто. Предмет платформенно-продуктовый, не твой.
|
||||
- **exit 2 при нехватке памяти читается платформой как успешный прогон с флагами** — общедвижковый класс.
|
||||
- **`readEngine` платформы выбрасывает stdout при любом ненулевом коде, кроме 2** — требование к
|
||||
платформенному паку: отчёт при отказе И ЕСТЬ продукт вызова.
|
||||
- **Развилка про канал ключей `redrive`** · **`rubyToCandidates` мёртв в проде** · **гейт диспетча слеп
|
||||
к `case` с константой** · **схема сида без `omitempty`** — пинги прошлых паков, остаются пингами.
|
||||
- **Проекция берёт тот же лок, что и применение** — проектируется платформенным паком.
|
||||
|
||||
---
|
||||
|
||||
## Записка от бэкенд-сессии двух предыдущих паков (написана до компакта её контекста, 27.08)
|
||||
|
||||
Я — сессия, которая строила дверь и оба дофикса. Дерево НЕ закоммичено, ты его продолжаешь. Здесь не
|
||||
инструкции — реонбординг: где что лежит, что я подтверждаю своим контекстом, на чём обжигался. Свежий
|
||||
взгляд с нуля ценнее моих планов, поэтому планов нет. ⚠ Прежняя моя записка (онбординг в формат и
|
||||
историю) живёт в хвосте `BACKEND_SEAM_FIX_SESSION_PROMPT.md` и уедет в архив — несущее повторено здесь.
|
||||
|
||||
### Реонбординг в код — обе точки входа разобраны на ИМЕНОВАННЫЕ фазы, и это твой рычаг
|
||||
|
||||
- `internal/membank/decisions.go` — чистая семантика. `ApplyDecisions` = `resolveAll` →
|
||||
`refuseSeedConflicts` → `foldAccepted` → `refuseInertDeclines` → `refuseNewFaults`; мутирует РОВНО
|
||||
одна фаза (`foldAccepted`), остальные судят. Прочитать пять имён = прочитать контракт двери.
|
||||
- `internal/pipeline/bankdecisions.go` — обвязка: `openDecisionRequest` → лок → `readBookState` →
|
||||
`ApplyDecisions` → `decisionReport` → `changedFiles` → `writeDecisionFiles`. **§4.5 садится ровно
|
||||
сюда**: отчёт рождается в `decisionReport` ДО исхода, и каждая ветка выхода после неё правит поля
|
||||
руками. Подтверждаю оба репро приёмки из своего контекста — это мои недочинки: stopped-ветка чинит
|
||||
`mode`/`changed`/`accepted` и НЕ трогает `signature` (он считается в `signatureState`, поле
|
||||
`unreadable` там уже есть — пригодится в §4.6); ветка отказа записи не правилась никогда.
|
||||
- §4.1–§4.3 живут в `internal/pipeline/mining.go`: `runBankMiningStop` — стоп и авто-провод сегодня
|
||||
действительно одно `if !r.VerifyBank`; рядом `unsignedEngineSurfaces` (фильтр «подписанного»),
|
||||
`ownerHandled`, `rejectSurfaces`, `signatureMapPath` (есть и пакетный помощник, не только метод).
|
||||
Store: `internal/store/store.go`, схема v15, `tmctl migrate` есть, `LockProject`/`OpenReadOnly` готовы.
|
||||
- Карта «предмет → пин»: `membank/decisions_test.go` (семантика) · `decisions_fuzz_test.go`
|
||||
(round-trip, три фаззера) · `pipeline/bankdecisions_test.go` (обвязка, классы, стоп-путь) ·
|
||||
`bankchain_test.go` (цепь; НАМЕРЕННО писан под старую семантику — §4.12 велит переписать; сохрани
|
||||
его премисс-проверки, фикстура даёт ровно «2 терма = 1 approve + 1 decline») ·
|
||||
`statusartifacts_test.go` · `config/decisionpaths_test.go` · `cmd/tmctl/keysfile_test.go`.
|
||||
|
||||
### Инструмент, без которого не сдавай
|
||||
|
||||
`cmd/tmmutate`: `-root` ОБЯЗАТЕЛЕН и это должна быть КОПИЯ (`cp -a backend /scratch/x && cd /scratch/x
|
||||
&& go run ./cmd/tmmutate -root .`). 36 записей, три вердикта (RED / NOTHING / survives), зелёная база
|
||||
пакета ДО первой посадки. ⚠ Якоря записей — точные строки кода: твой рефакторинг их сдвинет, инструмент
|
||||
скажет громко — пере-указывай сразу, это нормально. Со мной это однажды случилось МОЛЧА (старая версия
|
||||
считала провал сборки красным, и две записи целую итерацию числились пойманными тестами, которые не
|
||||
могли отработать) — теперь `NOTHING` роняет гейт; промт прав, что это свойство ломать нельзя.
|
||||
|
||||
### Ловушки, каждая стоила мне прогона
|
||||
|
||||
1. **Живая проба на стенде**: копия ВНЕ дерева; мёртвые абсолютные пути в ТРЁХ файлах (`book.yaml`,
|
||||
`pipeline.yaml` и `pairs/zh-ru.yaml` — в последнем `prompts_root`, про него забываешь); база схемы
|
||||
v11 → `tmctl migrate` на копии; банк-стоп на этой машине НЕ воспроизводится (нет jieba-контраста) —
|
||||
для стопа и цепи бери харнесс `miningstop_join_test.go`, он $0 и уже гоняет всё это.
|
||||
⚠ К §4.9(б): стендовые `book.yaml` объявляют оба ключа — в КОПИИ удали эти две строки сам;
|
||||
на самом стенде это не твоя зона (пинг оркестратору отправлен, он в курсе).
|
||||
2. **Батарея**: полная на ненагруженной машине зелёная ЦЕЛИКОМ; два store-флейка изолированно через
|
||||
`-run` падают детерминированно на обеих сторонах A/B (сжатый `opTimeout`) — не отнеси на себя.
|
||||
Числа времени под нагрузкой параллельных сессий гуляют в 3–6 раз — не публикуй ни одного времени
|
||||
без пометки, была ли нагрузка (я на этом попался дважды: §8 промта — про меня).
|
||||
3. **Субагенты и копии пишут туда, куда смотрят**: перед каждым «финальным» прогоном —
|
||||
`git ls-files --others` и сверка sha256 копии с деревом.
|
||||
|
||||
### Правила, купленные тремя раундами ревью подряд — они теперь и в §5.1, но вот цена
|
||||
|
||||
- **Закрытие проверяет НЕ тот, кто чинил.** Моя собственная проверка закрытия нашла 3 незакрытых и
|
||||
7 частичных из 28 «исправленных»; ни одно моё «всё исправлено» за сессию не выдержало проверки.
|
||||
- **Сначала посадка, потом пин.** Дважды поймало ВАКУУМНЫЕ пины моего же авторства (пин, написанный
|
||||
первым, проверяет то, что и так верно).
|
||||
- **Худшие мои дефекты были НЕВЕРНЫМИ ДОВОДАМИ при верном коде** — комментарий здесь контракт,
|
||||
по которому следующая сессия действует. Довод без команды хуже отсутствия довода.
|
||||
|
||||
### Подтверждения, чтобы ты не тратил раунд на пере-открытие
|
||||
|
||||
- Репро §4.5 и §4.9(а) — честные, не оспаривай, воспроизводи и чини.
|
||||
- «Семантика §4.1 не краснит ни один тест» — правдоподобно и по моему знанию тестов: всё, что я запинил
|
||||
про стоп, запинено через РЕЗУЛЬТАТ двери, не через условие гашения.
|
||||
- `FINDINGS`: вход через §26; §§0–13 — улика первой приёмки, §§14–35 — мои; дописывай НОВЫМИ секциями.
|
||||
- Каталог мутаций: запись `G-byte-gate` — записанный ВЫЖИВШИЙ с доводом недостижимости; не «чини» её.
|
||||
- Обмен с оркестратором закрыт (прямой канал, 27.08), четыре факта оттуда:
|
||||
(1) ратификация нового класса полосы «запись не завершена» — НА НЁМ, тем же лендинг-актом, что эрраты
|
||||
к 191/203(з); тебе — только движковая сторона (значение, номер, один класс на оба исхода с пофайловой
|
||||
правдой в отчёте); (2) стендовые `book.yaml` с ключами снимает он/владелец — не твоя зона; его замер
|
||||
«42 файла, ЧИТАЕМЫХ отклонений от конвенции ноль» сходится с моим; (3) **заказ §8 УЖЕ ИСПОЛНЕН мной
|
||||
до компакта**: слово `idle` в `Makefile` было неверным (мой замер шёл под тремя параллельными
|
||||
сессиями), довод переписан на диапазон ~95 с (свободный хост) … ~560 с (три сессии) без привязки к
|
||||
машине; ложное «на незагруженной машине» в `FINDINGS` §31 тоже исправлено — НЕ делай этот пункт
|
||||
заново, только перепроверь; (4) ⚠ отчёт сплошного читателя, на котором стоит §4.4 (2110/442/117/325),
|
||||
**в репозиторий не попал** — числа промта без первоисточника в дереве; будешь на них опираться —
|
||||
пере-мерь сам, это признал сам оркестратор.
|
||||
|
||||
— бэкенд-сессия паков, до компакта
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
| Роль | Активный промт | Статус |
|
||||
|---|---|---|
|
||||
| Оркестратор | [ORCHESTRATOR_SESSION_PROMPT.md](ORCHESTRATOR_SESSION_PROMPT.md) | роль и нормы; счётчик роли — CURRENT-STATE |
|
||||
| Бэкенд | [BACKEND_SEAM_FIX_SESSION_PROMPT.md](BACKEND_SEAM_FIX_SESSION_PROMPT.md) | дофикс движковой половины входной двери шва по приёмке 25.08: блокер round-trip reject-документа + восемь мажоров + пять слепых пятен гейта; дерево пака НЕ закоммичено и продолжается, не начинается заново; запуск по слову владельца |
|
||||
| Бэкенд | [BACKEND_SEAM_FIX2_SESSION_PROMPT.md](BACKEND_SEAM_FIX2_SESSION_PROMPT.md) | дофикс-2 входной двери шва: флажок банка становится флажком В ДВИЖКЕ (отложенная половина строки 191б — «ослабить границу паузы»), единая точка фиксации отчёта, фикс-лист приёмки; дерево двух паков НЕ закоммичено и продолжается; запуск по слову владельца |
|
||||
| Платформа | [PLATFORM_P8_REVIEW_SESSION_PROMPT.md](../platform/docs/PLATFORM_P8_REVIEW_SESSION_PROMPT.md) | read-only ревью четырёх осей; запуск по слову владельца |
|
||||
| Полигон | [POLYGON_EXP2223_REDO_SESSION_PROMPT.md](POLYGON_EXP2223_REDO_SESSION_PROMPT.md) (отложенный — [POLYGON_PACKAGE4_SESSION_PROMPT.md](POLYGON_PACKAGE4_SESSION_PROMPT.md), строка 85) | фаза Д ИДЁТ; ⚠ живой носитель курса — в `eval/dovodka/`, какой именно называет зона (⚠ [POLYGON_PHASE_D_HANDOFF.md](POLYGON_PHASE_D_HANDOFF.md) — перекрытый снимок, читать не как курс) |
|
||||
| Фронт | активного НЕТ | **ЗОНА ЗАМОРОЖЕНА** (D39.136 п.2 + D39.147: разморозка отдельным словом владельца, не привязана к P7); перечень первого касания — в зонном журнале |
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue