Skip to content

fix(worker): piri progress 스캔의 느슨한 디렉터리 매칭이 임의 디렉터리를 진행 신호로 흡수 — 태스크 즉시 stale 오판 (Phase A r12 실증) #2011

Description

@jinon86

증상 (jinwon-int/fleet-skills#18 intake 게이트 Phase A, r12)

  • 태스크 생성 후 4분 30초 만에 exceeded_requeue_limit으로 dead-letter: "task exceeded stale threshold 2700000ms" (45분 문턱이 4.5분 만에 발화)
  • 워커(dungae)는 핸들러를 정상 실행 중이었고, heartbeat는 "cannot heartbeat task while status is queued" 409로 반복 거부(requeue 루프의 부산물)
  • 재현 2회: r12와 동일 조건 r11 이전 라운드(r7~r11) 전부 동일 실패 양상

근본 원인

packages/broker/src/workers/broker-worker-client.tsmatchingPiriSessionDirs() 매칭 술어:

if (entry.name !== sessionDir && !entry.name.includes(taskId) && !taskId.includes(entry.name)) continue;

세 번째 조건 taskId.includes(entry.name) 때문에, piri 워크 루트에 존재만 하면 되는 짧은 이름의 디렉터리가 실제 task id 부분 문자열이면 전부 매칭됩니다.

실제 사례: dungae의 /var/lib/a2a-runner/piri-tasks/s (한 글자 디렉터리, 2026-08-19 잔재). "s"를 포함하는 모든 task id와 매칭되어 그 안의 artifacts/piri-progress.jsonl mtime(2026-08-19T00:30:47.987Z)이 heartbeat의 lastProgressAt으로 브로커에 보고됐습니다.

연쇄:

  1. resolveTaskStalenessSignalMs()lastProgressAt을 최우선 정합 신호로 신뢰 (broker-status-predicates.ts:29 — "progress is authoritative")
  2. task 레코드의 lastProgressAt = 9일 전 → stale 스윕이 생성 즉시 45분 초과 판정
  3. requeue → queued↔running 진동 → BROKER_MAX_REQUEUE_ATTEMPTS=2 소진 → dead-letter

실증 (인과 확정)

  • s 디렉터리 격리(/root/a2a-quarantine/s.stray-20260829T0335KST) 후 동일 매니페스트·동일 워커로 재디스패치(r13) 즉시 성공 — heartbeat 정상, verdict approve, 리뷰 게이트 통과
  • r12 레코드의 lastProgressAt(2026-08-19T00:30:47.987Z)과 격리된 디렉터리 내 progress 파일 mtime이 밀리초까지 정확히 일치

제안 수정

  1. client (근본): matchingPiriSessionDirs()에서 taskId.includes(entry.name) 절 제거 또는 가드 추가 — (a) sanitize된 sessionDir와의 정확 일치 + taskId 포함(contains)만 허용, 또는 (b) 최소 길이(예: ≥ 16자) + a2a- 프리픽스 요구. 진행 파일은 세션 디렉터리 네이밍 규약(a2a-<worker>-<taskId>-analysis)으로 재구성 가능하므로 contains 방향(entry.name.includes(taskId))만 남겨도 커버 충분
  2. broker (방어 심층): heartbeat의 client 제공 lastProgressAttask.createdAt 이전 값이면 기각(또는 clamp). 기존 monotonic 가드(broker-task-checkpoint.ts:186)는 "이전 값보다만 새로우면" 통과시켜 과거 시점 자체는 막지 못함

운영 조치 이력 (2026-08-29 KST)

  • dungae s 격리 완료. 플릿 전수 점검: 다른 노드 단문 디렉터리 0건 (jingun k3canary2는 실 task id와 부분 일치 불가한 9자라 저위험 — 세션 디렉터리 규약으로의 개명 권고, soonwook piri-<epoch> 계열은 매칭 불가한 무해 잔재)

크로스링크

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions