AURORA-1848: лист и своды без null-полей + фронт (B) #242

Open
aep wants to merge 9 commits from feat/233-aurora-1848-sheet-json-no-pydantic-b into feat/233-aurora-1848-sheet-json-no-pydantic
Owner

Не мержить до merge PR A (#239) и PR #223 (AURORA-1838). Ветка содержит merge-коммит #223; после их merge ветка перебазируется на test, коммиты #223 уйдут из диффа.

Closes #233. Jira AURORA-1848 (эпик AURORA-1834). Стек на PR A (#239).

Что сделано

  • Бэк: у листа формы и сводов 1/2 в data нет null-полей (jsonb_strip_nulls(data) внутри json_build_object(...)::text).
  • Фронт: тесты updateCells на отсутствующие ключи (версия #223 достаточна, cellUtils.js не менялся), cell_updated всегда несёт value (undefined -> null, messageUtils.js), getDataRowId возвращает null (после strip у групповых строк нет line_id, иначе row_deleted уходил без row_id и сервер рвал WebSocket, I-3).
  • perf/perfkit/gen/grow.py: form4_ids не падает на ответах без null-полей.
  • Аудит null/undefined на фронте (31 место, без дефектов; добавлена проверка полезной нагрузки WebSocket): .superpowers/sdd/.../task-15-report.md.

BREAKING для потребителя, который отличает «ключ есть и равен null» от «ключа нет»: в data листа и сводов 1/2 нет null-полей (на любой глубине; {} и null в массивах остаются). Отчёты проектов, ответы путей записи (PATCH отдаёт null явно) и WebSocket — как раньше. Выгрузка Excel не меняется. Поведение jsonb_strip_nulls проверено вручную на PG 15.12 и 16.15: идентично.
test_summary2_sheets_smoke ослаблять не пришлось.
TanStack Table в dev-сборке пишет console.warn для undefined во вложенном accessorKey — не исправляем, в prod нет. EditCell.jsx:223 <textarea value={undefined}> — аналогичное dev-предупреждение, deferred.
X-DB-Time-Ms в B включает стоимость jsonb_strip_nulls: доля Python в A и B напрямую не сопоставима.

Тесты

  • Бэк (PG16, dfip_1848): 3 failed (те же 3 известных на test), 248 passed, 4 skipped. PG 15.12 (ветка + AURORA-1922): 3 failed (те же), 250 passed, 4 skipped.
  • Фронт: node --test utils/*.test.js 31/31 (по отчёту исполнителя), npm run build успешен; biome: добавленные файлы чисты, ошибки только в файлах из #223 / старых тестах.
  • perf -m "not stand": 3 failed в test_run_all.py (есть и на origin/test).

Чек-лист ручной проверки (D6)

  • FORM_2/AHR: второй пользователь заполняет пустую ячейку — первый видит значение без перезагрузки; то же с очисткой
  • вход в пустую ячейку и выход без ввода — без ошибки
  • выбрать групповую строку -> Удалить: сообщение об ошибке, соединение не рвётся (I-3)
  • свод 2: пустые ячейки «—», поиск работает; свод 1 открывается
  • отчёт проекта не изменился
  • сценарий соавтора на стенде PERF_TARGETS='FORM_2/AHR/*' PERF_COAUTHOR_RATES=1 PERF_REPEATS=1, page_ws_updates > 0 (выполняет контроллер)
  • до merge: compare_responses.py compare --mode strip-nulls на стенде; PG15 (проверено, см. комментарий)

Замер до/после — добавит контроллер после прогона на стенде. Пороги (свод 2 GO -30 %, FORM_2/AHR -10 % и меньший распакованный размер) не условие мержа, недобор — follow-up. openspec archive aurora-1848-sheet-json — только после merge B.

Rulings I made

  • R-6 (design #6): PATCH null в тесте — сначала 225, затем null.
  • R-7 (design #7): getDataRowId -> null вместо undefined.
  • R-8 (design #8): аудит дополнен проверкой полезной нагрузки WebSocket.
    (Рулинги R-1..R-5 фазы A — в PR #239.)

Находки

Маркер Суть Статус
T11.1 комментарий: тест «q1 без m1» — регрессионный, на test зелёный deferred
T11.2 тест «два обновления одной строки на замороженных данных» fixed c859ca1 (= M-8)
T13.1 test_patch_cell_null_is_explicit зависит от созданного им состояния (откат сессией) rejected
T13.2 длинные строки >120 rejected (стиль)
T15.1 EditCell.jsx:223 <textarea value={undefined}> — dev-предупреждение React при первом вводе deferred
T15.2 вложенный accessorKey с undefined — dev-предупреждение TanStack (в prod нет) rejected (design)
I-3 удаление групповой строки слало row_deleted без row_id (getDataRowId вернул undefined после strip), сервер падал на data["data"]["row_id"] и рвал WebSocket fixed c859ca1
M-7 buildCellUpdatedMessage нормализует только value rejected (INPUT-строки only; покрыто фиксом I-3)
M-8 нет теста глубоко вложенного отсутствующего блока fixed c859ca1
M-9 нет теста jsonb_strip_nulls на литерале против _strip_nulls fixed c859ca1
M-10 X-DB-Time-Ms в B включает стоимость jsonb_strip_nulls: доля Python в A и B не сопоставима напрямую deferred (оговорка рядом с замерами)
R-6 (design #6) PATCH null: сначала 225, затем null fixed (решение)
R-7 (design #7) getDataRowId возвращает null fixed c859ca1
R-8 (design #8) аудит Task 15 дополнен проверкой полезной нагрузки WebSocket fixed (решение)
O-6 на origin/test cellUtils.js импортирует './rowUtils' без .js — красный шаг требовал временной правки; тест «q1 без m1» зелёный и на test rejected
O-7 ошибки biome в файлах #223 (cellUtils.js, cellUtils.test.js:10,23, useWebSocket.js) и в старом тесте rowUtils.test.js:17-19 rejected (не наши)

Отложенное (deferred): T11.1, T15.1, M-10; из A: T5.2, T6.2, T7.4, T7.6, M-2, O-3 (rf-rollup r.year).

🤖 Generated with Claude Code

**Не мержить до merge PR A (#239) и PR #223 (AURORA-1838). Ветка содержит merge-коммит #223; после их merge ветка перебазируется на `test`, коммиты #223 уйдут из диффа.** Closes #233. Jira AURORA-1848 (эпик AURORA-1834). Стек на PR A (#239). ## Что сделано - Бэк: у листа формы и сводов 1/2 в `data` нет null-полей (`jsonb_strip_nulls(data)` внутри `json_build_object(...)::text`). - Фронт: тесты `updateCells` на отсутствующие ключи (версия #223 достаточна, `cellUtils.js` не менялся), `cell_updated` всегда несёт `value` (`undefined` -> `null`, `messageUtils.js`), `getDataRowId` возвращает `null` (после strip у групповых строк нет `line_id`, иначе `row_deleted` уходил без `row_id` и сервер рвал WebSocket, I-3). - `perf/perfkit/gen/grow.py`: `form4_ids` не падает на ответах без null-полей. - Аудит null/undefined на фронте (31 место, без дефектов; добавлена проверка полезной нагрузки WebSocket): .superpowers/sdd/.../task-15-report.md. **BREAKING** для потребителя, который отличает «ключ есть и равен null» от «ключа нет»: в `data` листа и сводов 1/2 нет null-полей (на любой глубине; `{}` и null в массивах остаются). Отчёты проектов, ответы путей записи (PATCH отдаёт null явно) и WebSocket — как раньше. Выгрузка Excel не меняется. Поведение `jsonb_strip_nulls` проверено вручную на PG 15.12 и 16.15: идентично. `test_summary2_sheets_smoke` ослаблять не пришлось. TanStack Table в dev-сборке пишет `console.warn` для `undefined` во вложенном `accessorKey` — не исправляем, в prod нет. `EditCell.jsx:223` `<textarea value={undefined}>` — аналогичное dev-предупреждение, deferred. `X-DB-Time-Ms` в B включает стоимость `jsonb_strip_nulls`: доля Python в A и B напрямую не сопоставима. ## Тесты - Бэк (PG16, dfip_1848): 3 failed (те же 3 известных на test), 248 passed, 4 skipped. PG 15.12 (ветка + AURORA-1922): 3 failed (те же), 250 passed, 4 skipped. - Фронт: `node --test utils/*.test.js` 31/31 (по отчёту исполнителя), `npm run build` успешен; biome: добавленные файлы чисты, ошибки только в файлах из #223 / старых тестах. - perf `-m "not stand"`: 3 failed в test_run_all.py (есть и на origin/test). ## Чек-лист ручной проверки (D6) - [ ] FORM_2/AHR: второй пользователь заполняет пустую ячейку — первый видит значение без перезагрузки; то же с очисткой - [ ] вход в пустую ячейку и выход без ввода — без ошибки - [ ] выбрать групповую строку -> Удалить: сообщение об ошибке, соединение не рвётся (I-3) - [ ] свод 2: пустые ячейки «—», поиск работает; свод 1 открывается - [ ] отчёт проекта не изменился - [ ] сценарий соавтора на стенде `PERF_TARGETS='FORM_2/AHR/*' PERF_COAUTHOR_RATES=1 PERF_REPEATS=1`, `page_ws_updates > 0` (выполняет контроллер) - [ ] до merge: `compare_responses.py compare --mode strip-nulls` на стенде; PG15 (проверено, см. комментарий) Замер до/после — добавит контроллер после прогона на стенде. Пороги (свод 2 GO -30 %, FORM_2/AHR -10 % и меньший распакованный размер) не условие мержа, недобор — follow-up. `openspec archive aurora-1848-sheet-json` — только после merge B. ## Rulings I made - R-6 (design #6): PATCH null в тесте — сначала 225, затем null. - R-7 (design #7): `getDataRowId` -> `null` вместо `undefined`. - R-8 (design #8): аудит дополнен проверкой полезной нагрузки WebSocket. (Рулинги R-1..R-5 фазы A — в PR #239.) ## Находки | Маркер | Суть | Статус | |---|---|---| | T11.1 | комментарий: тест «q1 без m1» — регрессионный, на test зелёный | deferred | | T11.2 | тест «два обновления одной строки на замороженных данных» | fixed c859ca1 (= M-8) | | T13.1 | test_patch_cell_null_is_explicit зависит от созданного им состояния (откат сессией) | rejected | | T13.2 | длинные строки >120 | rejected (стиль) | | T15.1 | EditCell.jsx:223 `<textarea value={undefined}>` — dev-предупреждение React при первом вводе | deferred | | T15.2 | вложенный accessorKey с undefined — dev-предупреждение TanStack (в prod нет) | rejected (design) | | I-3 | удаление групповой строки слало row_deleted без row_id (getDataRowId вернул undefined после strip), сервер падал на data["data"]["row_id"] и рвал WebSocket | fixed c859ca1 | | M-7 | buildCellUpdatedMessage нормализует только value | rejected (INPUT-строки only; покрыто фиксом I-3) | | M-8 | нет теста глубоко вложенного отсутствующего блока | fixed c859ca1 | | M-9 | нет теста jsonb_strip_nulls на литерале против _strip_nulls | fixed c859ca1 | | M-10 | X-DB-Time-Ms в B включает стоимость jsonb_strip_nulls: доля Python в A и B не сопоставима напрямую | deferred (оговорка рядом с замерами) | | R-6 (design #6) | PATCH null: сначала 225, затем null | fixed (решение) | | R-7 (design #7) | getDataRowId возвращает null | fixed c859ca1 | | R-8 (design #8) | аудит Task 15 дополнен проверкой полезной нагрузки WebSocket | fixed (решение) | | O-6 | на origin/test cellUtils.js импортирует './rowUtils' без .js — красный шаг требовал временной правки; тест «q1 без m1» зелёный и на test | rejected | | O-7 | ошибки biome в файлах #223 (cellUtils.js, cellUtils.test.js:10,23, useWebSocket.js) и в старом тесте rowUtils.test.js:17-19 | rejected (не наши) | Отложенное (deferred): T11.1, T15.1, M-10; из A: T5.2, T6.2, T7.4, T7.6, M-2, O-3 (rf-rollup r.year). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 9 commits 2026-10-28 21:18:58 +03:00
Копируются только строки на пути к затронутой, остальные сохраняют идентичность;
без изменений возвращается тот же data. Отсутствующие в row.data ключи теперь
вставляются (нужно для AURORA-1844/1848). Тесты с паритетом к прежней реализации.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Четыре теста updateCells: вставка отсутствующего блока и поля,
явная запись null, вставка отсутствующего скалярного ключа data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
row_json_select(strip_nulls) оборачивает data в jsonb_strip_nulls внутри json_build_object;
флаг пробрасывается через get_json/get_svod1_json/get_svod2_json, роутеры листа и сводов
включают его. Проекты, PATCH/POST/DELETE не затронуты.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
form4_ids вычисляет vsp_ids и project_ids из строк FORM_4 через .get
с пропуском отсутствующих ключей, grow_form4_sheet использует её.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
После jsonb_strip_nulls у групп/позиций нет ключа line_id, getDataRowId
возвращал undefined, и row_id в сообщении удаления сериализовался в {}
(KeyError на сервере). Возвращаем null, как до фазы B.
Добавлены тесты updateCells (глубокое отсутствие блока, два обновления в батче)
и сверка jsonb_strip_nulls с _strip_nulls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
Owner

PG 15.12 (dfip-pg15:55434): ветка c859ca1 + исправление AURORA-1922 (временный worktree), полный pytest: 3 failed (те же 3 известных на test), 250 passed, 4 skipped. jsonb_strip_nulls на PG 15.12 и 16.15 идентичен (проверка ревьюером на литерале с {}, null в массиве).

PG 15.12 (dfip-pg15:55434): ветка c859ca1 + исправление AURORA-1922 (временный worktree), полный pytest: 3 failed (те же 3 известных на test), 250 passed, 4 skipped. jsonb_strip_nulls на PG 15.12 и 16.15 идентичен (проверка ревьюером на литерале с {}, null в массиве).
Author
Owner

Ночной замер на стенде perf/ (29.10, масштаб 1, D0 без grow, CPU 1x, arm-ka-* остановлены)

Сборки: «до» — test 2a28748; A — b612178 (#239); B — c859ca1 (этот PR). Одна БД perf (дамп D0), API перезапускался на каждом коммите.

Корректность (условие мержа) — выполнено

  • compare_responses.py compare <base> <B> --mode strip-nulls: совпало 56 из 56 (листы и своды — «до» с вырезанными null в data; отчёты/summary проектов — точно), код 0.
  • A→B --mode strip-nulls: 56 из 56. A против base --mode exact: 56 из 56.

Время: analysis/api_split.py --scale 1 --repeats 10 (версия скрипта из B; та же на всех сборках)

запрос base total, мс A total (A/base) B total (B/base) base / A / B X-DB, мс base / A / B размер, МБ base / A / B на проводе, МБ python_share base/A/B
лист FORM_2/AHR (1154 строк ответа) 367 305 (0.83) 299 (0.82) 307 / 282 / 284 4.29 / 4.76 / 1.55 0.33 / 0.35 / 0.21 0.16 / 0.08 / 0.05
лист FORM_4/CAP (110 строк ответа) 579 571 (0.99) 564 (0.97) 562 / 560 / 556 0.44 / 0.49 / 0.19 0.05 / 0.05 / 0.03 0.03 / 0.02 / 0.01
лист FORM_4/AHR (110 строк ответа) 602 587 (0.98) 582 (0.97) 584 / 578 / 575 0.44 / 0.49 / 0.20 0.05 / 0.05 / 0.04 0.03 / 0.02 / 0.01
отчёт проекта LIMIT (1364 строк ответа) 337 296 (0.88) 293 (0.87) 302 / 280 / 277 1.48 / 1.65 / 1.65 0.16 / 0.17 / 0.17 0.1 / 0.05 / 0.05
свод 1 MAIN (133 строк ответа) 253 248 (0.98) 245 (0.97) 238 / 239 / 236 0.13 / 0.15 / 0.15 0.05 / 0.05 / 0.05 0.06 / 0.04 / 0.03
свод 2 GO (все организации) (5617 строк ответа) 1019 684 (0.67) 562 (0.55) 674 / 595 / 524 30.91 / 33.66 / 6.91 2.43 / 2.58 / 1.49 0.34 / 0.13 / 0.07
свод 2 RF (все организации) (8597 строк ответа) 1537 1088 (0.71) 864 (0.56) 1018 / 938 / 814 47.23 / 51.44 / 10.49 3.50 / 3.73 / 2.12 0.34 / 0.14 / 0.06
сводные проектов (747 строк ответа) 323 308 (0.96) 307 (0.95) 292 / 299 / 293 0.49 / 0.56 / 0.56 0.11 / 0.11 / 0.11 0.1 / 0.03 / 0.04

Вердикт по порогам design D7 (цели, не условие мержа)

  • свод 2 GO, полное время B ≤ 0,7 × до: выполнен — 562 мс против 1019 (0,55). RF справочно 864 против 1537 (0,56).
  • FORM_2/AHR B ≤ 0,9 × до и размер меньше: выполнен — 299 против 367 мс (0,82); распакованный 1,55 МБ против 4,29 (−64 %), на проводе 0,21 против 0,33 МБ.
  • python_share (справочно): свод 2 GO 0,34 → 0,07, FORM_2/AHR 0,16 → 0,05. Оговорка M-10: X-DB-Time-Ms в B включает jsonb_strip_nulls, поэтому доля «БД» в B чуть завышена относительно A.
  • Соавтор на B (PERF_TARGETS='FORM_2/AHR/*' PERF_COAUTHOR_RATES=1 PERF_REPEATS=1, page_ws_updates > 0) — допишу отдельным комментарием после фронтовой серии.

Файлы: /private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/1848/ (dump-, compare-B-strip.txt, split-/api-split.{md,json}).

🤖 Generated with Claude Code

## Ночной замер на стенде perf/ (29.10, масштаб 1, D0 без grow, CPU 1x, arm-ka-* остановлены) **Сборки:** «до» — `test` 2a28748; A — b612178 (#239); B — c859ca1 (этот PR). Одна БД `perf` (дамп D0), API перезапускался на каждом коммите. ### Корректность (условие мержа) — выполнено - `compare_responses.py compare <base> <B> --mode strip-nulls`: **совпало 56 из 56** (листы и своды — «до» с вырезанными null в data; отчёты/summary проектов — точно), код 0. - A→B `--mode strip-nulls`: 56 из 56. A против base `--mode exact`: 56 из 56. ### Время: `analysis/api_split.py --scale 1 --repeats 10` (версия скрипта из B; та же на всех сборках) | запрос | base total, мс | A total (A/base) | B total (B/base) | base / A / B X-DB, мс | base / A / B размер, МБ | base / A / B на проводе, МБ | python_share base/A/B | |---|---|---|---|---|---|---|---| | лист FORM_2/AHR (1154 строк ответа) | 367 | 305 (0.83) | 299 (0.82) | 307 / 282 / 284 | 4.29 / 4.76 / 1.55 | 0.33 / 0.35 / 0.21 | 0.16 / 0.08 / 0.05 | | лист FORM_4/CAP (110 строк ответа) | 579 | 571 (0.99) | 564 (0.97) | 562 / 560 / 556 | 0.44 / 0.49 / 0.19 | 0.05 / 0.05 / 0.03 | 0.03 / 0.02 / 0.01 | | лист FORM_4/AHR (110 строк ответа) | 602 | 587 (0.98) | 582 (0.97) | 584 / 578 / 575 | 0.44 / 0.49 / 0.20 | 0.05 / 0.05 / 0.04 | 0.03 / 0.02 / 0.01 | | отчёт проекта LIMIT (1364 строк ответа) | 337 | 296 (0.88) | 293 (0.87) | 302 / 280 / 277 | 1.48 / 1.65 / 1.65 | 0.16 / 0.17 / 0.17 | 0.1 / 0.05 / 0.05 | | свод 1 MAIN (133 строк ответа) | 253 | 248 (0.98) | 245 (0.97) | 238 / 239 / 236 | 0.13 / 0.15 / 0.15 | 0.05 / 0.05 / 0.05 | 0.06 / 0.04 / 0.03 | | свод 2 GO (все организации) (5617 строк ответа) | 1019 | 684 (0.67) | 562 (0.55) | 674 / 595 / 524 | 30.91 / 33.66 / 6.91 | 2.43 / 2.58 / 1.49 | 0.34 / 0.13 / 0.07 | | свод 2 RF (все организации) (8597 строк ответа) | 1537 | 1088 (0.71) | 864 (0.56) | 1018 / 938 / 814 | 47.23 / 51.44 / 10.49 | 3.50 / 3.73 / 2.12 | 0.34 / 0.14 / 0.06 | | сводные проектов (747 строк ответа) | 323 | 308 (0.96) | 307 (0.95) | 292 / 299 / 293 | 0.49 / 0.56 / 0.56 | 0.11 / 0.11 / 0.11 | 0.1 / 0.03 / 0.04 | ### Вердикт по порогам design D7 (цели, не условие мержа) - свод 2 GO, полное время B ≤ 0,7 × до: **выполнен** — 562 мс против 1019 (0,55). RF справочно 864 против 1537 (0,56). - FORM_2/AHR B ≤ 0,9 × до и размер меньше: **выполнен** — 299 против 367 мс (0,82); распакованный 1,55 МБ против 4,29 (−64 %), на проводе 0,21 против 0,33 МБ. - python_share (справочно): свод 2 GO 0,34 → 0,07, FORM_2/AHR 0,16 → 0,05. Оговорка M-10: `X-DB-Time-Ms` в B включает `jsonb_strip_nulls`, поэтому доля «БД» в B чуть завышена относительно A. - Соавтор на B (`PERF_TARGETS='FORM_2/AHR/*' PERF_COAUTHOR_RATES=1 PERF_REPEATS=1`, page_ws_updates > 0) — допишу отдельным комментарием после фронтовой серии. Файлы: `/private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/1848/` (dump-*, compare-B-strip.txt, split-*/api-split.{md,json}). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Author
Owner

Дополнение: соавтор на B (фронт и бэк этого PR c859ca1, D0)

PERF_TARGETS='FORM_2/AHR/*' PERF_COAUTHOR_RATES=1 PERF_REPEATS=1 npx playwright test scenarios/scroll-coauthor.spec.ts:

  • page_ws_updates = 41 > 0 — критерий выполнен; бот: sent 48, echoed 41, errors 7 (доля ошибок как на test: 8.5 из 45.5 — известная O-10 стенда);
  • main_thread_ms_per_step автора 95.0 (на test rate 1: 91.0 — 1 повтор, в пределах шума одного прогона).
    Скриншоты B (1600×900) листа, свода 1, свода 2: /private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/1848/shots/p1848b-*.png (против night/base/shots/base-*.png; попиксельная сверка — в итоговом комментарии).

🤖 Generated with Claude Code

## Дополнение: соавтор на B (фронт и бэк этого PR c859ca1, D0) `PERF_TARGETS='FORM_2/AHR/*' PERF_COAUTHOR_RATES=1 PERF_REPEATS=1 npx playwright test scenarios/scroll-coauthor.spec.ts`: - **page_ws_updates = 41 > 0** — критерий выполнен; бот: sent 48, echoed 41, errors 7 (доля ошибок как на `test`: 8.5 из 45.5 — известная O-10 стенда); - main_thread_ms_per_step автора 95.0 (на `test` rate 1: 91.0 — 1 повтор, в пределах шума одного прогона). Скриншоты B (1600×900) листа, свода 1, свода 2: `/private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/1848/shots/p1848b-*.png` (против `night/base/shots/base-*.png`; попиксельная сверка — в итоговом комментарии). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Author
Owner

Ночной замер — часть 2 (итог)

Сборки как в части 1 (B = c859ca1). Добавлено: масштаб 2 и сверка скриншотов.

Масштаб 2 (D2 = gen --scale 2 + verify OK; api_split.py --scale 2 --repeats 5; полное время, мс, медиана 5; размер — несжатое тело):

запрос test B B / test
свод 2 GO 3938 (123,4 МБ) 2117 (27,6 МБ) 0.54
свод 2 RF 6410 (190,4 МБ) 3347 (42,3 МБ) 0.52
лист FORM_2/AHR (1744 строки) 3692 (6,5 МБ) 3695 (2,4 МБ) 1.00; размер −63 %
FORM_4/CAP / FORM_4/AHR 1116 / 1177 1115 / 1231 1.00 / 1.05
отчёт LIMIT 360 342 0.95
свод 1 MAIN / сводные 623 / 626 692 / 603 1.11 / 0.96
Python-доля свода 2 GO: 1470 → 130 мс. Оговорки: (а) AHR 3,7 с во всех трёх прогонах — это время БД (db_ms 3,6 с), а та же БД через 20 минут давала 0,46 с (после gen не было ANALYZE): порог «AHR ≤ 0.9×» на масштабе 2 по этим цифрам не оценить; (б) свод 1 MAIN +11 % (db_ms 686 против 607) — один и тот же код свода 1 в других прогонах той же ночи даёт 622–656 мс (разброс ±6 %), формально порог 1.05 превышен, считаю шумом.
Масштаб 1 (часть 1): GO 0.55, AHR 0.82, размер −64 % — условия выполнены.

Сверка скриншотов 1600×900, base против p1848b: лист (7 позиций) 0 – 0,18 %, свод 1 0 – 0,24 %, сводные 0 %, свод 2 (6 позиций) 0 %. Отличия — несколько чисел в верхних строках (область 1–2 строки), объясняются правками соавтора между снимками (O-2: прогон coauthor менял ячейки FORM_2/AHR), структуры и вёрстки не касаются.
Вердикт: GO ≤ 0.7× — выполнен (0.55 / 0.54); AHR ≤ 0.9× и размер меньше — выполнен на масштабе 1 (0.82, −64 %), на масштабе 2 не оценим; сверка strip-nulls 56/56 — из части 1.
Файлы: /private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/s2/split-1848-*/, imgdiff.txt, imgdiff/diff-p1848b-*.png.

## Ночной замер — часть 2 (итог) Сборки как в части 1 (B = c859ca1). Добавлено: масштаб 2 и сверка скриншотов. **Масштаб 2** (D2 = `gen --scale 2` + `verify` OK; `api_split.py --scale 2 --repeats 5`; полное время, мс, медиана 5; размер — несжатое тело): | запрос | test | B | B / test | |---|---|---|---| | свод 2 GO | 3938 (123,4 МБ) | **2117** (27,6 МБ) | **0.54** | | свод 2 RF | 6410 (190,4 МБ) | 3347 (42,3 МБ) | 0.52 | | лист FORM_2/AHR (1744 строки) | 3692 (6,5 МБ) | 3695 (2,4 МБ) | 1.00; размер −63 % | | FORM_4/CAP / FORM_4/AHR | 1116 / 1177 | 1115 / 1231 | 1.00 / 1.05 | | отчёт LIMIT | 360 | 342 | 0.95 | | свод 1 MAIN / сводные | 623 / 626 | **692** / 603 | **1.11** / 0.96 | Python-доля свода 2 GO: 1470 → 130 мс. Оговорки: (а) AHR 3,7 с во всех трёх прогонах — это время БД (db_ms 3,6 с), а та же БД через 20 минут давала 0,46 с (после `gen` не было `ANALYZE`): порог «AHR ≤ 0.9×» на масштабе 2 по этим цифрам не оценить; (б) свод 1 MAIN +11 % (db_ms 686 против 607) — один и тот же код свода 1 в других прогонах той же ночи даёт 622–656 мс (разброс ±6 %), формально порог 1.05 превышен, считаю шумом. Масштаб 1 (часть 1): GO 0.55, AHR 0.82, размер −64 % — условия выполнены. **Сверка скриншотов 1600×900, base против p1848b:** лист (7 позиций) 0 – 0,18 %, свод 1 0 – 0,24 %, сводные 0 %, свод 2 (6 позиций) 0 %. Отличия — несколько чисел в верхних строках (область 1–2 строки), объясняются правками соавтора между снимками (O-2: прогон coauthor менял ячейки FORM_2/AHR), структуры и вёрстки не касаются. **Вердикт:** GO ≤ 0.7× — **выполнен** (0.55 / 0.54); AHR ≤ 0.9× и размер меньше — **выполнен на масштабе 1** (0.82, −64 %), на масштабе 2 не оценим; сверка `strip-nulls` 56/56 — из части 1. Файлы: `/private/tmp/claude-501/-Users-andrey-epifancev-projects-fomichev-claude/6fa9c75e-eb11-4e5d-98c1-05eb590ab14f/scratchpad/night/s2/split-1848-*/`, `imgdiff.txt`, `imgdiff/diff-p1848b-*.png`.
This pull request can be merged automatically.
You are not authorized to merge this pull request.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/233-aurora-1848-sheet-json-no-pydantic-b:feat/233-aurora-1848-sheet-json-no-pydantic-b
git checkout feat/233-aurora-1848-sheet-json-no-pydantic-b
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RSHB/DFiP_Budget_planing#242
No description provided.