# task-3038 — update-system-spec.py 정기 실행 (9회차)

- **팀**: dev8 (라/Ra)
- **실행**: `python3 /home/jay/workspace/scripts/update-system-spec.py`
- **실행 시각**: 2026-08-27 18:15:41 ~ 18:15:45 KST
- **exit code**: `1` — **알려진 양성(benign)**, 데이터 손실 없음. Critical 7 아님.

## 1. 실행 결과

| 섹션 | 수집 | 변경감지 | 문서반영 |
|---|---|---|---|
| skills | OK | - | - |
| services | OK | ✅ | ✅ 18 → 17 |
| projects | OK | - | - |
| scripts | OK | - | - |
| task_stats | OK | ✅ | ✅ |
| cron | **FAIL** (`ANU_CHAT` 미설정) | ✅(거짓) | ❌ 미반영(정상) |

`cron` 의 "데이터 변경"은 **9회 연속 동일한 거짓 양성**이다. 수집 실패로 `new=None`
이 되어 `old != new` 가 성립할 뿐이고, 갱신 루프는 `if section not in new_state:
continue` 로 건너뛴다. **로그만 찍히고 문서는 그대로**다.

## 2. 검증 (실행 전후 대조)

방법: `cp` 스냅샷 → 실행 → 전문 `diff` + `AUTO:cron` 마커 포함 구간 md5 before↔after.

- `AUTO:cron` md5 **before = after = `af7090faa1da20f713b9f6e31ae7eb8c`** → 보존 확인
- cron 블록 `created_at` = `2026-04-16 11:16:10` (9회 연속 동결)
- 전문 diff = **16줄 / 2 hunk** (services 5줄 + task_stats 8줄)
- `services` 스펙 17 = 실측 17 (`systemctl --user list-units --state=running --type=service`) ✅
- task_stats 2279→2281 (완료 2214→2216, 평균 1:10:24→1:10:21) — 증가분 2건 중 1건은 **본 task 자신**의 타이머 start (자기참조. 외부 활동량으로 읽지 말 것)

## 3. ★ 이번 회차 신규 발견 — `cloudflared-whisper.service` 정지

`services` 델타가 **기존 플래핑 3종이 아니다.** `at-spi-dbus-bus`·`dbus`·`gpg-agent`
는 5회 연속 present 이고, 이번에 빠진 것은 `cloudflared-whisper.service` 단독이다.

**실측**
- `Active: inactive (dead) since 2026-08-27 14:35:05 KST` (실행 지속 1d 2h 27min)
- 종료 코드 `status=0/SUCCESS`
- 튜널 로그: `Initiating graceful shutdown due to signal terminated` @ 05:35:05Z(=14:35:05 KST)

**근인**: 외부에서 SIGTERM 수신 → graceful shutdown → exit 0.

**구조적 결함 (잠복)**: 유닛의 재시작 정책이 `Restart=on-failure` 다.
정상 종료(exit 0)에는 **발동하지 않는다.** 즉 SIGTERM 한 번이면 튜널은
수동 개입 전까지 **영구 정지**한다. 3시간 40분간 아무 알림도 없었다.

**SIGTERM 발신원은 미확정.** journal 에 `Stopping cloudflared-whisper.service`
라인이 **없다**(8/26 12:05 세션 재시작 때는 있었음) → systemd 가 건 정지가 아니다.
canonical `scripts/`·`dispatch/`·`tools/` 에서 cloudflared 를 죽이는 코드는 **0건**.
로그만으로는 특정 불가하여 추측하지 않는다.

**영향 범위 — 알려진 소비자에는 영향 없음**
- canonical 소비자 `scripts/youtube-transcribe.py:32` 는
  `WHISPER_SERVICE_URL = "http://localhost:8200/v1/transcribe"` — **localhost 직접 호출**,
  튜널 경유 아님
- `whisper-gpu.service` 는 **정상 가동 중**(`localhost:8200` HTTP 404 = 서버 살아있음,
  라우트만 미존재)
- 튜널은 `trycloudflare.com` **quick tunnel** 이라 재시작마다 URL 이 바뀐다 →
  URL 을 하드코딩한 코드가 존재할 수 없고, 실제로 repo 내 `trycloudflare` 참조는
  worktree 사본의 **주석뿐**(실참조 0건)

→ **외부 노출 경로만 소실.** 로컬 전사 파이프라인은 무영향. 자동 복구는 안 된다.

## 4. 백업 스케줄러 (별개 스케줄 EE825F5E)

기대 슬롯 격자 ↔ 백업 디렉터리 실재 대조:

```
08-26_00 OK   08-26_06 OK   08-26_12 MISS   08-26_18 OK
08-27_00 OK   08-27_06 OK   08-27_12 OK     08-27_18 OK
```

`08-26_12` 결번은 기존에 확인된 **모드B(레코드 자체 부재 = 미발화)** 1건 그대로이며
신규 결번 없음. 다만 연속 ok 회차를 세어 "고장 아님"으로 승격하지 않는다(직전 회차 교훈).

## 5. 판정

- 스크립트 정기 실행: **성공**. 문서·changelog 갱신 완료.
- Critical Escalation 7종: **해당 없음** (데이터 손실·보안·머지사고 없음).
- 회장님 알림: 스크립트 실패 아님 → 필수 아님. 단 §3 은 **보고 가치 있음**.

## 6. 미해소 / 위임 후보

1. **`cloudflared-whisper` 자동복구 부재** — `Restart=on-failure` → `Restart=always`
   전환 검토. 단 quick tunnel 은 재시작 시 URL 이 바뀌므로, 외부 접근이 실제로
   필요하다면 named tunnel 로 승격하는 편이 근본 해소. **현 시점 실피해 0건**이라
   긴급도는 낮음. (선행 질문: 이 튜널의 외부 소비자가 실재하는가?)
2. **`collect_cron()` ANU_CHAT 미주입** — 9회 연속. 해소는 (a) 크론에 ANU 소유
   `ANU_CHAT`/`ANU_KEY` 주입, 또는 (b) `detect_changes()` 가 수집 실패 섹션을
   변경으로 계산하지 않도록 수정. **팀 봇 키 대체 수집은 금지**(스코프 부분집합으로
   문서 퇴행).
3. **`collect_services()` returncode 미검사** — 세션버스 실패 시 `services` 블록
   21줄→2줄 소실 가능(재현 완료, 실발생 0회). 계류 중.

## 산출물
- `memory/specs/anu-system-spec.md` (services·task_stats 갱신)
- `memory/specs/anu-system-spec-changelog.md` (`[2026-08-27 18:15]` 항목 추가)
- `memory/reports/task-3038.md`
- `memory/events/task-3038.json`
