fix(skills): add --max-time to all forgejo curl commands #46

Merged
slaid098 merged 5 commits from fix/skills/curl-max-time into main 2026-08-11 17:01:48 +03:00
Owner

Что сделано

Глобальный grep-replace всех curl команд к $FORGEJO_URL/git.slaid098.dev//api/v1/ в .opencode/**/*.md — добавлены --max-time 30 --connect-timeout 10 (30с общий таймаут, 10с на connect) после curl -s (или после curl -sX POST/PATCH/PUT).

Затронутые файлы:

  • Skills: run-pipeline/SKILL.md, issue/SKILL.md, repo-readme/SKILL.md, release/SKILL.md, project-template/SKILL.md (4 curl: repo-exists, repo create, settings, branch protection + дубль в edge-cases блоке), bug-discovery/SKILL.md
  • Agents: reviewer.md, memory-syncer.md — обновлены и инструкции (4 call site), и allow-rules в frontmatter (см. Watch out)
  • Тесты: tests/test_permissions.py — 4 новых regression-теста

bug-discovery/SKILL.md duplicate-check: добавлены &limit=50&page=1 к query string (пагинация вместо листания всех open issues). Документировано в комментарии, что это first-page check — агент может пагинировать &page=2 если >50 issues.

Почему

PR#41 (issue #40) пофиксил hang в _shared.ts:callForgejo через urlopen timeout. Но 20+ curl-вызовов к Forgejo API в skills/agents — все без --max-time/--connect-timeout (curl default = infinite). Агенты выполняют эти curl в bash, полностью bypass'я _shared.ts. Тот же класс 5-мин hang'а при недоступности Forgejo: curl ждет бесконечно, агент молчит, pipeline висит. Timeout заставляет curl fail fast (exit code 28), агент видит ошибку и репортит.

Watch out

Spec deviation (зафиксировано, не додумано): issue #43 пункт 3 утверждал, что permission rules не сломаются — "флаги --max-time/--connect-timeout не должны влиять на match". Это оказалось неверно для agent frontmatter rules: reviewer.md и memory-syncer.md имели literal allow-rules "curl -s -H ...": allow (БЕЗ wildcard * между -s и -H). Новая команда curl -s --max-time 30 -H ... НЕ матчит literal curl -s -H → попадает в catch-all "*": deny → agent не может читать PR metadata. Поэтому allow-rules в обоих агентах обновлены синхронно с инструкциями (добавлены --max-time 30 --connect-timeout 10 в сам pattern).

Глобальный opencode.json:230 "curl *": "allow" — матчит (glob * поглощает флаги), не тронут. Глобальный deny "curl * -X DELETE *FORGEJO_URL*" (safety net) — также продолжает работать (* между curl и -X).

--max-time 30 для POST-запросов с upload (release create с assets) может быть tight, но release create в release/SKILL.md:76 идёт без assets (assets — отдельный шаг, web UI), 30с достаточно. Если станет узким местом — вынести в отдельный issue.

Тест test_no_forgejo_curl_without_max_time_in_skills намеренно исключает строки с git.slaid098.dev (там где URL упоминается в prose, не в curl-команде) и требует чтобы curl был в части строки ДО $FORGEJO_URL (т.е. реальная команда, не комментарий про curl после URL).

Pending

—\n\nCloses #43

Closes #43

