[PIX-12937] Merge-очередь orphan-веток партия 2 (12 веток) #160

Merged
andrei merged 14 commits from merge/pix-12937-batch2 into master 2026-07-04 08:39:05 +00:00
Owner

Что сделано

Влиты 12 orphan-веток из аудита PIX-12932 (batch 2): agent/fullstack/pix-13055, pix-12998, pix-12993, pix-12985, pix-12212, pix-11638, pix-11528, pix-11433, pix-12682; agent/devops/pix-13883, pix-13218, pix-13138.

В ходе перебазирования исправлены реальные баги, обнаруженные при typecheck/тестах:

  • heartbeat.ts: reconcileProcesslessRunsTargetingTerminalIssues ссылался на несуществующую колонку heartbeatRuns.issueId, исправлено на join через issues.executionRunId
  • heartbeat.ts: некорректный generic-тип в Parameters<typeof db.update<...>> заменён на устоявшийся паттерн Partial<typeof heartbeatRuns.$inferInsert>
  • routes/issues.ts: /issues/:id/low-trust/promotions не передавал обязательное поле status
  • heartbeat-processless-run-reconciliation.test.ts переписан на embedded-postgres фикстуру
  • pix-11638-build-regression.test.ts: убрана некорректная runtime-проверка require.resolve для types-only пакета
  • approvals-lite.test.ts: isAuthenticated возвращал строку вместо boolean из-за короткого замыкания &&
  • git-delivery-gate.ts: STRONG/WEAK regex-детекторы не распознавали "PR created" и множественное число "тесты" — добавлены недостающие альтернативы

Зачем

Эти ветки содержат уникальную работу (багфиксы, тесты, фичи), которая не была влита в master. Дочерняя задача от orphan-branch audit PIX-12932.

План тестирования

  • pnpm --filter @paperclipai/server exec tsc --noEmit — 0 ошибок
  • Целевые regression-тесты (approvals-lite, heartbeat-processless-run-reconciliation, pix-11638-build-regression, git-delivery-gate-*) — все проходят
  • node scripts/check-no-git-push.mjs — 0 нарушений (ложное срабатывание на тестовых строках-фикстурах закрыто маркером paperclip:allow-git-push)
  • Полный pre-push CI (typecheck по всему workspace + check:no-git-push) пройден локально перед push

Где могу ошибаться

  • Полный vitest run по всему workspace не запускался в рамках этого heartbeat (только targeted-тесты для изменённых файлов) из-за бюджета времени — рекомендую отдельный CI-прогон перед мержем.
  • Изменения в git-delivery-gate.ts затрагивают gate логики done-статуса для issues — стоит last-look ревью на предмет false positive/negative в проде.
## Что сделано Влиты 12 orphan-веток из аудита PIX-12932 (batch 2): agent/fullstack/pix-13055, pix-12998, pix-12993, pix-12985, pix-12212, pix-11638, pix-11528, pix-11433, pix-12682; agent/devops/pix-13883, pix-13218, pix-13138. В ходе перебазирования исправлены реальные баги, обнаруженные при typecheck/тестах: - heartbeat.ts: reconcileProcesslessRunsTargetingTerminalIssues ссылался на несуществующую колонку heartbeatRuns.issueId, исправлено на join через issues.executionRunId - heartbeat.ts: некорректный generic-тип в Parameters<typeof db.update<...>> заменён на устоявшийся паттерн Partial<typeof heartbeatRuns.$inferInsert> - routes/issues.ts: /issues/:id/low-trust/promotions не передавал обязательное поле status - heartbeat-processless-run-reconciliation.test.ts переписан на embedded-postgres фикстуру - pix-11638-build-regression.test.ts: убрана некорректная runtime-проверка require.resolve для types-only пакета - approvals-lite.test.ts: isAuthenticated возвращал строку вместо boolean из-за короткого замыкания && - git-delivery-gate.ts: STRONG/WEAK regex-детекторы не распознавали "PR created" и множественное число "тесты" — добавлены недостающие альтернативы ## Зачем Эти ветки содержат уникальную работу (багфиксы, тесты, фичи), которая не была влита в master. Дочерняя задача от orphan-branch audit PIX-12932. ## План тестирования - `pnpm --filter @paperclipai/server exec tsc --noEmit` — 0 ошибок - Целевые regression-тесты (approvals-lite, heartbeat-processless-run-reconciliation, pix-11638-build-regression, git-delivery-gate-*) — все проходят - `node scripts/check-no-git-push.mjs` — 0 нарушений (ложное срабатывание на тестовых строках-фикстурах закрыто маркером paperclip:allow-git-push) - Полный pre-push CI (typecheck по всему workspace + check:no-git-push) пройден локально перед push ## Где могу ошибаться - Полный `vitest run` по всему workspace не запускался в рамках этого heartbeat (только targeted-тесты для изменённых файлов) из-за бюджета времени — рекомендую отдельный CI-прогон перед мержем. - Изменения в git-delivery-gate.ts затрагивают gate логики done-статуса для issues — стоит last-look ревью на предмет false positive/negative в проде.
- Remove word boundaries (\b...\b) that break Cyrillic pattern matching
- Add 'PR created' pattern (PR without number)
- Fix Russian patterns: правка/обновка кода variants, мердж ветки
- Add 'прогнал тесты' weak signal pattern
- Add comprehensive regression test suite (27 test cases)

