fix(pipeline-oracle): explicit API failure handling in issue resolution #85

Closed
opened 2026-08-16 20:11:08 +03:00 by slaid098 · 0 comments
Owner

Контекст

Аудитом после PR #80 найдены два robustness-дефекта в .opencode/scripts/pipeline-status.py:

  1. resolve_number() (~1016-1045): на шаге GET /issues/{N} ЛЮБОЙ non-200 (500, 401, сетевой сбой) классифицируется как «ghost» → пользователь получает вводящее в заблуждение «Не существует ни PR, ни issue с номером N», хотя сбойнул сам API.
  2. find_open_prs_for_issue() (~1048-1078): при non-200 на любой странице пагинации цикл молча обрывается (break) → усечённый список кандидатов → возможен ЛОЖНЫЙ bootstrap (NEXT: template=A for issue #N при реально существующем PR) → риск дубль-PR, от которого система только что избавилась.

Задача

  1. В resolve_number(): различать 404 (числа действительно нет ни среди PR, ни среди issues → ghost-поведение сохранить) от прочих non-200/сетевых ошибок → AMBIGUOUS: сбой Forgejo API при проверке issue #N (<код/описание>) — повторите позже. НЕ ghost, НЕ bootstrap.
  2. В find_open_prs_for_issue(): non-200 на любой странице → результат помечается недостоверным; вызывающая сторона выдаёт AMBIGUOUS: не удалось получить список открытых PR (сбой API) вместо bootstrap/детерминированного ответа.
  3. Happy-path ветки (404-ghost, 0 кандидатов → bootstrap, 1 кандидат → резолюция, 2+ → AMBIGUOUS) не менять.
  4. Тесты новых веток: 500 от /issues/{N} → AMBIGUOUS (не ghost); сбой на 2-й странице пагинации PR → AMBIGUOUS (не bootstrap); сетевое исключение → AMBIGUOUS.

Контракты

  • Текст bootstrap-ответа NEXT: dispatch subagent (subagent_type=general, template=A) for issue #N и exit-коды существующих веток не меняются.
  • Новые AMBIGUOUS-строки — в существующем формате (AMBIGUOUS: <причина> + NEXT: уточните статус вручную), чтобы оркестратор трактовал их единообразно (STOP).

Инварианты

  • Скрипт остаётся read-only (только GET).
  • Существующие тесты резолюции (test_resolve_number_*, test_main_*) зелёные.

Граничные случаи

  • 404 от /issues/{N} после 404 от /pulls/{N} — по-прежнему ghost, exit 1 (не AMBIGUOUS).
  • 401 — AMBIGUOUS с указанием проверить FORGEJO_TOKEN.

Влияние на связанные компоненты

  • run-pipeline SKILL.md трактует любой AMBIGUOUS как STOP — новые строки совместимы, правок скилла не требуется.

Вне scope

  • Retry/бэкофф к Forgejo API.
  • Изменения других scripts/tools.

Критерии приемки

  • pytest tests/test_pipeline_status*.py зелёный, включая 3 новых теста сбоев API.
  • В resolve_number 404 явно отделён от прочих статусов.
  • В find_open_prs_for_issue молчаливый обрыв пагинации невозможен: либо полный список, либо флаг недостоверности.
## Контекст Аудитом после PR #80 найдены два robustness-дефекта в `.opencode/scripts/pipeline-status.py`: 1. `resolve_number()` (~1016-1045): на шаге `GET /issues/{N}` ЛЮБОЙ non-200 (500, 401, сетевой сбой) классифицируется как «ghost» → пользователь получает вводящее в заблуждение «Не существует ни PR, ни issue с номером N», хотя сбойнул сам API. 2. `find_open_prs_for_issue()` (~1048-1078): при non-200 на любой странице пагинации цикл молча обрывается (`break`) → усечённый список кандидатов → возможен ЛОЖНЫЙ bootstrap (`NEXT: template=A for issue #N` при реально существующем PR) → риск дубль-PR, от которого система только что избавилась. ## Задача 1. В `resolve_number()`: различать 404 (числа действительно нет ни среди PR, ни среди issues → ghost-поведение сохранить) от прочих non-200/сетевых ошибок → `AMBIGUOUS: сбой Forgejo API при проверке issue #N (<код/описание>) — повторите позже`. НЕ ghost, НЕ bootstrap. 2. В `find_open_prs_for_issue()`: non-200 на любой странице → результат помечается недостоверным; вызывающая сторона выдаёт `AMBIGUOUS: не удалось получить список открытых PR (сбой API)` вместо bootstrap/детерминированного ответа. 3. Happy-path ветки (404-ghost, 0 кандидатов → bootstrap, 1 кандидат → резолюция, 2+ → AMBIGUOUS) не менять. 4. Тесты новых веток: 500 от `/issues/{N}` → AMBIGUOUS (не ghost); сбой на 2-й странице пагинации PR → AMBIGUOUS (не bootstrap); сетевое исключение → AMBIGUOUS. ## Контракты - Текст bootstrap-ответа `NEXT: dispatch subagent (subagent_type=general, template=A) for issue #N` и exit-коды существующих веток не меняются. - Новые AMBIGUOUS-строки — в существующем формате (`AMBIGUOUS: <причина>` + `NEXT: уточните статус вручную`), чтобы оркестратор трактовал их единообразно (STOP). ## Инварианты - Скрипт остаётся read-only (только GET). - Существующие тесты резолюции (`test_resolve_number_*`, `test_main_*`) зелёные. ## Граничные случаи - 404 от `/issues/{N}` после 404 от `/pulls/{N}` — по-прежнему ghost, exit 1 (не AMBIGUOUS). - 401 — AMBIGUOUS с указанием проверить FORGEJO_TOKEN. ## Влияние на связанные компоненты - run-pipeline SKILL.md трактует любой `AMBIGUOUS` как STOP — новые строки совместимы, правок скилла не требуется. ## Вне scope - Retry/бэкофф к Forgejo API. - Изменения других scripts/tools. ## Критерии приемки - `pytest tests/test_pipeline_status*.py` зелёный, включая 3 новых теста сбоев API. - В `resolve_number` 404 явно отделён от прочих статусов. - В `find_open_prs_for_issue` молчаливый обрыв пагинации невозможен: либо полный список, либо флаг недостоверности.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
slaid098/opencode-config#85
No description provided.