## Что сделано Глобальный grep-replace всех `curl` команд к `$FORGEJO_URL`/`git.slaid098.dev`/`/api/v1/` в `.opencode/**/*.md` — добавлены `--max-time 30 --connect-timeout 10` (30с общий таймаут, 10с на connect) после `curl -s` (или после `curl -sX POST/PATCH/PUT`). Затронутые файлы: - **Skills**: `run-pipeline/SKILL.md`, `issue/SKILL.md`, `repo-readme/SKILL.md`, `release/SKILL.md`, `project-template/SKILL.md` (4 curl: repo-exists, repo create, settings, branch protection + дубль в edge-cases блоке), `bug-discovery/SKILL.md` - **Agents**: `reviewer.md`, `memory-syncer.md` — обновлены и инструкции (4 call site), и **allow-rules в frontmatter** (см. Watch out) - **Тесты**: `tests/test_permissions.py` — 4 новых regression-теста `bug-discovery/SKILL.md` duplicate-check: добавлены `&limit=50&page=1` к query string (пагинация вместо листания всех open issues). Документировано в комментарии, что это first-page check — агент может пагинировать `&page=2` если >50 issues. ## Почему PR#41 (issue #40) пофиксил hang в `_shared.ts:callForgejo` через `urlopen` timeout. Но 20+ curl-вызовов к Forgejo API в skills/agents — все без `--max-time`/`--connect-timeout` (curl default = infinite). Агенты выполняют эти curl в bash, полностью bypass'я `_shared.ts`. Тот же класс 5-мин hang'а при недоступности Forgejo: curl ждет бесконечно, агент молчит, pipeline висит. Timeout заставляет curl fail fast (exit code 28), агент видит ошибку и репортит. ## Watch out **Spec deviation (зафиксировано, не додумано)**: issue #43 пункт 3 утверждал, что permission rules не сломаются — *"флаги `--max-time`/`--connect-timeout` не должны влиять на match"*. Это оказалось **неверно для agent frontmatter rules**: `reviewer.md` и `memory-syncer.md` имели literal allow-rules `"curl -s -H ...": allow` (БЕЗ wildcard `*` между `-s` и `-H`). Новая команда `curl -s --max-time 30 -H ...` НЕ матчит literal `curl -s -H` → попадает в catch-all `"*": deny` → agent не может читать PR metadata. Поэтому allow-rules в обоих агентах обновлены синхронно с инструкциями (добавлены `--max-time 30 --connect-timeout 10` в сам pattern). Глобальный `opencode.json:230` `"curl *": "allow"` — матчит (glob `*` поглощает флаги), не тронут. Глобальный deny `"curl * -X DELETE *FORGEJO_URL*"` (safety net) — также продолжает работать (`*` между `curl` и `-X`). `--max-time 30` для POST-запросов с upload (release create с assets) может быть tight, но release create в `release/SKILL.md:76` идёт без assets (assets — отдельный шаг, web UI), 30с достаточно. Если станет узким местом — вынести в отдельный issue. Тест `test_no_forgejo_curl_without_max_time_in_skills` намеренно исключает строки с `git.slaid098.dev` (там где URL упоминается в prose, не в curl-команде) и требует чтобы `curl` был в части строки ДО `$FORGEJO_URL` (т.е. реальная команда, не комментарий про curl после URL). ## Pending —\n\nCloses #43 Closes #43
test(permissions): add curl --max-time regression tests for issue #43
Some checks failed
CI (always) / bootstrap (pull_request) Successful in 6s
CI / bootstrap (pull_request) Successful in 9s
Permission Security Check / check (pull_request) Successful in 11s
CI / complexity (pull_request) Successful in 27s
CI / typecheck (pull_request) Successful in 27s
CI / lint (pull_request) Failing after 27s
CI / test (3.13) (pull_request) Successful in 1m39s
2e490cb431
chore(ci): trigger fresh CI run
Some checks failed
CI (always) / bootstrap (pull_request) Successful in 4s
CI / bootstrap (pull_request) Successful in 7s
Permission Security Check / check (pull_request) Successful in 9s
CI / typecheck (pull_request) Successful in 26s
CI / complexity (pull_request) Successful in 26s
CI / lint (pull_request) Failing after 26s
CI / test (3.13) (pull_request) Successful in 1m35s
be7b6fea4c
style(tests): ruff format test_permissions assertion
All checks were successful
CI (always) / bootstrap (pull_request) Successful in 7s
CI / bootstrap (pull_request) Successful in 12s
Permission Security Check / check (pull_request) Successful in 12s
CI / lint (pull_request) Successful in 23s
CI / typecheck (pull_request) Successful in 29s
CI / complexity (pull_request) Successful in 24s
CI / test (3.13) (pull_request) Successful in 1m59s
766b20a732
Author
Owner

Code Review Summary

