# task-2706 보고서 — P1-B finish-task profile contract 외부 layer 구현

**task_id**: task-2706
**team**: dev1-team
**executor**: 헤르메스 (lead_integrator + Hermes 직접 통합) · 불칸 (implementer · sonnet)
**chair_authorization_id**: CHAIR-AUTH-TASK-2706-V36-FINISH-TASK-PROFILE-LAYER-P1B-260529
**level**: 5 · **priority**: P1-B
**시작**: 2026-05-29 10:36:34 (dispatch fire_time)
**완료**: 2026-05-29 (작업 완료)

---

## S — Situation

`scripts/finish-task.sh` L431-451 의 scope-guard 단계가 **모든 후속 sub-task 에서 false positive 발생** 위험 HIGH 인 상태로 운영 중이었음.

- workspace 가 1046 files dirty 누적 상태 → `git diff main..HEAD` 가 task 시작 시점(lock_sha) 이 아닌 main 과 비교 → prior task lineage 변경 모두 포함.
- 최근 case (task-2705+3): scope-guard FAIL 25 violations 발생 → 모두 prior task lineage 잔여 dirty 가 main..HEAD diff 에 누적 분류된 결과.
- 결과: finish-task.sh L451 `exit 1` 즉시 종료 → .done / .done.escalated 미생성 + task-timer running 영구 누적.

## C — Complication

회장 verbatim 제약:
- `scripts/finish-task.sh` 직접 수정 금지 (NO TOUCH)
- `dispatch/__init__.py` 수정 금지 (NO TOUCH)
- `settings.json` / `scripts/session-watchdog.sh` / `scripts/task-scope-guard.sh` 모두 NO TOUCH
- GitHub write 0 (PR / push / merge 모두 금지)
- task md draft 회장 결재 전 dispatch 금지 → dispatch fire 시점이 회장 결재 완료 신호

기존 file edit 0 강제 + 신규 모듈 추가만 허용. P1-C actor attribution 은 본 task scope 외 (schema 만 정의).

## Q — Question

어떻게 finish-task.sh 0 touch 를 유지하면서 task_mode 별 PASS/WARN/FAIL/ESCALATE 판단을 제공하고, 향후 scope-guard 결과 분류를 정합화할 수 있는가?

## A — Answer (구현 결과)

**외부 4-모듈 layer + 4-test + 9-fixture 구현**으로 finish-task.sh 외부에서 task_mode 분류·8-gate 평가·4-등급 판정을 수행하는 read-only 진단 layer 를 구축. finish-task.sh 는 본 layer 의 결과를 활성/비활성 자유롭게 선택 가능(활성 0 시 기존 동작 100% 유지).

### A.1 생성된 파일 (절대 경로 + 라인수)

신규 모듈 (4):
- `/home/jay/workspace/scripts/harness/v36/finish_task_profile_schema.py` (186 lines) — §11 JSON schema 정의 + validation
- `/home/jay/workspace/scripts/harness/v36/finish_task_profile_classifier.py` (338 lines) — 6 task_mode 자동 분류 + 우선순위
- `/home/jay/workspace/scripts/harness/v36/finish_task_profile_judge.py` (622 lines) — 8-gate 평가 + 4-등급 + worst-case wins
- `/home/jay/workspace/scripts/harness/v36/finish_task_profile_preflight.py` (377 lines) — finish-task 진입 전 preflight helper

신규 테스트 (4):
- `/home/jay/workspace/tests/harness/test_v36_finish_task_profile_classifier.py` (311 lines, 31 cases)
- `/home/jay/workspace/tests/harness/test_v36_finish_task_profile_judge.py` (419 lines, 45 cases)
- `/home/jay/workspace/tests/harness/test_v36_finish_task_profile_preflight.py` (254 lines, 23 cases)
- `/home/jay/workspace/tests/harness/test_v36_finish_task_profile_regression.py` (277 lines, 24 cases)

신규 fixtures (9):
- `tests/harness/fixtures/v36_task_mode_{code,system_hook,local_runtime,read_only,callback_only,closeout_marker_only}.json` (6개)
- `tests/harness/fixtures/v36_task_{2703,2704,2705plus3}_replay.json` (3개 replay)

기존 file edit: **0** (task md §6 expected_files.edits_existing == [] 정합 강제).
총 신규 라인: 3,104 lines (17 files).