All regression tests passing. Verified Paperclip API health OK.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
(cherry picked from commit f139a39f58)
- Fix regex to properly handle ordinal suffixes (st/nd/rd/th) with optional comma and space before year
- Previously: (?:st|nd|rd|th)?,?\s+ (required comma before suffix)
- Now: (?:st|nd|rd|th)?(?:,\s+)? (optional comma with space)
- This allows parsing dates like 'Jun 7th, 2026 3:21 PM'

- Also fix isCodexTransientUpstreamError to check CODEX_USAGE_LIMIT_RE directly
- Previously it called extractCodexRetryNotBefore(input) which uses current time
- This caused issues with tests using past dates, as they'd return null
- Now checks pattern directly without time-dependent validation

Fixes PIX-12998

(cherry picked from commit bf28817f0b)
Добавлен лёгкий endpoint для получения pending одобрений текущего агента.

- Новый endpoint GET /api/agents/me/approvals-lite возвращает одобрения агента в упрощённом формате
- Требует аутентификации агента
- Фильтрует одобрения по ID агента (requestedByAgentId)
- Возвращает структуру { data: [], total: 0 }
- Добавлены unit тесты для проверки логики фильтрации и аутентификации
- Исправлено: добавлен paperclip:allow-git-push комментарий к error message в git-delivery-gate.ts

PIX-12948: Нужен лёгкий endpoint для получения pending одобрений агента для autonomy-refill и других системных операций.

- pnpm typecheck:  0 ошибок
- pnpm check:no-git-push:  проверка успешна
- Unit тесты для логики фильтрации и аутентификации: 
- Endpoint правильно проверяет agent authentication
- Правильно фильтрует одобрения по requestedByAgentId

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
(cherry picked from commit e6cec52f34)
- Add POST /api/issues/{id}/low-trust/promotions endpoint
- Route validates checkout ownership via assertAgentIssueMutationAllowed
- Creates work product artifact from quarantined output
- Includes activity logging and recovery revalidation
- Fixes regression: 2 tests now passing (peer rejection, cheap recovery block)

(cherry picked from commit 33dd0d6335)
Проблема: build падал с "Cannot find name 'node:fs'" когда компилировал
@paperclipai/shared пакет. Причина — отсутствие entry в types array.

Решение: добавить "types": ["node"] в compilerOptions shared/tsconfig.json
чтобы TypeScript правильно резолвил типы для node: imports.

Также добавлен регрессионный тест для проверки что @types/node
доступен и node: imports работают корректно.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
(cherry picked from commit bd63b88c54)
Добавлены комплексные smoke-тесты для проверки:
- Heartbeat execution flow
- Adapter management и model profiles
- Orphaned run detection (PIX-10721)
- Auth recovery после restart
- Workspace validation для git-sensitive адаптеров
- Process lifecycle management
- Session ID sanitization

Тесты выявляют и документируют ключевые weak areas:
- Orphaned runs без process_pid
- Process exit handling с empty output
- Workspace provision fallback logic
- Adapter session sanitization

Status: 15/15 tests passing

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
(cherry picked from commit bd8132d308)
- Раскрыли registerModuleMocks в top-level vi.doMock
- Добавлены: costService, environmentRuntimeService, recoveryService, issueRecoveryActionService
- Тесты падают 'No costService' - баг vitest v4.1.8

PIX-11433

(cherry picked from commit 7f70170484)
When a run reports new output activity (lastOutputAt is updated), automatically
clear the process_detached error code. This prevents runs with temporarily
detached processes from staying in error state indefinitely.

- Added check in output flush to clear DETACHED_PROCESS_ERROR_CODE
- Clears both error and errorCode fields when process shows activity
- Regression test verifies recovery mechanism is in place

Issue: Hermes agent run stuck in 'running' status with process_detached
error despite reporting recent output activity.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
(cherry picked from commit 05a592860c)
When the hermes adapter returns a response that consists entirely of an
extended-thinking block (┌─ Reasoning ─┐ … └─┘ with no trailing text),
stripModelReasoningText stripped everything and left an empty string.
buildHeartbeatRunIssueComment then got null for both summary and result,
so CEO heartbeat runs produced no operator summary despite durable issue
updates (PIX-13883, runs f6af4727 / af125366).

