# Агент v16: оценка через доску Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** `ensure_fields` со `story_points` и `board_id` ставит оценку через `/rest/agile/1.0/issue/{key}/estimation?boardId=…`. **Architecture:** в `Executor.do_ensure_fields` ветка оценки с доской отделяется от `PUT /issue`: сначала остальные поля (как v15, `GET /issue` только если они есть), затем `GET`/`PUT` оценки доски. Без `board_id` — путь v15. **Tech Stack:** Python 3.9 stdlib, unittest; фейк Jira — `tests/fake_jira.py`. **Spec:** `sdlc-hub/openspec/changes/sp-estimation-board/specs/agent/spec.md`, `…/specs/commands/spec.md`; решения — `openspec/changes/agent-v16-sp-estimation/design.md`. ## Global Constraints - `AGENT_VERSION = 16`; Python 3.9, только stdlib (`tests/test_py39.py`). - Тело `PUT`: `{"value": <число или null>}`; путь `AGILE + "/issue/%s/estimation"` с параметром `boardId`. - Сравнение — `_same_points`; плохое значение — `failed` «story_points — число ≥ 0 или null» до вызовов Jira. ## Review Focus 1. Команда только с оценкой — без `GET /issue` и `PUT /issue`; `jira_calls` 2 (запись) и 1 (без изменений). 2. Оценка и другие поля — `PUT /issue` без поля оценки, затем `PUT estimation`; `changed` — все поля. 3. Ошибка Jira на `PUT estimation` (400) — `failed`, остальные поля уже записаны. 4. `null` при пустой оценке — без записи; при `1.0` — `PUT {"value": null}`. 5. Без `board_id` — поведение v15 (существующие тесты `test_story_points_*` не меняются). --- ### Task 1: Оценка через estimation доски **Files:** - Modify: `tests/fake_jira.py` (маршрут `/rest/agile/1.0/issue/{key}/estimation`: `GET` → `{"fieldId": POINTS_FIELD, "value": <поле задачи>}`, `PUT` → пишет `value` в поле задачи, тело в `self.estimation_bodies`; доска не из `self.boards` → 400; задачи нет → 404; маршрут — до общего `/rest/agile/1.0/issue/([^/]+)$`) - Modify: `src/agent.py` (`do_ensure_fields`, `AGENT_VERSION = 16`) - Test: `tests/test_executor_fields.py` (раздел `# --- story_points через доску (#53)`) - [ ] **Step 1: Тесты:** - `test_points_by_board_set` — оценка `1.0`, `story_points=2, board_id=4216`: `result == {"changed": ["story_points"]}`, `jira_calls == 2`, `estimation_bodies == [{"value": 2}]`, `("PUT", "/rest/api/2/issue/AURORA-1704")` и `("GET", "/rest/api/2/issue/AURORA-1704")` нет в `requests`; - `test_points_by_board_same` — оценка `2.0`, `story_points=2`: `changed == []`, `jira_calls == 1`, записей нет; - `test_points_by_board_clear` — оценка `1.0`, `story_points=None` → тело `{"value": None}`; при пустой оценке — без записи; - `test_points_by_board_with_fields` — `duedate` + `story_points`: `PUT /issue` без `customfield_10106`, потом `PUT estimation`; `changed == ["duedate", "story_points"]`; - `test_points_by_board_jira_error` — доска 9999 (нет у фейка): `failed`, `duedate` уже записан; - `test_points_by_board_no_field_lookup` — `fake.fields = []`: всё равно `done` (без `GET /field`); - `test_points_by_board_bad_value` — `"3"` → `failed`, `requests` пуст. - [ ] **Step 2:** `/usr/bin/python3 -m unittest tests.test_executor_fields` — FAIL. - [ ] **Step 3:** `do_ensure_fields`: при `board_id` и `story_points` — путь доски (R-1…R-3 design), иначе v15; `AGENT_VERSION = 16`. - [ ] **Step 4:** `/usr/bin/python3 -W error::ResourceWarning -m unittest discover -s tests -t .` — зелёный. - [ ] **Step 5:** commit «Агент v16: оценка через estimation доски (#53)».