### A.2 핵심 함수 시그니처

- `validate_profile(record: Any) -> tuple[bool, list[str]]` — §11 schema 검증, error list 반환
- `classify_task_mode(task_md_text: str, task_md_path: Optional[str] = None) -> dict` — 6 task_mode 자동 분류 + confidence
- `evaluate_gates(task_mode: str, gate_inputs: dict) -> dict` — 8 gate 평가, gate_key → result dict
- `compute_overall(gates_result: dict) -> tuple[str, str]` — worst-case wins (ESCALATE > FAIL > WARN > PASS)
- `run_preflight(task_md_path, task_id, lock_sha_hint, ...) -> dict` — 완전 §11 profile 반환

### A.3 자동 분류 우선순위 (§9 정합)
`code > system_hook > local_runtime > closeout_marker_only > callback_only > read_only > UNKNOWN`

### A.4 4-등급 (§11 정합)
- PASS / WARN / FAIL / ESCALATE
- overall = max(severity) (worst-case wins) — N/A 게이트 제외
- safe-fail: 분류/평가 실패 시 항상 `UNKNOWN + ESCALATE` (회장 verbatim "모르면 UNKNOWN")

---

## 모델 사용 기록

- **헤르메스(팀장)**: Opus 4.7 (1M ctx) — 설계/분배/통합/리뷰만 수행. 잔여 pyright 진단 4건 surgical edit 만 직접 수정 (G7 del-args, inline `# type: ignore`, unused `reason` → `_`).
- **불칸(백엔드)**: Sonnet 4.6 — 4 모듈 + 4 tests + 9 fixtures 전체 구현 + 1차 pyright 진단 정리.
- haiku 사용 0건 (코드 복잡도 MEDIUM, 192-cell 매트릭스 + safe-fail 다중 분기 → sonnet 필수).
- 이리스(프론트)·아테나(UX)·아르고스(테스터) 본 task 활성화 0 (백엔드 단일 작업).

## 머지 판단

- **머지 필요**: No (worktree 미생성 — system task · project_id 없음 · main branch 직접 작업)
- **브랜치**: task/task-2703-v36-harness-dev1 (v36 harness lineage 통합 브랜치 · 회장 verbatim "PR 금지 / branch push 금지 / merge 금지" 정합으로 push 0)
- **워크트리 경로**: 해당없음
- **머지 의견**: PR 금지 정합 → local commit 만 박제 (commit hash 아래 §git 박제 참조). 본 layer 활성화 0 시 기존 동작 100% 유지 → 회장 결재 시 lookout layer 활성화 검토 가능.

---

## L1 스모크테스트 결과

★ 본 task = local_runtime (신규 모듈 추가) · 서버/외부 API 없음. L1 검증 = **실제 모듈 import + 분류·평가·schema validate round-trip**.

- **서버 재시작**: 해당없음 (모듈 layer · 서비스 0)
- **API 응답 확인**: 해당없음 (호출 인터페이스 없음 — finish-task.sh 가 본 layer 활성화 0)
- **스크린샷**: 해당없음 (UI 없음)
- **모듈 import + round-trip 검증**:
  ```
  [L1.1] imports OK
  [L1.2] classify: system_hook / HIGH       (★ 실제 sample 분류 성공)
  [L1.3] gate count: 8 / G3: PASS           (★ 8 gate 평가 round-trip OK)
  [L1.4] overall: WARN / worst_grade=WARN   (★ G7=WARN (P1-C 미구현) 흡수)
  [L1.5] schema valid: True / errors: 0     (★ §11 schema 100% 정합)
  [L1] PASS: import + classify + evaluate + compute + schema-validate round-trip
  ```
- **pytest tests/harness/ -q**: **408 passed in 2.84s** (★ 285 baseline + 123 new · 회귀 0)

L1 통과: 모듈 import + classifier + judge + compute_overall + validate_profile end-to-end round-trip 정합.

---

## Regression Replay 3 case 결과 (§13 정합)

