Агент v16: зазор между записями и сверка поля оценки доски (#53, I-1, I-2)
I-1: если ensure_fields записал поля через PUT /issue, перед записью оценки — зазор ensure_fields. I-2: fieldId оценки доски сверяется с field_ids.story_points; расхождение — failed без записи. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
a3247d6f2d
commit
20747c2b65
@ -32,3 +32,5 @@ the appropriate screen, or unknown». Поле оценки не на экран
|
|||||||
| 25.10.2026 | R-2: сначала остальные поля, затем оценка | новый путь не должен ломать остальные поля | частичная запись, повтор безопасен |
|
| 25.10.2026 | R-2: сначала остальные поля, затем оценка | новый путь не должен ломать остальные поля | частичная запись, повтор безопасен |
|
||||||
| 25.10.2026 | R-3: без `GET /issue`, если в команде только оценка | минус вызов Jira на команду в пакете оценок | нет |
|
| 25.10.2026 | R-3: без `GET /issue`, если в команде только оценка | минус вызов Jira на команду в пакете оценок | нет |
|
||||||
| 25.10.2026 | R-5: `value` — число как есть | Jira отдаёт число; живая проверка до пакета | одна правка агента |
|
| 25.10.2026 | R-5: `value` — число как есть | Jira отдаёт число; живая проверка до пакета | одна правка агента |
|
||||||
|
| 25.10.2026 | I-1 (финальное ревью): между `PUT /issue` и `PUT …/estimation` одной команды — зазор `ensure_fields` | политика темпа: зазор между записями внутри команды | пакет «оценка + поля» идёт медленнее |
|
||||||
|
| 25.10.2026 | I-2 (финальное ревью): `fieldId` оценки доски сверяется с `field_ids.story_points` (если задан), расхождение — `failed` без записи | иначе число уйдёт в чужое поле доски другого проекта | лишний отказ, если поле настроено неверно — правится настройкой |
|
||||||
|
|||||||
@ -890,7 +890,14 @@ class Executor:
|
|||||||
changed = self.ensure_issue_fields(key, p, sp_fid)
|
changed = self.ensure_issue_fields(key, p, sp_fid)
|
||||||
if by_board:
|
if by_board:
|
||||||
path = AGILE + "/issue/%s/estimation" % key
|
path = AGILE + "/issue/%s/estimation" % key
|
||||||
if not _same_points(self.jira.get(path, boardId=p["board_id"]).get("value"), p["story_points"]):
|
est = self.jira.get(path, boardId=p["board_id"])
|
||||||
|
own = (self.s.get("field_ids") or {}).get("story_points")
|
||||||
|
if own and est.get("fieldId") and est["fieldId"] != own: # доска оценивает другим полем — не писать туда
|
||||||
|
return self._out("failed", error="у доски %s оценка — поле %s, а не story points (%s)"
|
||||||
|
% (p["board_id"], est["fieldId"], own))
|
||||||
|
if not _same_points(est.get("value"), p["story_points"]):
|
||||||
|
if changed: # вторая запись команды — по зазору типа (политика темпа)
|
||||||
|
self.gap("ensure_fields")
|
||||||
self.jira.call("PUT", path, {"value": p["story_points"]}, params={"boardId": p["board_id"]})
|
self.jira.call("PUT", path, {"value": p["story_points"]}, params={"boardId": p["board_id"]})
|
||||||
changed.append("story_points")
|
changed.append("story_points")
|
||||||
return self._out("done", {"changed": changed})
|
return self._out("done", {"changed": changed})
|
||||||
|
|||||||
@ -352,5 +352,26 @@ class ExecutorFieldsTest(unittest.TestCase):
|
|||||||
self.assertEqual((out["status"], out["error"]), ("failed", "story_points — число ≥ 0 или null"))
|
self.assertEqual((out["status"], out["error"]), ("failed", "story_points — число ≥ 0 или null"))
|
||||||
self.assertEqual(self.fake.requests, [])
|
self.assertEqual(self.fake.requests, [])
|
||||||
|
|
||||||
|
def test_points_by_board_gap_after_fields(self): # I-1: зазор ensure_fields между двумя записями
|
||||||
|
gaps = []
|
||||||
|
self.ex.sleep = gaps.append
|
||||||
|
self.ex.s["pacing"] = {"ensure_fields": 120}
|
||||||
|
self.points("AURORA-1", None)
|
||||||
|
self.run_cmd("ensure_fields", key="AURORA-1", duedate="2026-10-30", story_points=3, board_id=4216)
|
||||||
|
self.assertEqual(gaps, [120])
|
||||||
|
self.run_cmd("ensure_fields", key="AURORA-1", duedate="2026-10-30", story_points=5, board_id=4216)
|
||||||
|
self.assertEqual(gaps, [120]) # PUT /issue не было — паузы нет
|
||||||
|
|
||||||
|
def test_points_by_board_other_field(self): # I-2: оценка доски — не поле story points
|
||||||
|
self.points("AURORA-1", 1.0)
|
||||||
|
self.ex.s["field_ids"] = dict(SETTINGS["field_ids"], story_points="customfield_20000")
|
||||||
|
out = self.run_cmd("ensure_fields", key="AURORA-1", story_points=2, board_id=4216)
|
||||||
|
self.assertEqual((out["status"], out["error"]),
|
||||||
|
("failed", "у доски 4216 оценка — поле customfield_10106, а не story points (customfield_20000)"))
|
||||||
|
self.assertEqual(self.fake.estimation_bodies, [])
|
||||||
|
self.ex.s["field_ids"] = dict(SETTINGS["field_ids"], story_points="customfield_10106")
|
||||||
|
out = self.run_cmd("ensure_fields", key="AURORA-1", story_points=2, board_id=4216)
|
||||||
|
self.assertEqual(out["result"], {"changed": ["story_points"]})
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user