@uzysjung/agent-harness 26.106.0 → 26.107.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uzysjung/agent-harness",
3
- "version": "26.106.0",
3
+ "version": "26.107.0",
4
4
  "description": "Curate vetted AI-coding skills & plugins by your tech stack — install only what you need, across Claude Code, Codex, OpenCode & Antigravity",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -1,12 +1,13 @@
1
1
  #!/bin/bash
2
2
  # spec-drift-check.sh
3
- # SPEC.md/todo.md/PRD.md의 drift를 검출한다.
4
- # Verify 또는 Ship 단계에서 호출 가능.
3
+ # SPEC/TODO 문서의 drift를 검출한다. Verify 또는 Ship 단계에서 호출 가능.
5
4
  #
6
5
  # 검출 항목:
7
- # 1. SPEC.md Verification Checklist에 unchecked 항목 존재
8
- # 2. todo.md unchecked 항목 존재
9
- # 3. PRD.md Status가 In Progress인데 모든 Phase가 Complete인 경우
6
+ # 1. SPEC 문서에 unchecked 항목 존재 (docs/SPEC.md SPEC.md 존재 파일)
7
+ # 2. TODO 문서에 unchecked 항목 존재 (docs/todo.md docs/TODO.md → todo.md → TODO.md
8
+ # tasks/todo.md 존재 파일 first-match 라 대소문자 무시 FS 에서도 이중 카운트 없음)
9
+ # 3. SPEC Status가 "Define"인데 build/verify gate가 완료된 경우 (gate-status.json 존재 시)
10
+ # 4. Ship 단계에서는 모든 unchecked가 차단
10
11
  #
11
12
  # Exit codes:
12
13
  # 0: drift 없음
@@ -26,40 +27,74 @@ count_unchecked() {
26
27
  grep -c "^- \[ \]\|^ - \[ \]" "$file" 2>/dev/null | tail -1 | tr -d ' \n'
27
28
  }
28
29
 
29
- # 1. SPEC.md unchecked 검사
30
- if [ -f "$DOCS_DIR/SPEC.md" ]; then
31
- UNCHECKED=$(count_unchecked "$DOCS_DIR/SPEC.md")
30
+ # 후보 목록 중 첫 존재 파일 (없으면 빈 문자열). v26.107.0 docs/ 고정이던 탐지를
31
+ # 실제 워크플로 산출 레이아웃(root SPEC.md·tasks/todo.md 등)까지 확장 (SOD 리뷰 I-3).
32
+ first_existing() {
33
+ local f
34
+ for f in "$@"; do
35
+ if [ -f "$f" ]; then
36
+ echo "$f"
37
+ return 0
38
+ fi
39
+ done
40
+ echo ""
41
+ }
42
+
43
+ SPEC_FILE=$(first_existing "$DOCS_DIR/SPEC.md" "$PROJECT_DIR/SPEC.md")
44
+ TODO_FILE=$(first_existing "$DOCS_DIR/todo.md" "$DOCS_DIR/TODO.md" "$PROJECT_DIR/todo.md" \
45
+ "$PROJECT_DIR/TODO.md" "$PROJECT_DIR/tasks/todo.md")
46
+
47
+ # 1. SPEC unchecked 검사
48
+ if [ -n "$SPEC_FILE" ]; then
49
+ UNCHECKED=$(count_unchecked "$SPEC_FILE")
32
50
  UNCHECKED=${UNCHECKED:-0}
33
51
  if [ "$UNCHECKED" -gt 0 ] 2>/dev/null; then
34
- echo "DRIFT: SPEC.md에 unchecked 항목 ${UNCHECKED}건" >&2
52
+ echo "DRIFT: ${SPEC_FILE#"$PROJECT_DIR"/}에 unchecked 항목 ${UNCHECKED}건" >&2
35
53
  DRIFT=$((DRIFT + 1))
36
54
  fi
37
55
  fi
38
56
 
39
- # 2. todo.md unchecked 검사
40
- if [ -f "$DOCS_DIR/todo.md" ]; then
41
- UNCHECKED=$(count_unchecked "$DOCS_DIR/todo.md")
57
+ # 2. TODO unchecked 검사
58
+ if [ -n "$TODO_FILE" ]; then
59
+ UNCHECKED=$(count_unchecked "$TODO_FILE")
42
60
  UNCHECKED=${UNCHECKED:-0}
