Two safety follow-ups к autonomous-pipeline (flagged в multiagent-аудите):
- Self-extending guard расширен: reviewer-bot NEVER merge'ит PR, меняющий
_autonomous_pickup.md (claim/kill-switch/merge-FSM contract) или любой
work-as-*.md (persona activation) — раньше защищались только git-pr.md
Auto-merge policy + CLAUDE.md + auto-code-reviewer.md. Закрывает дыру, где
bot мог изменить claim/kill-switch logic без human. Правки в git-pr.md,
auto-code-reviewer.md, work-as-reviewer.md.
- cleanup-stale-claims.sh: pause-bots early-exit. Без него cron освобождал
wip-claim worker'а, приостановленного mid-work (он держит claim до un-pause
per _autonomous_pickup.md), теряя его работу.
🔴 Critical (3):
1. cleanup-stale-claims.sh: export CUTOFF + STALE_HOURS
Без `export` Python heredoc child process получал "0" вместо реального
cutoff → cron всегда видел все issues как fresh → ничего не освобождал.
Plus added abort при CUTOFF=0 в Python heredoc для defense-in-depth.
2. cleanup-stale-claims.sh: datetime.UTC → datetime.timezone.utc
datetime.UTC требует Python 3.11+. Forgejo runner ubuntu-latest имеет 3.10.
datetime.timezone.utc works в 3.8+.
3. cleanup-stale-claims.sh: invert label order — DELETE wip FIRST, потом
POST ready. Если step 2 (add ready) fails — issue в neutral state без
status/*, менее опасно чем оба status/ready+status/wip одновременно.
🟠 + 🟡 + 🟢 (5):
4. Added pagination loop (defensive cap 10 pages × 50 = 500 issues), но
реализована через temp file + Python parsing (не bash JSON concat).
5. Removed dead code: iso_to_epoch() shell helper не использовался.
6. _autonomous_pickup.md: fix broken `Out-Null | if (-not $?)` pattern.
GetEnvironmentVariable НЕ throws при missing — возвращает $null. $? у
Get* всегда $true. Заменено на прямую проверку результата.
7. stale-claims.yml: добавлен concurrency group чтобы overlapping runs
не stomp'ились (хотя 5-min timeout делает overlap unlikely, defensive).
8. Documented updated_at != heartbeat assumption в header script'а.
Не сделано (low/optional):
- Setup script tokens в memory (UX trade-off — не critical)
- Token suffix в console output (минор info leak в shell history)
Refs: PR #610 review by review-bot (sha=297eb29, verdict=changes)
#11: slash-commands и _autonomous_pickup.md теперь читают persistent User-scope
env vars напрямую (FORGEJO_TOKEN_<ROLE>) вместо file-based из ~/.claude/secrets/.
Один раз: scripts/setup-bot-env.ps1 (запускается user'ом локально, кладёт
токены из vault в Windows User registry). После этого окна grab credentials
через [System.Environment]::GetEnvironmentVariable() — никаких файлов.
Все 5 work-as-*.md обновлены (analyst/backend/frontend/reviewer/qa).
#12: stale-claim cleanup — cron каждые 30 минут.
- scripts/cleanup-stale-claims.sh — bash, parses Forgejo API + Python для JSON
- .forgejo/workflows/stale-claims.yml — cron schedule `*/30 * * * *`
Освобождает issues застрявшие в status/wip >4h:
- assignees=[]
- +status/ready -status/wip
- comment "stale claim released, worker likely crashed"
Использует secret FORGEJO_BOT_QA_TOKEN (минимум прав = write:issue).
Setup: secret нужно завести в Forgejo Actions UI после merge —
git.gendsgn.ru/lekss361/gendesign/-/settings/actions/secrets.
Refs: PRs #608, #609. Closes TODO с PR #608 (stale-claim cron).