#!/bin/bash # PD 지시 로그 활성 테이블의 산출물 경로 실존 자동 감사 # 신설 근거: 2026-04-17 pm-auditor 감사 Critical C1 + 클라이언트팀 B-1 설계 # 관련 규칙: C13 PD 지시 트래킹, C31-1-D 세션 시작 맥락 복원, P26 PM 업무 정확도 보장 REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null) [ -z "$REPO_ROOT" ] && exit 0 LOG_DIR="$REPO_ROOT/공유/PD_지시_트래킹" [ ! -d "$LOG_DIR" ] && exit 0 MISSING_COUNT=0 CHECKED_COUNT=0 REPORT="" # 활성 지시 섹션 파싱: "## 활성 지시"와 "## 완료 아카이브" 사이 for LOG_FILE in "$LOG_DIR"/*_PD_지시_로그.md; do [ ! -f "$LOG_FILE" ] && continue TEAM=$(basename "$LOG_FILE" _PD_지시_로그.md) # awk로 활성 섹션만 추출 ACTIVE_SECTION=$(awk '/^## 활성 지시/,/^## 완료 아카이브/' "$LOG_FILE" 2>/dev/null) # 테이블 행(| 로 시작)에서 5번째 컬럼(산출물 경로) 추출 # 헤더·구분선(-|-|)은 제외 PATHS=$(echo "$ACTIVE_SECTION" | awk -F'|' ' /^\| *[0-9]/ && NF>=6 { # 5번째 컬럼에서 백틱 감싸진 경로 추출 col=$6 while (match(col, /`[^`]+`/)) { p = substr(col, RSTART+1, RLENGTH-2) # D:/ 로 시작하는 외부 경로는 스킵 if (p !~ /^[A-Z]:/ && p !~ /^http/) { print p } col = substr(col, RSTART+RLENGTH) } }' | sort -u) [ -z "$PATHS" ] && continue while IFS= read -r P; do [ -z "$P" ] && continue CHECKED_COUNT=$((CHECKED_COUNT + 1)) FULL_PATH="$REPO_ROOT/$P" # 디렉토리 경로(/로 끝) or 파일 경로 모두 -e로 확인 if [ ! -e "$FULL_PATH" ]; then MISSING_COUNT=$((MISSING_COUNT + 1)) REPORT="${REPORT}[${TEAM}] ${P}\n" fi done <<< "$PATHS" done if [ "$MISSING_COUNT" -gt 0 ]; then echo "" echo "🚨 [PD 지시 로그 경로 감사] 부재 산출물 ${MISSING_COUNT}/${CHECKED_COUNT}건 감지:" echo -e "$REPORT" | head -20 echo "" echo "→ PD 지시 로그 비고란에 '경로 정정 또는 흡수/소실 판정' 갱신 필요" echo "→ dev-auditor·plan-auditor 모드 C 호출 권고" exit 1 else if [ "$CHECKED_COUNT" -gt 0 ]; then echo "✅ [PD 지시 로그 경로 감사] ${CHECKED_COUNT}건 전수 실존 확인" fi exit 0 fi