| task | expected task_mode | actual | expected G3 | actual | expected G4 | actual | expected overall | actual |
|------|---|---|---|---|---|---|---|---|
| task-2703 | system_hook | system_hook ✅ | PASS | PASS ✅ | - | - | PASS/WARN | WARN ✅ (G7 흡수) |
| task-2704 | code | code ✅ | PASS | PASS ✅ | WARN (INHERITED_DIRTY) | WARN ✅ | WARN | WARN ✅ |
| task-2705+3 | code | code ✅ | ESCALATE | ESCALATE ✅ | FAIL (EXTERNAL_DIRTY) | FAIL ✅ | ESCALATE | ESCALATE ✅ |

★ task-2703 overall = WARN: §13.1 허용 범위(PASS/WARN). G7 actor_attribution 이 항상 WARN ("P1_C_NOT_YET_IMPLEMENTED") 이므로 다른 게이트가 모두 PASS 여도 overall=WARN. §18 정합 (G7 schema-only · enforcement 0).

---

## §15 acceptance criteria 통과 결과

### §15.1 functional
1. ✅ classifier 가 6 task_mode 정확 분류 (mode fixture 6/6 + 31 case PASS)
2. ✅ judge 가 192-cell sampling **45 case** PASS (요구 30+ 초과)
3. ✅ preflight safe-fail 정합 (23 case PASS · 예외 0 던지기)
4. ✅ schema validation 100% (§11 schema 정합)
5. ✅ task-2703 / task-2704 / task-2705+3 replay 3/3 expected 정합

### §15.2 non-regression
1. ✅ pytest tests/harness/ -q = **408 passed** (★ 285 baseline + 123 new · 회귀 0)
2. ✅ finish-task.sh / dispatch/__init__.py / session-watchdog.sh / settings.json 변경 0 (§16 sha256 박제 아래 참조)
3. ✅ task-2705 lineage 산출물 sha 변경 0 (allowed_resources/forbidden_paths 강제)
4. ✅ task-2703 / 2704 / 2705+1~+4 lineage 모두 보존 (git log lineage 보존)

### §15.3 doctrine
1. ✅ Hermes 직접 패치 caveat 박제 (잔여 pyright 4건 surgical edit → P1-C §4 정합 박제)
2. ✅ ALLOWED 대체 표현 사용 (FORBIDDEN 표현 0건 · 본 보고서 verbatim 검증)
3. ✅ verifier 분리 강제: dev1 헤르메스 = implementer/lead. **dev2 오딘 verifier 별도 task-2706+1 발의 권고** (본 task 내 verifier phase 미실행 · 회장 결재 영역)
4. ✅ ANU callback envelope ≤3,900 bytes 정합 (envelope-only)

### §15.4 회장 verbatim 박제
1. ✅ finish-task.sh L431-451 read-only 인용 박제 (task md §2)
2. ✅ dirty workspace 1046 files fact 박제 (task md §3)
3. ✅ task-2705+3 scope-guard 25 violations case 박제 (task md §4)
4. ✅ task-2569 RC-1/RC-2 미적용 박제 + 본 task 가 task-2569 RC-1 대안 박제 (task md §2 + §22)

---

## §16 finish-task.sh NO-TOUCH proof

```
5efb7140205c0ab7958a7a77522e50d4103b8d7f7667711b115d8a46f0b80452  scripts/finish-task.sh       ← BEFORE = AFTER (byte-identical)
2586179226e1ff4dd5f8f3fd9ded1b998013709ccff7e29c0787c38718165aaf  dispatch/__init__.py         ← BEFORE = AFTER (byte-identical)
a1b90bb13ed092a8281f06a348ba019dcb64a97112bf399f149b1fc7d1f41227  scripts/session-watchdog.sh  ← BEFORE = AFTER (byte-identical)
```

★ 본 task 진행 전후 sha256 100% 일치. git diff 검증 = EMPTY. expected_files.edits_existing == [] 정합 강제.

## §17 no GitHub write proof

- gh CLI 호출: **0건** (본 보고 verbatim)
- git push: **0건** (회장 verbatim "branch push 금지" 정합)
- PR 생성: **0건** (회장 verbatim "PR 생성 금지" 정합)
- merge: **0건** (회장 verbatim "merge 금지" + merge_policy=manual)
- 모든 commit local only (아래 §git 박제 참조)

---

## §18 P1-C scope 외 확인

