# Prompts Log ## Prompt 1: Project Setup Стэк - Python 3.14, Pydantic v2, FastAPI 0.135, pytest, Docker для локального рантайма Описание проекта - локальный трекер задач "Backlog -> In progress -> Done" с чистым API, валидацией, подсчетом метрик workflow и HTML-страницей /stats. Сохранение состояния приперезапуске сервиса и контейнера в data/tasks.json Пользовательский сценарии 1. Создать задачу. 2. Просмотреть список с фильтрами по статусу/поиску. 3. Перевести задачу в inprogress, затем в done. 4. Удалить задачу. 5. Посмотреть статистику. 6. Экспортировать данные в csv. Минимальные тесты: 1. CRUD и фильтры - все 2xx/4xx по спецификации. 2. Переходы и ошибки статусов задач 409 invalid_transaction 3. Метрики: корректные avg_cycle/lead. 4. Экспорт CSV: text/csv, корректный заголовок. 5. Сохранение данных между сессиями. 6. Производительность: обработка типичных запросов ≤ 100 мс. Структура репозитория app/, data/, tests/ Цель - запуск сервиса в докере одной командой, успешное прохождение всех тестов Архитектура: - транспортный слой, - доменный слой - бизнес-логика - слой хранения Сущности: Task: {id: uuid, title: str(100), created_at: datetime, started_at: datetime, done_at: datetime} Эндпоинты: GET /api/tasks с пагинацией (default=100) и опциональными фильтрами GET /api/tasks/{id} POST /api/tasks PATCH /api/tasks/{id} DELETE /api/tasks/{id} POST /api/tasks/{id}/start - идемпотентность (повторный старт не меняет записанную дату) POST /api/tasks/{id}/done - целостность (соблюдение потока backlog -> inprogress -> done) GET /api/tasks/export - возвращает tasks.csv с защитой от csv-инъекций GET /stats - HTML-страница со статистикой (вверху блок с информацией о выбранной задаче: title, start dt, done dt, Cycle time, внизу канбан доска с плашками задач) Требования и соглашения: - дата время серверные UTC ISO-8601 - атомарная запись состояния (временный файл + rename), при повреждении данных бэкап и сброс состояния, чтобы не ломался сервис - единый формат ошибок invalid_* (в т.ч. invalid_id) - валидация входных данных Сгенерируй README.md проекта в формате unified diff (новый файл) содержащий грамотный инженерный каркас на английском языке и договоренности по предоставленным данным. ## Prompt 2: main.py Сгенерируй diff для main.py (только создание приложения), пустых __init__.py для всех пакетов проекта, эндпоинт health для пинга с выводом серверного времени в отдельном модуле ## Prompt 3: health testplan спланируй тесты для эндпоинта health, выведи таблицу с положительными и отрицательными кейсами и ожидаемыми результатами (пара положительных и один отрицательный) ## Prompt 4: health tests сгенерируй код предложенных тестов в формате diff ## Prompt 5: DTO Сгенерируй код DTO для эндпоинтов task. Выведи diff. ## Prompt 6: storage layer Сгенерируй код слоя storage. Должна учитываться версия формата данных. Выведи только diff ## Prompt 7: testplan for storage layer спланируй тесты для слоя storage. по 1-2 позитивных и один негативный на публичные контракты, также учти сценарии: - приложение завершилось между записью и rename — данные не повреждены; - файл tasks.json повреждён — сервис стартует с пустым состоянием и сохраняет бэкап. выведи таблицу с кейсами и ожидаемым выводом ## Prompt 8: tests for storage layer Сгенерируй код тестов по предложенному плану. Не фиксируй дату для тестов, используй текущую. пришли diff ## Prompt 9: domain layer Сгенерируй код функций start_task(task), complete_task(task) в доменном слое. пришли diff ## Prompt 10: testplan for domain layer спланируй тесты для функций доменного слоя, 1-2 позитивных и 1 негативный на каждую функцию. выведи в виде таблицы с кейсами и ожидаемым выводом ## Prompt 11: tests for domain layer напиши код тестов по предложенному плану. пришли дифф ## Prompt 12: tasks endpoints Напиши код для эндпоинтов tasks (crud функции и методы start и done). Пришли дифф ## Prompt 13: testplan for tasks endpoints спланируй тесты для эндпоинта tasks по 1-2 позитивному и 1 негативный на каждый метод. выведи в виде таблицы ## Prompt 14: tests for tasks endpoints напиши код тестов по предложенному плану. верни дифф ## Prompt 15: fix test fails (task-flow) kak@BigBrother task_flow % pytest -v tests/test_api_tasks.py ========================================================= test session starts ========================================================== platform darwin -- Python 3.14.2, pytest-9.0.2, pluggy-1.6.0 -- /Users/kak/Documents/Projects/vibe_coding_learning/task_flow/.venv/bin/python3 cachedir: .pytest_cache rootdir: /Users/kak/Documents/Projects/vibe_coding_learning/task_flow configfile: pyproject.toml plugins: anyio-4.13.0 collected 0 items / 1 error ================================================================ ERRORS ================================================================ _______________________________________________ ERROR collecting tests/test_api_tasks.py _______________________________________________ tests/test_api_tasks.py:8: in from app.api.tasks import get_task_repository app/api/__init__.py:2: in from app.api.tasks import router as tasks_router app/api/tasks.py:205: in @router.delete( .venv/lib/python3.14/site-packages/fastapi/routing.py:1450: in decorator self.add_api_route( .venv/lib/python3.14/site-packages/fastapi/routing.py:1386: in add_api_route route = route_class( .venv/lib/python3.14/site-packages/fastapi/routing.py:905: in __init__ assert is_body_allowed_for_status_code(status_code), ( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E AssertionError: Status code 204 must not have a response body ======================================================= short test summary info ======================================================== ERROR tests/test_api_tasks.py - AssertionError: Status code 204 must not have a response body !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! =========================================================== 1 error in 0.22s =========================================================== исправь, верни дифф ## Prompt 16: fix test fails 2 (task-flow) kak@BigBrother task_flow % pytest -v tests/test_api_tasks.py ========================================================= test session starts ========================================================== platform darwin -- Python 3.14.2, pytest-9.0.2, pluggy-1.6.0 -- /Users/kak/Documents/Projects/vibe_coding_learning/task_flow/.venv/bin/python3 cachedir: .pytest_cache rootdir: /Users/kak/Documents/Projects/vibe_coding_learning/task_flow configfile: pyproject.toml plugins: anyio-4.13.0 collected 0 items / 1 error ================================================================ ERRORS ================================================================ _______________________________________________ ERROR collecting tests/test_api_tasks.py _______________________________________________ tests/test_api_tasks.py:8: in from app.api.tasks import get_task_repository app/api/__init__.py:2: in from app.api.tasks import router as tasks_router app/api/tasks.py:205: in @router.delete( .venv/lib/python3.14/site-packages/fastapi/routing.py:1450: in decorator self.add_api_route( .venv/lib/python3.14/site-packages/fastapi/routing.py:1386: in add_api_route route = route_class( .venv/lib/python3.14/site-packages/fastapi/routing.py:905: in __init__ assert is_body_allowed_for_status_code(status_code), ( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E AssertionError: Status code 204 must not have a response body ======================================================= short test summary info ======================================================== ERROR tests/test_api_tasks.py - AssertionError: Status code 204 must not have a response body !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! =========================================================== 1 error in 0.24s =========================================================== патч не помог, исправь. верни дифф ## Prompt 17: fix test fails 3 (task-flow) kak@BigBrother task_flow % pytest -v tests/test_api_tasks.py ========================================================= test session starts ========================================================== platform darwin -- Python 3.14.2, pytest-9.0.2, pluggy-1.6.0 -- /Users/kak/Documents/Projects/vibe_coding_learning/task_flow/.venv/bin/python3 cachedir: .pytest_cache rootdir: /Users/kak/Documents/Projects/vibe_coding_learning/task_flow configfile: pyproject.toml plugins: anyio-4.13.0 collected 27 items tests/test_api_tasks.py::test_list_tasks_returns_empty_list_by_default PASSED [ 3%] tests/test_api_tasks.py::test_list_tasks_filters_by_status_and_search PASSED [ 7%] tests/test_api_tasks.py::test_list_tasks_rejects_invalid_status_filter PASSED [ 11%] tests/test_api_tasks.py::test_get_task_returns_existing_task PASSED [ 14%] tests/test_api_tasks.py::test_get_task_returns_done_status_for_completed_task PASSED [ 18%] tests/test_api_tasks.py::test_get_task_returns_invalid_id_for_bad_uuid PASSED [ 22%] tests/test_api_tasks.py::test_create_task_creates_new_backlog_task PASSED [ 25%] tests/test_api_tasks.py::test_create_task_trims_title PASSED [ 29%] tests/test_api_tasks.py::test_create_task_rejects_invalid_payload PASSED [ 33%] tests/test_api_tasks.py::test_update_task_updates_title PASSED [ 37%] tests/test_api_tasks.py::test_update_task_keeps_existing_timestamps FAILED [ 40%] tests/test_api_tasks.py::test_update_task_returns_not_found_for_missing_task PASSED [ 44%] tests/test_api_tasks.py::test_delete_task_removes_existing_task PASSED [ 48%] tests/test_api_tasks.py::test_delete_task_only_removes_target_task PASSED [ 51%] tests/test_api_tasks.py::test_delete_task_returns_invalid_id_for_bad_uuid PASSED [ 55%] tests/test_api_tasks.py::test_start_task_transitions_backlog_to_in_progress PASSED [ 59%] tests/test_api_tasks.py::test_start_task_is_idempotent FAILED [ 62%] tests/test_api_tasks.py::test_start_task_rejects_completed_task PASSED [ 66%] tests/test_api_tasks.py::test_done_task_transitions_in_progress_to_done FAILED [ 70%] tests/test_api_tasks.py::test_done_task_is_idempotent_for_completed_task FAILED [ 74%] tests/test_api_tasks.py::test_done_task_rejects_backlog_task PASSED [ 77%] tests/test_api_tasks.py::test_list_tasks_rejects_invalid_limit PASSED [ 81%] tests/test_api_tasks.py::test_get_task_returns_not_found_for_missing_uuid PASSED [ 85%] tests/test_api_tasks.py::test_patch_task_rejects_invalid_payload PASSED [ 88%] tests/test_api_tasks.py::test_delete_task_returns_not_found_for_missing_uuid PASSED [ 92%] tests/test_api_tasks.py::test_start_task_returns_not_found_for_missing_uuid PASSED [ 96%] tests/test_api_tasks.py::test_done_task_returns_not_found_for_missing_uuid PASSED [100%] =============================================================== FAILURES =============================================================== ______________________________________________ test_update_task_keeps_existing_timestamps ______________________________________________ tmp_path = PosixPath('/private/var/folders/6x/qy6dwbb95ng55w0rd2sqpf3w0000gn/T/pytest-of-kak/pytest-3/test_update_task_keeps_existin0') def test_update_task_keeps_existing_timestamps(tmp_path): client, repo = make_client(tmp_path) task = make_task(title="Workflow", started=True, done=True) repo.create_task(task) response = client.patch( f"/api/tasks/{task.id}", json={"title": "Workflow updated"}, ) assert response.status_code == 200 data = response.json() assert data["title"] == "Workflow updated" > assert data["started_at"] == task.started_at.isoformat() E AssertionError: assert '2026-03-29T15:47:28.534306Z' == '2026-03-29T1....534306+00:00' E E - 2026-03-29T15:47:28.534306+00:00 E ? ^^^^^^ E + 2026-03-29T15:47:28.534306Z E ? ^ tests/test_api_tasks.py:194: AssertionError ____________________________________________________ test_start_task_is_idempotent _____________________________________________________ tmp_path = PosixPath('/private/var/folders/6x/qy6dwbb95ng55w0rd2sqpf3w0000gn/T/pytest-of-kak/pytest-3/test_start_task_is_idempotent0') def test_start_task_is_idempotent(tmp_path): client, repo = make_client(tmp_path) task = make_task(title="Already started", started=True, done=False) repo.create_task(task) response = client.post(f"/api/tasks/{task.id}/start") assert response.status_code == 200 data = response.json() assert data["status"] == "in_progress" > assert data["started_at"] == task.started_at.isoformat() E AssertionError: assert '2026-03-29T15:47:28.560807Z' == '2026-03-29T1....560807+00:00' E E - 2026-03-29T15:47:28.560807+00:00 E ? ^^^^^^ E + 2026-03-29T15:47:28.560807Z E ? ^ tests/test_api_tasks.py:271: AssertionError ____________________________________________ test_done_task_transitions_in_progress_to_done ____________________________________________ tmp_path = PosixPath('/private/var/folders/6x/qy6dwbb95ng55w0rd2sqpf3w0000gn/T/pytest-of-kak/pytest-3/test_done_task_transitions_in_0') def test_done_task_transitions_in_progress_to_done(tmp_path): client, repo = make_client(tmp_path) task = make_task(title="Complete me", started=True, done=False) repo.create_task(task) before_call = datetime.now(UTC) response = client.post(f"/api/tasks/{task.id}/done") after_call = datetime.now(UTC) assert response.status_code == 200 data = response.json() assert data["status"] == "done" > assert data["started_at"] == task.started_at.isoformat() E AssertionError: assert '2026-03-29T15:47:28.568179Z' == '2026-03-29T1....568179+00:00' E E - 2026-03-29T15:47:28.568179+00:00 E ? ^^^^^^ E + 2026-03-29T15:47:28.568179Z E ? ^ tests/test_api_tasks.py:297: AssertionError ___________________________________________ test_done_task_is_idempotent_for_completed_task ____________________________________________ tmp_path = PosixPath('/private/var/folders/6x/qy6dwbb95ng55w0rd2sqpf3w0000gn/T/pytest-of-kak/pytest-3/test_done_task_is_idempotent_f0') def test_done_task_is_idempotent_for_completed_task(tmp_path): client, repo = make_client(tmp_path) task = make_task(title="Already done", started=True, done=True) repo.create_task(task) response = client.post(f"/api/tasks/{task.id}/done") assert response.status_code == 200 data = response.json() assert data["status"] == "done" > assert data["done_at"] == task.done_at.isoformat() E AssertionError: assert '2026-03-29T15:56:28.572797Z' == '2026-03-29T1....572797+00:00' E E - 2026-03-29T15:56:28.572797+00:00 E ? ^^^^^^ E + 2026-03-29T15:56:28.572797Z E ? ^ tests/test_api_tasks.py:313: AssertionError ======================================================= short test summary info ======================================================== FAILED tests/test_api_tasks.py::test_update_task_keeps_existing_timestamps - AssertionError: assert '2026-03-29T15:47:28.534306Z' == '2026-03-29T1....534306+00:00' FAILED tests/test_api_tasks.py::test_start_task_is_idempotent - AssertionError: assert '2026-03-29T15:47:28.560807Z' == '2026-03-29T1....560807+00:00' FAILED tests/test_api_tasks.py::test_done_task_transitions_in_progress_to_done - AssertionError: assert '2026-03-29T15:47:28.568179Z' == '2026-03-29T1....568179+00:00' FAILED tests/test_api_tasks.py::test_done_task_is_idempotent_for_completed_task - AssertionError: assert '2026-03-29T15:56:28.572797Z' == '2026-03-29T1....572797+00:00' ===================================================== 4 failed, 23 passed in 0.22s ===================================================== некоторые тесты упали, верни дифф ## Prompt 18: export csv endpoint сгенерируй код экспорта csv, верни diff ## Prompt 19: testplan for csv export спланируй тесты для экспорта csv, учти корректность MIME. верни в виде таблицы ## Prompt 20: tests for csv export напиши код предложенных тестов, верни дифф ## Prompt 21: stats page напиши код возврата HTML-страницы /stats, шаблон размести в /templates. реализуй динамическое обновление блока с информацией о выбранной задаче по клику на плашках задач в доске. верни дифф ## Prompt 22: testplan for stats page спланируй тесты для /stats. выведи в виде таблицы ## Prompt 23: tests for stats page напиши код предложенных тестов. верни дифф ## Prompt 24: fix tests fails (task-flow) kak@BigBrother task_flow % pytest -v tests/test_api_stats.py ========================================================= test session starts ========================================================== platform darwin -- Python 3.14.2, pytest-9.0.2, pluggy-1.6.0 -- /Users/kak/Documents/Projects/vibe_coding_learning/task_flow/.venv/bin/python3 cachedir: .pytest_cache rootdir: /Users/kak/Documents/Projects/vibe_coding_learning/task_flow configfile: pyproject.toml plugins: anyio-4.13.0 collected 12 items tests/test_api_stats.py::test_stats_returns_html_page_for_empty_board PASSED [ 8%] tests/test_api_stats.py::test_stats_renders_tasks_in_all_kanban_columns PASSED [ 16%] tests/test_api_stats.py::test_stats_preselects_first_task_in_details_block FAILED [ 25%] tests/test_api_stats.py::test_stats_shows_placeholders_for_missing_dates PASSED [ 33%] tests/test_api_stats.py::test_stats_renders_cycle_time_for_completed_task PASSED [ 41%] tests/test_api_stats.py::test_stats_embeds_task_payload_for_client_side_switching PASSED [ 50%] tests/test_api_stats.py::test_stats_includes_js_hooks_for_dynamic_selected_task_update PASSED [ 58%] tests/test_api_stats.py::test_stats_handles_utf8_titles PASSED [ 66%] tests/test_api_stats.py::test_stats_escapes_html_in_task_title PASSED [ 75%] tests/test_api_stats.py::test_stats_rejects_unsupported_method PASSED [ 83%] tests/test_api_stats.py::test_stats_still_works_after_recovery_from_corrupted_file PASSED [ 91%] tests/test_api_stats.py::test_stats_renders_created_started_and_done_values_for_completed_task FAILED [100%] =============================================================== FAILURES =============================================================== __________________________________________ test_stats_preselects_first_task_in_details_block ___________________________________________ tmp_path = PosixPath('/private/var/folders/6x/qy6dwbb95ng55w0rd2sqpf3w0000gn/T/pytest-of-kak/pytest-7/test_stats_preselects_first_ta0') def test_stats_preselects_first_task_in_details_block(tmp_path): client, repo = make_client(tmp_path) first = make_task(title="First task", started=False, done=False) second = make_task(title="Second task", started=True, done=False) repo.create_task(first) repo.create_task(second) response = client.get("/stats") assert response.status_code == 200 assert 'id="selected-title"' in response.text assert 'id="selected-created-at"' in response.text assert "First task" in response.text > assert first.created_at.isoformat().replace("+00:00", "Z") in response.text E assert '2026-03-29T16:05:30.901908Z' in '\n\n\n \n \n TaskFlow Stats\n