43
61
  if [ "$UNCHECKED" -gt 0 ] 2>/dev/null; then
44
- echo "DRIFT: todo.md에 unchecked 항목 ${UNCHECKED}건" >&2
62
+ echo "DRIFT: ${TODO_FILE#"$PROJECT_DIR"/}에 unchecked 항목 ${UNCHECKED}건" >&2
45
63
  DRIFT=$((DRIFT + 1))
46
64
  fi
47
65
  fi
48
66
 
49
- # 3. Ship 단계에서는 모든 unchecked가 차단
67
+ # 3. SPEC Status 일관성 gate-status.json과 대조 (6-gate 워크플로 사용 프로젝트만; 파일 없으면 skip)
68
+ GATE_FILE="$PROJECT_DIR/.claude/gate-status.json"
69
+ if [ -f "$GATE_FILE" ] && [ -n "$SPEC_FILE" ] && command -v jq &> /dev/null; then
70
+ BUILD_DONE=$(jq -r '.build.completed // false' "$GATE_FILE")
71
+ VERIFY_DONE=$(jq -r '.verify.completed // false' "$GATE_FILE")
72
+
73
+ # SPEC Status가 "Define"인지 확인 (frontmatter 형식만, 본문 파이프라인 설명 제외)
74
+ if grep -qE "^> \*\*Status\*\*:.*Define" "$SPEC_FILE"; then
75
+ if [ "$BUILD_DONE" = "true" ] || [ "$VERIFY_DONE" = "true" ]; then
76
+ echo "DRIFT: SPEC Status='Define'인데 Build/Verify gate가 완료됨" >&2
77
+ DRIFT=$((DRIFT + 1))
78
+ # Ship 게이트에서는 차단 (Build 이후에도 SPEC이 Define이면 안 됨)
79
+ [ "$1" = "ship" ] && BLOCK=1
80
+ fi
81
+ fi
82
+ fi
83
+
84
+ # 4. Ship 단계에서는 모든 unchecked가 차단
50
85
  if [ "$1" = "ship" ] && [ "$DRIFT" -gt 0 ]; then
51
86
  BLOCK=1
52
87
  fi
53
88
 
54
89
  # Summary
55
90
  if [ "$DRIFT" -eq 0 ]; then
56
- echo "OK: SPEC/todo/PRD 동기화 상태 정상"
91
+ echo "OK: SPEC/TODO 동기화 상태 정상"
57
92
  exit 0
58
93
  fi
59
94
 
60
95
  if [ "$BLOCK" -eq 1 ]; then
61
96
  echo "" >&2
62
- echo "BLOCKED (ship gate): SPEC drift 발견 — SPEC.md, todo.md, PRD.md 동기화 후 재시도" >&2
97
+ echo "BLOCKED (ship gate): SPEC/TODO drift 발견 — 동기화 후 재시도" >&2
63
98
  exit 2
64
99
  fi
65
100
 