PR добавляет --max-time 30 --connect-timeout 10 ко всем curl-командам к Forgejo API в skills/agents (issue #43, Волна 2), добавляет пагинацию &limit=50&page=1 в bug-discovery duplicate-check, синхронно обновляет agent frontmatter allow-rules и добавляет 4 regression-теста. Изменения полные, консистентные, CI green (23 теста проходят).

Что правильно

  • Полнота покрытия curl: все 11 curl-команд к $FORGEJO_URL в .opencode/**/*.md обновлены — skills (bug-discovery, run-pipeline ×2, issue, project-template ×4, repo-readme ×2, release) и agents (reviewer ×3, memory-syncer ×3). rg 'curl.*FORGEJO_URL' .opencode/ | rg -v --max-time возвращает только строку-описание project-template/SKILL.md:236 ("Все операции через curl к Forgejo API") — это не команда, false positive.
  • Синхронность frontmatter ↔ инструкции: agent allow-rules обновлены вместе с inline-инструкциями. Это критично — literal glob curl -s -H ... не поглощает --max-time (нет wildcard между curl -s и -H), поэтому без обновления rule новые команды падали бы в catch-all "*": deny. Тест test_agent_curl_allow_rules_have_max_time это проверяет.
  • Пагинация bug-discovery: &limit=50&page=1 с комментарием "first page only — paginate with &page=2 etc." — корректный подход (ограничение размера ответа + явная инструкция для >50 issues).
  • Regression-тесты: 4 новых теста покрывают именно точки регрессии:
    • test_agent_curl_allow_rules_have_max_time — frontmatter rules содержат флаги (writer-side).
    • test_global_curl_allow_matches_timed_commands — global curl * glob всё ещё матчит timed-команды через fnmatch (reader-side, подтверждает что global allow не сломан).
    • test_bug_discovery_skill_has_pagination_and_timeout — skill содержит оба инварианта.
    • test_no_forgejo_curl_without_max_time_in_skills — full-scan regression guard по .opencode/**/*.md с regex curl\s+-s(?:X\s+\w+)?\s+(?!.*--max-time).
  • Cross-file impact: writer (agent frontmatter) обновлён совместно с reader (check-permissions.py валидирует структуру — новые rules валидны, тест test_check_permissions_passes проходит). Связь pipeline-status.py ↔ post-review.ts не затронута (формат ### Verdict: не менялся).
  • CI-фиксы: ruff format на assertion + trigger fresh CI — гигиена коммитов корректна, стиль соответствует conventional commits (fix(skills), fix(agents), test(permissions), style(tests), chore(ci)).

Замечаний нет

Изменения полностью покрывают scope issue #43, тесты green, regression guard на месте. Готов к merge.

Verdict: APPROVE

## Code Review Summary PR добавляет `--max-time 30 --connect-timeout 10` ко всем curl-командам к Forgejo API в skills/agents (issue #43, Волна 2), добавляет пагинацию `&limit=50&page=1` в bug-discovery duplicate-check, синхронно обновляет agent frontmatter allow-rules и добавляет 4 regression-теста. Изменения полные, консистентные, CI green (23 теста проходят). ### Что правильно - **Полнота покрытия curl**: все 11 curl-команд к `$FORGEJO_URL` в `.opencode/**/*.md` обновлены — skills (bug-discovery, run-pipeline ×2, issue, project-template ×4, repo-readme ×2, release) и agents (reviewer ×3, memory-syncer ×3). `rg 'curl.*FORGEJO_URL' .opencode/ | rg -v --max-time` возвращает только строку-описание `project-template/SKILL.md:236` ("Все операции через `curl` к Forgejo API") — это не команда, false positive. - **Синхронность frontmatter ↔ инструкции**: agent allow-rules обновлены вместе с inline-инструкциями. Это критично — literal glob `curl -s -H ...` не поглощает `--max-time` (нет wildcard между `curl -s` и `-H`), поэтому без обновления rule новые команды падали бы в catch-all `"*": deny`. Тест `test_agent_curl_allow_rules_have_max_time` это проверяет. - **Пагинация bug-discovery**: `&limit=50&page=1` с комментарием "first page only — paginate with `&page=2` etc." — корректный подход (ограничение размера ответа + явная инструкция для >50 issues). - **Regression-тесты**: 4 новых теста покрывают именно точки регрессии: - `test_agent_curl_allow_rules_have_max_time` — frontmatter rules содержат флаги (writer-side). - `test_global_curl_allow_matches_timed_commands` — global `curl *` glob всё ещё матчит timed-команды через `fnmatch` (reader-side, подтверждает что global allow не сломан). - `test_bug_discovery_skill_has_pagination_and_timeout` — skill содержит оба инварианта. - `test_no_forgejo_curl_without_max_time_in_skills` — full-scan regression guard по `.opencode/**/*.md` с regex `curl\s+-s(?:X\s+\w+)?\s+(?!.*--max-time)`. - **Cross-file impact**: writer (agent frontmatter) обновлён совместно с reader (`check-permissions.py` валидирует структуру — новые rules валидны, тест `test_check_permissions_passes` проходит). Связь `pipeline-status.py ↔ post-review.ts` не затронута (формат `### Verdict:` не менялся). - **CI-фиксы**: `ruff format` на assertion + trigger fresh CI — гигиена коммитов корректна, стиль соответствует conventional commits (`fix(skills)`, `fix(agents)`, `test(permissions)`, `style(tests)`, `chore(ci)`). ### Замечаний нет Изменения полностью покрывают scope issue #43, тесты green, regression guard на месте. Готов к merge. ### Verdict: APPROVE
slaid098 deleted branch fix/skills/curl-max-time 2026-08-11 17:01:48 +03:00
Sign in to join this conversation.
No reviewers
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!46
No description provided.