Единый список задач вместо двух секций, порядок по выполнению

Секции «Ядро» и «Инфра» слиты в одну «Очередь»: полок домена у проекта
нет, а две секции держали два независимых порядка вместо одного.

Порядок: красный гейт, потом долги, задевающие интерфейсы, потом
хранилище, вход, разграничение, приложение. Разведка потолков SpeechKit
последней — она обслуживает направление, а не очередь.
This commit is contained in:
av
2026-08-10 21:39:55 +03:00
parent 115b3796e8
commit d21da8575c
16 changed files with 28 additions and 28 deletions
+13 -13
View File
@@ -2,11 +2,14 @@
Что **можно взять**. Одна задача = один файл `items/<slug>.md` Что **можно взять**. Одна задача = один файл `items/<slug>.md`
+ строка здесь. Целей тут нет — они в [ROADMAP.md](ROADMAP.md): беклог — то, что берут, + строка здесь. Целей тут нет — они в [ROADMAP.md](ROADMAP.md): беклог — то, что берут,
роадмап — то, подо что берут. **Порядок строк внутри секции значим:** роадмап — то, подо что берут. **Порядок строк значим:**
это очередь, и первая строка — то, что делают следующим. Порядок это очередь, и первая строка — то, что делают следующим. Порядок
назначает человек на груминге, машина его не выводит. Одно исключение назначает человек на груминге, машина его не выводит. Одно исключение
производно от типа — сырьё (`research` без раздела «Вопрос») производно от типа — сырьё (`research` без раздела «Вопрос»)
стоит в конце секции: его не берут. Ведётся скиллом `tasks`. стоит в конце: его не берут. Ведётся скиллом `tasks`.
Секция одна — полок домена у проекта нет, и делить очередь на две
значило бы держать два порядка вместо одного.
Тип записи стоит первым полем меты и решает, что у неё может быть: Тип записи стоит первым полем меты и решает, что у неё может быть:
`feature` 🐞 `fix` 🧹 `chore` 🔬 `research` `feature` 🐞 `fix` 🧹 `chore` 🔬 `research`
@@ -15,23 +18,20 @@
(работа не может продолжаться ни одной задачей), оно живёт до ответа (работа не может продолжаться ни одной задачей), оно живёт до ответа
человека, а его следы — вопросами в файлах задач. человека, а его следы — вопросами в файлах задач.
## Ядро ## Очередь
- [🐞 Починить тесты http-обработчика, ни разу не бывшие зелёными](items/http-handler-tests-never-green.md) — go test ./... падает на master: тесты требуют файла, которого нет в репозитории, и ждут 201 от ffprobe, которому скормили строку. - [🐞 Починить тесты http-обработчика, ни разу не бывшие зелёными](items/http-handler-tests-never-green.md) — go test ./... падает на master: тесты требуют файла, которого нет в репозитории, и ждут 201 от ffprobe, которому скормили строку.
- [🧹 Сравнивать доменные ошибки через errors.As](items/errors-as-instead-of-typecast.md) — NoopJobError и JobNotFoundError проверяются приведением типа: первая же обёртка %w между слоями сломает проверку молча.
- [🧹 Задать таймауты обращениям к внешним сервисам](items/external-call-timeouts.md) — Ни у Telegram, ни у Object Storage, ни у SpeechKit нет таймаута: молчащий собеседник держит шаг конвейера до истечения часового захвата.
- [🧹 Перевести хранилище на встроенный PocketBase](items/pocketbase-storage.md) — Хранилище, учётные записи и веб-панель нужны все три, и SQLite с goqu не даёт ни второго, ни третьего.
- [✨ Пускать в приложение только после входа через OIDC](items/oidc-login.md) — HTTP API открыт наружу без аутентификации: любой из интернета заводит задачи за наши деньги и читает чужие расшифровки по идентификатору. - [✨ Пускать в приложение только после входа через OIDC](items/oidc-login.md) — HTTP API открыт наружу без аутентификации: любой из интернета заводит задачи за наши деньги и читает чужие расшифровки по идентификатору.
- [✨ Привязать запись к владельцу и отдавать только свои](items/record-ownership.md) — У задачи и файла нет владельца, поэтому знание UUID задачи и есть право её читать. - [✨ Привязать запись к владельцу и отдавать только свои](items/record-ownership.md) — У задачи и файла нет владельца, поэтому знание UUID задачи и есть право её читать.
- [✨ Сопоставить пользователя Telegram с учётной записью](items/telegram-account-link.md) — Белый список сверяется с именем пользователя Telegram, которое владелец меняет в любой момент, а записи из бота ни с кем не связаны. - [✨ Сопоставить пользователя Telegram с учётной записью](items/telegram-account-link.md) — Белый список сверяется с именем пользователя Telegram, которое владелец меняет в любой момент, а записи из бота ни с кем не связаны.
- [✨ Свести приём и чтение записей к одному контракту для приложения](items/json-api-for-spa.md) — Сегодняшний API отвечает 404 на любую ошибку чтения и 500 на любую ошибку приёма: строить на нём экраны нечем. - [✨ Свести приём и чтение записей к одному контракту для приложения](items/json-api-for-spa.md) — Сегодняшний API отвечает 404 на любую ошибку чтения и 500 на любую ошибку приёма: строить на нём экраны нечем.
- [✨ Сделать экран загрузки записи и её состояния](items/upload-and-status-screen.md) — Первое, ради чего приложение открывают: отдать файл и увидеть, что с ним происходит.
- [✨ Сделать экран списка своих записей и чтения текста](items/records-list-screen.md) — Расшифровка сегодня доходит одним сообщением и теряется в переписке; вернуться к ней через неделю нечем.
- [✨ Отправлять готовый текст через apprise и ntfy](items/ntfy-delivery.md) — Пользователь веба узнаёт о готовности только опросом с открытого экрана.
- [🧹 Сравнивать доменные ошибки через errors.As](items/errors-as-instead-of-typecast.md) — NoopJobError и JobNotFoundError проверяются приведением типа: первая же обёртка %w между слоями сломает проверку молча.
- [🔬 Потолки SpeechKit по длине записи и по формату](items/speechkit-limits.md) — Потолок длины записи и перечень принимаемых форматов неизвестны, а цель про долгие записи без них не начинается.
## Инфра
- [🧹 Перевести хранилище на встроенный PocketBase](items/pocketbase-storage.md) — Хранилище, учётные записи и веб-панель нужны все три, и SQLite с goqu не даёт ни второго, ни третьего.
- [🔬 Выбор фреймворка для приложения](items/spa-framework-choice.md) — Конвенция веб-UI написана под htmx, а решено делать SPA: до выбора фреймворка не заводится ни сборка, ни первый экран. - [🔬 Выбор фреймворка для приложения](items/spa-framework-choice.md) — Конвенция веб-UI написана под htmx, а решено делать SPA: до выбора фреймворка не заводится ни сборка, ни первый экран.
- [✨ Собрать каркас приложения и раздать его из бинарника](items/spa-skeleton.md) — Экранов нет и собирать их нечем: ни сборки фронтенда, ни раздачи статики в проекте не существует. - [✨ Собрать каркас приложения и раздать его из бинарника](items/spa-skeleton.md) — Экранов нет и собирать их нечем: ни сборки фронтенда, ни раздачи статики в проекте не существует.
- [✨ Сделать экран загрузки записи и её состояния](items/upload-and-status-screen.md) — Первое, ради чего приложение открывают: отдать файл и увидеть, что с ним происходит.
- [✨ Сделать экран списка своих записей и чтения текста](items/records-list-screen.md) — Расшифровка сегодня доходит одним сообщением и теряется в переписке; вернуться к ней через неделю нечем.
- [✨ Сделать приложение устанавливаемым на телефон](items/installable-pwa.md) — Приложение, живущее вкладкой браузера, теряется среди прочих: ярлыка на экране у него нет. - [✨ Сделать приложение устанавливаемым на телефон](items/installable-pwa.md) — Приложение, живущее вкладкой браузера, теряется среди прочих: ярлыка на экране у него нет.
- [🧹 Задать таймауты обращениям к внешним сервисам](items/external-call-timeouts.md) — Ни у Telegram, ни у Object Storage, ни у SpeechKit нет таймаута: молчащий собеседник держит шаг конвейера до истечения часового захвата. - [✨ Отправлять готовый текст через apprise и ntfy](items/ntfy-delivery.md) — Пользователь веба узнаёт о готовности только опросом с открытого экрана.
- [🔬 Потолки SpeechKit по длине записи и по формату](items/speechkit-limits.md) — Потолок длины записи и перечень принимаемых форматов неизвестны, а цель про долгие записи без них не начинается.
+1 -1
View File
@@ -1,7 +1,7 @@
# 🧹 Сравнивать доменные ошибки через errors.As # 🧹 Сравнивать доменные ошибки через errors.As
- **Тип:** chore - **Тип:** chore
- **Категория:** Ядро - **Категория:** Очередь
- **Зачем:** NoopJobError и JobNotFoundError проверяются приведением типа: первая же обёртка %w между слоями сломает проверку молча. - **Зачем:** NoopJobError и JobNotFoundError проверяются приведением типа: первая же обёртка %w между слоями сломает проверку молча.
Сегодня это работает только потому, что ошибку на этом пути никто не Сегодня это работает только потому, что ошибку на этом пути никто не
+1 -1
View File
@@ -1,7 +1,7 @@
# 🧹 Задать таймауты обращениям к внешним сервисам # 🧹 Задать таймауты обращениям к внешним сервисам
- **Тип:** chore - **Тип:** chore
- **Категория:** Инфра - **Категория:** Очередь
- **Зачем:** Ни у Telegram, ни у Object Storage, ни у SpeechKit нет таймаута: молчащий собеседник держит шаг конвейера до истечения часового захвата. - **Зачем:** Ни у Telegram, ни у Object Storage, ни у SpeechKit нет таймаута: молчащий собеседник держит шаг конвейера до истечения часового захвата.
Все обращения наружу идут с `context.Background()` либо через `http.Get` без Все обращения наружу идут с `context.Background()` либо через `http.Get` без
@@ -1,7 +1,7 @@
# 🐞 Починить тесты http-обработчика, ни разу не бывшие зелёными # 🐞 Починить тесты http-обработчика, ни разу не бывшие зелёными
- **Тип:** fix - **Тип:** fix
- **Категория:** Ядро - **Категория:** Очередь
- **Зачем:** go test ./... падает на master: тесты требуют файла, которого нет в репозитории, и ждут 201 от ffprobe, которому скормили строку. - **Зачем:** go test ./... падает на master: тесты требуют файла, которого нет в репозитории, и ждут 201 от ffprobe, которому скормили строку.
Тесты заведены коммитом `87d8b05` и с тех пор ни разу не проходили: файл Тесты заведены коммитом `87d8b05` и с тех пор ни разу не проходили: файл
+1 -1
View File
@@ -1,7 +1,7 @@
# ✨ Сделать приложение устанавливаемым на телефон # ✨ Сделать приложение устанавливаемым на телефон
- **Тип:** feature - **Тип:** feature
- **Категория:** Инфра - **Категория:** Очередь
- **Зачем:** Приложение, живущее вкладкой браузера, теряется среди прочих: ярлыка на экране у него нет. - **Зачем:** Приложение, живущее вкладкой браузера, теряется среди прочих: ярлыка на экране у него нет.
- **Теги:** goal:web-access - **Теги:** goal:web-access
+1 -1
View File
@@ -1,7 +1,7 @@
# ✨ Свести приём и чтение записей к одному контракту для приложения # ✨ Свести приём и чтение записей к одному контракту для приложения
- **Тип:** feature - **Тип:** feature
- **Категория:** Ядро - **Категория:** Очередь
- **Зачем:** Сегодняшний API отвечает 404 на любую ошибку чтения и 500 на любую ошибку приёма: строить на нём экраны нечем. - **Зачем:** Сегодняшний API отвечает 404 на любую ошибку чтения и 500 на любую ошибку приёма: строить на нём экраны нечем.
- **Теги:** goal:web-access - **Теги:** goal:web-access
+1 -1
View File
@@ -1,7 +1,7 @@
# ✨ Отправлять готовый текст через apprise и ntfy # ✨ Отправлять готовый текст через apprise и ntfy
- **Тип:** feature - **Тип:** feature
- **Категория:** Ядро - **Категория:** Очередь
- **Зачем:** Пользователь веба узнаёт о готовности только опросом с открытого экрана. - **Зачем:** Пользователь веба узнаёт о готовности только опросом с открытого экрана.
- **Теги:** goal:ready-notification - **Теги:** goal:ready-notification
+1 -1
View File
@@ -1,7 +1,7 @@
# ✨ Пускать в приложение только после входа через OIDC # ✨ Пускать в приложение только после входа через OIDC
- **Тип:** feature - **Тип:** feature
- **Категория:** Ядро - **Категория:** Очередь
- **Зачем:** HTTP API открыт наружу без аутентификации: любой из интернета заводит задачи за наши деньги и читает чужие расшифровки по идентификатору. - **Зачем:** HTTP API открыт наружу без аутентификации: любой из интернета заводит задачи за наши деньги и читает чужие расшифровки по идентификатору.
- **Теги:** goal:multi-user, question - **Теги:** goal:multi-user, question
+1 -1
View File
@@ -1,7 +1,7 @@
# 🧹 Перевести хранилище на встроенный PocketBase # 🧹 Перевести хранилище на встроенный PocketBase
- **Тип:** chore - **Тип:** chore
- **Категория:** Инфра - **Категория:** Очередь
- **Зачем:** Хранилище, учётные записи и веб-панель нужны все три, и SQLite с goqu не даёт ни второго, ни третьего. - **Зачем:** Хранилище, учётные записи и веб-панель нужны все три, и SQLite с goqu не даёт ни второго, ни третьего.
PocketBase встраивается библиотекой в тот же бинарник и приносит хранилище, PocketBase встраивается библиотекой в тот же бинарник и приносит хранилище,
+1 -1
View File
@@ -1,7 +1,7 @@
# ✨ Привязать запись к владельцу и отдавать только свои # ✨ Привязать запись к владельцу и отдавать только свои
- **Тип:** feature - **Тип:** feature
- **Категория:** Ядро - **Категория:** Очередь
- **Зачем:** У задачи и файла нет владельца, поэтому знание UUID задачи и есть право её читать. - **Зачем:** У задачи и файла нет владельца, поэтому знание UUID задачи и есть право её читать.
- **Теги:** goal:multi-user - **Теги:** goal:multi-user
+1 -1
View File
@@ -1,7 +1,7 @@
# ✨ Сделать экран списка своих записей и чтения текста # ✨ Сделать экран списка своих записей и чтения текста
- **Тип:** feature - **Тип:** feature
- **Категория:** Ядро - **Категория:** Очередь
- **Зачем:** Расшифровка сегодня доходит одним сообщением и теряется в переписке; вернуться к ней через неделю нечем. - **Зачем:** Расшифровка сегодня доходит одним сообщением и теряется в переписке; вернуться к ней через неделю нечем.
- **Теги:** goal:web-access - **Теги:** goal:web-access
+1 -1
View File
@@ -1,7 +1,7 @@
# 🔬 Выбор фреймворка для приложения # 🔬 Выбор фреймворка для приложения
- **Тип:** research - **Тип:** research
- **Категория:** Инфра - **Категория:** Очередь
- **Зачем:** Конвенция веб-UI написана под htmx, а решено делать SPA: до выбора фреймворка не заводится ни сборка, ни первый экран. - **Зачем:** Конвенция веб-UI написана под htmx, а решено делать SPA: до выбора фреймворка не заводится ни сборка, ни первый экран.
- **Теги:** goal:web-access - **Теги:** goal:web-access
+1 -1
View File
@@ -1,7 +1,7 @@
# ✨ Собрать каркас приложения и раздать его из бинарника # ✨ Собрать каркас приложения и раздать его из бинарника
- **Тип:** feature - **Тип:** feature
- **Категория:** Инфра - **Категория:** Очередь
- **Зачем:** Экранов нет и собирать их нечем: ни сборки фронтенда, ни раздачи статики в проекте не существует. - **Зачем:** Экранов нет и собирать их нечем: ни сборки фронтенда, ни раздачи статики в проекте не существует.
- **Теги:** goal:web-access - **Теги:** goal:web-access
+1 -1
View File
@@ -1,7 +1,7 @@
# 🔬 Потолки SpeechKit по длине записи и по формату # 🔬 Потолки SpeechKit по длине записи и по формату
- **Тип:** research - **Тип:** research
- **Категория:** Ядро - **Категория:** Очередь
- **Зачем:** Потолок длины записи и перечень принимаемых форматов неизвестны, а цель про долгие записи без них не начинается. - **Зачем:** Потолок длины записи и перечень принимаемых форматов неизвестны, а цель про долгие записи без них не начинается.
- **Теги:** goal:long-recordings - **Теги:** goal:long-recordings
+1 -1
View File
@@ -1,7 +1,7 @@
# ✨ Сопоставить пользователя Telegram с учётной записью # ✨ Сопоставить пользователя Telegram с учётной записью
- **Тип:** feature - **Тип:** feature
- **Категория:** Ядро - **Категория:** Очередь
- **Зачем:** Белый список сверяется с именем пользователя Telegram, которое владелец меняет в любой момент, а записи из бота ни с кем не связаны. - **Зачем:** Белый список сверяется с именем пользователя Telegram, которое владелец меняет в любой момент, а записи из бота ни с кем не связаны.
- **Теги:** goal:multi-user - **Теги:** goal:multi-user
+1 -1
View File
@@ -1,7 +1,7 @@
# ✨ Сделать экран загрузки записи и её состояния # ✨ Сделать экран загрузки записи и её состояния
- **Тип:** feature - **Тип:** feature
- **Категория:** Ядро - **Категория:** Очередь
- **Зачем:** Первое, ради чего приложение открывают: отдать файл и увидеть, что с ним происходит. - **Зачем:** Первое, ради чего приложение открывают: отдать файл и увидеть, что с ним происходит.
- **Теги:** goal:web-access - **Теги:** goal:web-access