Fix: collect lines inside reasoning blocks as a fallback; when stripping
produces an empty result but reasoning content was captured, return the
reasoning content itself so the summary is never silently empty.

Regression tests added for the two failing shapes (closed box without
trailing text, unclosed box without a boundary line) and for the
end-to-end mergeHeartbeatRunResultJson path.

(cherry picked from commit d2f448ff9b)
Implement safe reconciliation for running runs when their target issue reaches
terminal status (done/cancelled) but the process is no longer alive.

Changes:
- Add reconcileProcesslessRunsTargetingTerminalIssues() to detect and cancel
  running runs targeting terminal issues that have no active process (PID dead)
- Integrate into heartbeatService.tickTimers() for automatic periodic detection
- Use POSIX kill(pid, 0) for reliable process liveness check
- Properly release execution locks and promote next queued runs
- Export function for testing

Fixes: live-run 886d86ef targeting done issue with missing PID 190091
Scope: Paperclip control-plane heartbeat reconciliation only

Test: Add heartbeat-processless-run-reconciliation.test.ts with 3 cases
- Detects and cancels processless run on terminal issue
- Preserves running run when issue is not terminal
- Skips run when process is still alive

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
(cherry picked from commit 0281687b85)
Implemented Redis-backed company search rate limiter to support
distributed rate limiting across multiple Paperclip instances.

Changes:
- Add Redis configuration (host/port/password) to config.ts
- Create redis-client.ts with ExecRedisClient using redis-cli INCR
- Graceful fallback to in-memory when Redis unavailable
- Update company-search-rate-limit to use async Redis-backed counter
- Add REDIS_* environment variables to .env.example
- Update routes/issues.ts to initialize limiter with config
- Update tests to work with async consume() method

Verification:
- Redis container (europatech-redis) verified working on localhost:6379
- INCR operations tested and working
- In-memory fallback confirmed for compatibility

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
(cherry picked from commit 5eb444dcc8)
- heartbeat.ts: reconcileProcesslessRunsTargetingTerminalIssues ссылался
  на несуществующую колонку heartbeatRuns.issueId; исправлено на join
  через issues.executionRunId = heartbeatRuns.id
- heartbeat.ts: некорректный generic-тип Parameters<typeof db.update<...>>
  заменён на устоявшийся в файле паттерн Partial<typeof heartbeatRuns.$inferInsert>
- routes/issues.ts: /issues/:id/low-trust/promotions не передавал
  обязательное поле status в createForIssue
- heartbeat-processless-run-reconciliation.test.ts: тест был недописан
  (db никогда не инициализировался) — переписан на embedded-postgres
  фикстуру по образцу costs-service.test.ts
- pix-11638-build-regression.test.ts: заменена runtime-проверка
  require.resolve("@types/node") (ошибочна для types-only пакета) на
  прямую проверку compilerOptions.types в packages/shared/tsconfig.json
- approvals-lite.test.ts: isAuthenticated возвращал строку вместо boolean
  из-за короткого замыкания && — обёрнуто в Boolean()
fix(git-delivery-gate): исправить два бага в regex-детекторах PIX-12937
Some checks failed
PR Quality Gates / PR Quality Gates (pull_request_target) Has been cancelled
Agents CI / Typecheck and Build (pull_request) Has been cancelled
9b2f9ade87
- STRONG_CODE_TASK_PATTERN не распознавал "PR created" (только pr#N) —
  добавлена альтернатива pr\s+created
- WEAK_CODE_TASK_PATTERN не распознавал "прогнали тесты" (множественное
  число) — тест заменён на тест(?:ы)?
- git-delivery-gate-cyrillic-regex.regression.test.ts содержал тестовые
  строки-фикстуры с "git push origin main", которые ловил pre-push хук
  check-no-git-push.mjs как ложное срабатывание — добавлены маркеры
  paperclip:allow-git-push согласно документированному opt-in механизму
merge: интегрировать master (PR #155-157) в merge/pix-12937-batch2
Some checks reported warnings
security/pr-scan 4 security flag(s) — see Actions log (critical)
PR Quality Gates / PR Quality Gates (pull_request_target) Successful in 4s
Agents CI / Typecheck and Build (pull_request) Successful in 5m47s
01e6d9184c
Разрешены конфликты между дублирующейся реализацией /agents/me/approvals-lite
из этой ветки (PIX-12937 batch2) и уже смерженной в master версией (PR #156,
PIX-12948): оставлена версия из master (более полная фильтрация по
linkedAgentId + pending статусу), дублирующий вариант из batch2 отброшен.
git-delivery-gate.ts и heartbeat.ts слились автоматически без конфликтов.
andrei merged commit 0d8ed19b71 into master 2026-07-04 08:39:05 +00:00
Sign in to join this conversation.
No reviewers
No labels
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
europa-tech-srl/europa-tech-agents!160
No description provided.