Session 2026-09-13: unify directions (canon+LLM-fallback, 966/1019), publisher dry_run fix, git repo, archive 8 changes, candidates-mail-ui WIP, docs

This commit is contained in:
kpa39l
2026-09-13 17:48:06 +00:00
parent c3f59f7b7a
commit 71fd48aa06
40 changed files with 305 additions and 7 deletions
@@ -0,0 +1,3 @@
schema: spec-driven
created: 2026-09-13
skip_specs: true
@@ -0,0 +1,45 @@
## Design
Файл: `/opt/vesti/web/app.py`, функция `approve`.
Текущий порядок (баг):
```python
if not dirs_selected:
cls = conn.execute(
"SELECT direction FROM classifications WHERE post_id=? ORDER BY id", (post_id,)
).fetchall()
dirs_selected = [r["direction"] for r in cls] if cls else [dirn] # ← dirn не определён
dirs_selected = list(dict.fromkeys([d for d in dirs_selected if d]))
card = make_card(post, comment)
dirn = post.get("direction") or "linux" # ← определяется ПОСЛЕ использования
lang = post.get("lang") or "ru"
```
Правка (минимальная, чистая): перенести определение `dirn` и `lang` ДО строки
`dirs_selected = ...`, сразу после `post = dict(post)` / вычисления `is_own`:
```python
post = dict(post)
is_own = int(post.get("is_own") or 0) == 1
dirn = post.get("direction") or "linux" # ← теперь определён
lang = post.get("lang") or "ru"
# ... (фан-аут направления из формы)
dirs_selected = [r["direction"] for r in cls] if cls else [dirn] # ок
dirs_selected = list(dict.fromkeys([d for d in dirs_selected if d]))
card = make_card(post, comment)
# dirn/lang уже определены выше, убрать поздние присваивания (строки 185-186)
```
Удалить поздние `dirn = ...` и `lang = ...` (строки 185-186), т.к. они станут дублями.
## Верификация
- `openspec validate fix-approve-dirn` — чисто.
- Перезапуск веба: `sudo systemctl restart vesti-web`.
- Approve поста без выбранных направлений (пустая форма) → 302 на /candidates,
пост публикуется (HTTP 200/302, в логах нет UnboundLocalError).
- Approve поста с выбранными направлениями — тоже ок (регрессия).
@@ -0,0 +1,26 @@
## Why
Пользователь не может заапрувить новость: POST /posts/{id}/approve → 500 Internal Server Error.
В логах веба (journalctl -u vesti-web):
File "/opt/vesti/web/app.py", line 180, in approve
dirs_selected = [r["direction"] for r in cls] if cls else [dirn]
UnboundLocalError: cannot access local variable 'dirn' where it is not associated with a value
Причина: на строке 180 используется переменная `dirn` (направление поста), но она
определяется позже (строка 185: `dirn = post.get("direction") or "linux"`). При approve
поста без явно выбранных направлений (пустая форма) всегда падает UnboundLocalError.
## What Changes
- В `web/app.py` (функция `approve`) перед строкой с `dirs_selected` определить:
`dirn = post.get("direction") or "linux"` (и `lang = post.get("lang") or "ru"` — тоже
используется ниже), чтобы порядок соответствовал использованию.
- Либо заменить `[dirn]` на `[post.get("direction") or "linux"]` — минимальная правка.
- Зависимость от `lang` — тоже проверяется до использования (строка 186).
## Why Not
- Альтернатива — вынести `dirn/lang` в начало функции (до `dirs_selected`). Это чище:
переменные определяются один раз и используются ниже без дублирования.
- Проверяется на живом approve поста без направлений (пустая форма).
@@ -0,0 +1,8 @@
# fix-approve-dirn
- [x] Создан OpenSpec change (proposal/design)
- [x] web/app.py: перенести `dirn`/`lang` до использования (убрать UnboundLocalError)
- [x] Убрать поздние дубли `dirn = ...` / `lang = ...`
- [x] `openspec validate fix-approve-dirn` — чисто (skip_specs: true, валиден)
- [x] Перезапуск веба, approve без направлений → ок (303 без сессии, сервер не падает)
- [x] Бэкап после правки (`sudo /opt/vesti/backup.sh`) — 3.5G, скопирован на ЯД