@@ -0,0 +1,62 @@
1
+ # Document Governance
2
+
3
+ 문서 작성 + 작업 완료 시 추적 동기화 규칙. 프로젝트 문서가 "거짓 상태"가 되는 것을 막는 SSOT 규약 —
4
+ 실서비스 운영에서 검증된 관행의 일반화.
5
+
6
+ ## SSOT 위계 (한 사실은 한 곳)
7
+
8
+ | 문서 | 역할 | 갱신 시점 |
9
+ |------|------|----------|
10
+ | `NORTH_STAR.md` | 왜·어디로 (비전 · 북극성 지표 · Non-Goals · 의사결정 휴리스틱) | 방향 전환 시만 |
11
+ | `SPEC.md` (+ `specs/`) | 무엇 (제품/기능 스펙 — 모듈이 커지면 파일 분리) | 기능 정의/변경 |
12
+ | `PRD.md` | 문제 · 솔루션 · 요구사항 | 제품 방향 변경 |
13
+ | `TODO.md` (또는 `tasks/todo.md`) | 다음 할 일 · 진행/완료 추적 | 작업 시작/완료 |
14
+ | `README.md` | 진입점 · 현재 상태 (shipped/stack/배포) | 현재 상태 변동 |
15
+ | `docs/decisions/` | 아키텍처/의존성/데이터모델/보안 결정 (ADR) | change-management.md 분류 따름 |
16
+
17
+ - 파일 위치는 프로젝트 레이아웃을 따른다 (루트 또는 `docs/`) — **역할·위계·동기화 의무는 불변**.
18
+ - **위계 = 충돌 시 상위 우선.** NORTH_STAR 와 SPEC 이 모순되면 NORTH_STAR 가 이긴다.
19
+ - **같은 사실을 두 곳에 쓰지 않는다.** 한 곳(SSOT)에 두고 나머지는 링크로 가리킨다. 중복 서술 = drift 의 씨앗.
20
+
21
+ ## 무엇을 언제 쓰나
22
+
23
+ - 신규 기능 → **먼저 SPEC 등재, 그 다음 구현** (spec-first). 대화에서 "추가하자/넣자" = 우선 문서 작업이지 구현 착수가 아니다.
24
+ - 아키텍처 / 외부 의존성 / 데이터 모델 / 보안 / breaking API 결정 → **ADR** (`docs/decisions/`, 템플릿은 change-management.md).
25
+ - 진행/완료 추적 → TODO. 현재 상태 변동 → README.
26
+
27
+ ## 작업 완료 처리 (merge = 코드 + 추적 동기화) — 핵심 의무
28
+
29
+ PR 머지로 작업이 끝난 게 아니다. **머지 직후 같은 작업 단위로**:
30
+
31
+ 1. TODO 해당 항목 → `[x] (✅ #PR번호)`.
32
+ 2. AC / Phase / Non-Goals / DO NOT CHANGE 에 영향 시 → SPEC Change Log.
33
+ 3. 현재 상태(shipped / 배포) 변동 시 → README §현재 상태.
34
+
35
+ 빠지면 추적 SSOT 가 거짓 상태가 되고, **다음 세션이 완료분을 backlog 로 오인해 중복 작업하거나
36
+ 미완분을 완료로 오인해 건너뛴다.** 금지.
37
+
38
+ ## 현행 vs archive
39
+
40
+ - **현행 SSOT 만 루트/`docs/` 에**: 위 위계 문서 + `specs/` + `decisions/`.
41
+ - **히스토리는 `docs/archive/`** 로 격리 (옛 버전, 폐기 sub-spec, 완료된 리서치/audit 산출물) —
42
+ 지도 파일(`archive/README.md`) 하나로 찾을 수 있게 한다. 현행 문서에 히스토리가 쌓이면
43
+ "현재가 무엇인지"를 읽는 비용이 히스토리에 비례해 커진다.
44
+ - 변경 이력이 길어진 문서는 이력만 archive 로 빼고 본문에는 최근분만 남긴다.
45
+
46
+ ## 작성 원칙
47
+
48
+ - **why 중심** — what 은 코드/diff 가 보여준다.
49
+ - SPEC 이 800줄을 넘으면 기능별 분리 (`spec-scaling` 스킬 참조).
50
+ - **추정/임의 단정 금지** — "직관상 별로", "일반적으로 필요", "내 경험상"은 출처 없는 일반화.
51
+ 측정/스펙 참조/재현 증거로 입증한다.
52
+
53
+ ## 검증 게이트
54
+
55
+ `.claude/hooks/spec-drift-check.sh` 가 SPEC/TODO 의 unchecked 잔존·Status 불일치를 검출한다 —
56
+ verify 단계에서 경고(exit 1), **ship 단계(`spec-drift-check.sh ship`)에서는 차단(exit 2)**.
57
+ 탐지 경로: SPEC 은 `docs/SPEC.md` → `SPEC.md`(루트) 중 첫 존재 파일, TODO 는 `docs/todo.md` →
58
+ `docs/TODO.md` → `todo.md` → `TODO.md` → `tasks/todo.md` 중 첫 존재 파일 — **이 목록 밖 레이아웃은
59
+ 게이트가 못 본다** (그 경우 본 규약은 프로즈로만 작동한다고 알라). dev 트랙 설치 시
60
+ ship-checklist.md 의 "SPEC/PRD 정합성" 게이트가 이 스크립트를 호출한다. 프로즈 규약(본 문서)과
61
+ 결정론 게이트(훅)는 짝이다 — 규약만으로 안 지켜지는 것이 확인되면 게이트를 넓혀라
62
+ (dev 트랙 설치 시 recurrence-prevention 스킬의 에스컬레이션 사다리 참조).