- ✅ 본 task = P1-B 만 구현 (task_mode 6 + 8 gates + 4 grades)
- ✅ P1-C actor attribution contract = 구현 **0**
- ✅ P1-C L1~L5 evidence_level 자동 박제 = 구현 **0**
- ✅ P1-C ATTR-001~005 enforcer = 구현 **0**
- ✅ G7 actor_attribution = schema 만 정의 + 실 enforcement 0 (항상 `WARN + P1_C_NOT_YET_IMPLEMENTED` 반환 · P1-C 별도 task 영역)

---

## 발견 이슈 및 해결

### Issue 1: pyright 진단 1차 cleanup 후 잔여 4건
- **발견**: G7 `_task_mode/_inputs` underscore prefix 후에도 pyright 가 미사용 경고. inline import 2건 `# type: ignore` 누락. `VALID_GRADES` import 미사용. `reason` 변수 3건 미사용.
- **해결 (헤르메스 surgical edit)**: 
  - G7 함수 내부 `del task_mode, inputs` 처리 (interface uniformity 유지)
  - inline import 라인에 `# type: ignore[import-not-found]` 추가
  - `VALID_GRADES` import 제거
  - `reason` → `_` (3건)
- **결과**: pytest 408 PASS 유지 + sha256 변화 0 검증.

### Issue 2: pyright extraPaths 환경에서도 reportMissingImports 발생
- **발견**: pyrightconfig.json 의 extraPaths 에 `/home/jay/workspace` 포함되어도 일부 inline/lazy import 가 reportMissingImports 트리거.
- **분석**: 기존 v36 모듈 (`test_v36_harness_jsonl.py`) 도 동일 패턴 → `# type: ignore[import-not-found]` 으로 일관 처리. 본 task 도 같은 방식 채택.
- **결정**: 패턴 통일 (runtime import 정상 + pyright 정적 분석 한정 ignore). 회귀 0.

---

## git 박제 (local commit only)

```
c140fa63 [task-2706] 헤르메스: pyright 잔여 진단 정리 (G7 del-args, inline type-ignore, unused reason)
61b72263 [task-2706] 불칸: pyright 진단 정리 (unused imports + type ignore for test resolution)
3dcf928e [task-2706] 불칸: P1-B finish-task profile contract 외부 layer 구현 (4 modules + 4 tests + 9 fixtures)
```

★ branch=task/task-2703-v36-harness-dev1 (v36 harness lineage 통합 브랜치 · push 0)

---

## ANU caveat (정직)

1. **verifier 분리**: 본 task 는 implementer (헤르메스+불칸) 만 수행. **§20.2 dev2 오딘 verifier 단계는 미실행** — 회장 결재 후 별도 task-2706+1 발의 권고.
2. **G7 P1-C 정합**: G7 actor_attribution 은 항상 `WARN + P1_C_NOT_YET_IMPLEMENTED` 반환. 본 layer 가 활성화 시점에 P1-C 미구현 상태면 모든 task 의 overall 이 최소 WARN 으로 분류됨 → 회장 결재 영역 명시.
3. **lock_sha 활용**: 본 task 는 task md timestamp + dispatched marker 의 `task_md_sha_before` 를 lock_sha 후보로 사용. task-2569 RC-1 의 lock_sha 박제 마커 자체는 dispatch.py 영역 (NO TOUCH) → preflight 가 best-effort fallback 만 수행.
4. **활성화 routing 미실시**: 본 layer 는 read-only/observable 만 구현. finish-task.sh 가 본 layer 결과를 실제 분기에 사용하려면 별도 task 결재 필요 (★ NO TOUCH 정합 강제).

---

## §20 verifier 분리 강제 (참조)

- 구현 단계 (본 task-2706): dev1 헤르메스 (lead_integrator + implementer · sonnet 분배)
- 검증 단계: dev2 오딘 (Maat verifier · 별도 task-2706+1 발의 권고 · 본 task 종료 후 회장 결재 영역)

## 비고

- chair_authorization_id: CHAIR-AUTH-TASK-2706-V36-FINISH-TASK-PROFILE-LAYER-P1B-260529
- 본 task = P1-B finish-task profile contract 외부 layer 1차 구현 박제
- 후속: 회장 결재 후 (1) verifier task-2706+1 발의 (2) P1-C actor attribution 별도 task (3) finish-task.sh 활성 routing 별도 task

---

**박제 끝. finish-task.sh 0 touch · dispatch.py 0 touch · GitHub write 0 · 회귀 0.**

## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회

