---
task_id: task-3030
scope: task
team: dev8
owner: 라(Ra)
type: cron-execution
status: success_with_known_benign_exit1
created_at: "2026-08-26 18:15 KST"
---

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

## S (상황)

`python3 /home/jay/workspace/scripts/update-system-spec.py` 6시간 주기 정기 실행.
직전 4회(task-3015 / 3020 / 3022 / 3027)에서 "exit code 1 + `[cron] 데이터 변경`"이
`ANU_CHAT` 미설정 수집 실패에 기인한 **거짓 양성**임이 이미 규명되어 있다.

## C (복잡성)

직전 회차(task-3027)가 남긴 두 개의 미결 관찰이 이번 회차의 판정 대상이었다.

1. **services 섹션이 되돌아갔다.** 3027 에서 17→15 로 줄었던(`at-spi-dbus-bus`·
   `dbus`·`gpg-agent` 삭제) 세 서비스가 이번엔 **전부 재등장**해 15→18 이 되었다.
   "실제 인프라 변경"인지 **세션 스코프 플래핑**인지 가려야 했다.
2. **spec 백업 12:00 결번**(별개 스케줄러 `backup-spec.sh`, ID `EE825F5E`)이
   영구 고장인지 1회성 미발화인지 미확정 상태였다.

## Q (질문)

- exit 1 이 이번에도 알려진 거짓 양성인가, 새로운 실패인가?
- `AUTO:cron` 블록이 이번에도 보존되었나?
- services 18개가 실측과 일치하나 — 진짜 변경인가 플래핑인가?
- 백업 스케줄러는 살아 있나?

## A (답변 / 실행 결과)

### 1. 실행 결과 — exit code 1, 알려진 거짓 양성 재현 (5회 연속)

```
  [FAIL] cron: ANU_CHAT 환경변수가 설정되지 않았습니다.
  [OK] skills / services / projects / scripts / task_stats
  변경 감지: ['cron', 'services', 'task_stats']
  업데이트 완료 / 변경 로그 기록 완료
  EXIT CODE: 1
```

수집 실패는 `cron` **단 한 섹션**. 나머지 5개 섹션 전부 `[OK]`.
문서·changelog 는 정상 기록(mtime `18:15:35`). **데이터 손실 0 → Critical 7 아님.**

### 2. `AUTO:cron` 블록 보존 — diff 0줄 확증

실행 전 `/tmp/spec-before-3030.md` 스냅샷 → 실행 후 START/END 마커 구간 대조:

```
before md5: af7090faa1da20f713b9f6e31ae7eb8c
after  md5: af7090faa1da20f713b9f6e31ae7eb8c   → diff 0줄
created_at: "2026-04-16 11:16:10"              → 5회 연속 동결
```

수집 실패 섹션은 `if section not in new_state: continue` 로 건너뛰므로
**로그만 찍히고 문서는 그대로**라는 기존 규명과 정확히 일치.

### 3. 전문 diff — 20줄, services + task_stats 뿐

```
540c540   실행 중: 15개 → 18개
543a544   + at-spi-dbus-bus.service
547a549   + dbus.service
549a552   + gpg-agent.service
1165-1168 총 작업 2270→2272 · 완료 2203→2209 · 97.0%→97.2% · 평균 1:10:11→1:10:32
```

cron JSON 라인은 diff 에 **1줄도 없다** → §2 와 교차 확증.

### 4. ★ services 변화의 정체 — 실제 변경 아닌 **세션 스코프 플래핑**

실측 대조:

```
systemctl --user list-units --state=running --type=service | wc -l  → 18
스펙 services 블록의 .service 개수                                  → 18   (일치)
```

수치는 정확하다. 다만 **성격**이 3027 의 판정과 다르다:

- `insuro-preview.service` — 3027 에서 추가된 뒤 **이번에도 살아있음** = 진짜 인프라 변경(지속)
- `at-spi-dbus-bus` · `dbus` · `gpg-agent` — 12:16 삭제 → 18:15 재등장 = **6시간 만에 왕복**

이 세 개는 데스크톱/로그인 세션에 딸린 user 유닛이라 세션 유무에 따라 뜨고 진다.
따라서 changelog 의 `[services] 추가/삭제` 3줄은 **인프라 변경 기록이 아니라 세션 상태의 잔상**이다.
`insuro-preview` 만이 신호였고, 나머지 셋은 노이즈다.

> **판정 규칙(신규):** services 델타는 개수 일치만으로 "실제 변경"이라 부르면 안 된다.
> 직전 회차와 **왕복(추가→삭제→추가)** 하는 유닛은 플래핑으로 분류할 것.

### 5. 백업 스케줄러 — 1회성 미발화로 확정, 현재 정상

```
2026-08-26_00  00:00:15   ✅
2026-08-26_06  06:00:17   ✅
2026-08-26_12  ────────   ❌ 결번 (3027 에서 발견)
2026-08-26_18  18:00:25   ✅ 복구
```

18:00 버킷이 `HH:00:1x~2x` 규칙대로 정상 생성됨 → **러너 생존 확인, 영구 고장 아님.**
12:00 은 단발 미발화로 남는다. (사후 임의 생성 금지 — 의미가 뒤집힌다.)
18:00 백업본은 내 18:15 실행 **이전** 상태를 담고 있어 롤백 지점으로 유효하다.

## 결론

| 항목 | 결과 |
|---|---|
| 스펙 문서 갱신 | ✅ 성공 (18:15:35) |
| changelog 기록 | ✅ 5개 항목 기록 |
| exit code 1 | 알려진 거짓 양성 (5회 연속 재현) — 조치 불요 |
| `AUTO:cron` 블록 | ✅ 보존 (md5 동일, diff 0줄) |
| services 18개 | ✅ 실측 일치 — 단 3건은 세션 플래핑 |
| 백업 스케줄러 | ✅ 18:00 정상 발화 (12:00 은 단발 결번) |
| 제이회장님 알림 | **불요** (실패 아님) |

## 미결 / 이월

1. **근본 해소 미착수** — `detect_changes()` 가 수집 실패 섹션을 변경으로 계산하지 않도록
   수정하거나 크론에 ANU 소유 `ANU_CHAT`/`ANU_KEY` 를 주입해야 한다.
   (팀 봇 키 대체 수집은 **금지** — key 스코프 부분집합으로 문서가 퇴행함.)
   현재 하루 4회 × 무한 반복으로 changelog 를 오염시키는 중.
2. **`collect_services` 무방비** (3027 ANU 검증에서 실증) — `systemctl` 출력 변이 주입 시
   스펙을 0개로 덮어쓴다. 이번 플래핑 관찰이 그 취약성을 재확인해준다.
3. 위 2건 모두 이 크론 작업의 범위 밖 → ANU 판단 사항으로 이월.
