# task-2705+1 — V3.6_TASK_MD_SHA_BOOTSTRAP_RECOVERY (★ 회장 verbatim 2026-05-28 · task-2705 VALID_HOLD 후속 · 1회성 bootstrap 예외)

- Level: **Lv.3 infrastructure** (★ control plane layer 0 · 모든 실행 계약의 기준점)
- type: **coding** (★ md/report 중심 금지 · py/sh/json/schema/test 중심)
- 분류: **task-2705 후속 bootstrap recovery** (★ task-2705 VALID_HOLD 인정 보존 · ACCEPT/DENY/무효화 0 · race contamination 0)
- 담당: **dev1-team 헤르메스 (Hermes)** (★ 회장 verbatim 유지 · bot key c38fb9955616e24d · 구현↔검증 주체 분리)
- chair_authorization_id (후보 · ★ 회장 최종 확정 대기): **`CHAIR-AUTH-TASK-2705PLUS1-V36-TASK-MD-SHA-BOOTSTRAP-260528`**
- 완료 목표: **`V36_TASK_MD_SHA_BOOTSTRAP_RECOVERY_ACTIVE_AND_VERIFIED`**
- 상태: **`TASK_2705PLUS1_DRAFT_PENDING_CHAIR_CONFIRMATION`** (★ 회장 verbatim · 초안 단계 · 발사 전 dispatch 금지 · "설계 확정" 단정 금지)

## ★ task-2705 lineage (★ 회장 verbatim 박제 보존)

- **task-2705 상태**: **VALID_HOLD** (★ 무효화 0 · ACCEPT/DENY 0)
- 근거 (회장 verbatim 확정 fact 7):
  1. ANU 기록 task md 14,827 bytes
  2. dispatch.py rewrite 이후 실제 task md 14,826 bytes
  3. 차이 = 1 byte
  4. dispatch.py L4518 에서 `task_desc = read_text(...).strip()` 경로 확인
  5. L3611-3636 에서 기존 task file 과 strip 된 task_desc 가 다르면 `write_text(task_desc)` 발동
  6. 봇은 rewrite 이후 post-sha 파일을 읽음
  7. ★ task-2705 의 `HOLD_FOR_CHAIR` 는 정합한 판단
- **lineage 산출물 보존**:
  - `memory/events/task-2705.task-md-sha-decision.json` (★ task-2705 봇의 HOLD decision marker · sha 0cc87f00…)
  - `memory/reports/task-2705.md` (★ task-2705 봇 보고서 · sha d3c1b10f…)
  - `memory/events/task-2705.fallback-cron-91665D06-260528.json` (★ ANU fallback marker)
  - `memory/events/task-2705.DUPLICATE_SPAWN_DETECTED-260528.json` (★ duplicate 감지)
  - `memory/events/task-2705.dispatched-20260528.json` (★ task-2704 dispatch_marker_writer 자동 생성)
- task-2705 race contamination: **없음** (★ 산출물 single actor · PID 646559 산출물 0)
- task-2705 폐기 0 · ★ 본 task-2705+1 의 입력 사실로 보존

## ★ task-2705+1 의 직접 책임 (★ task md sha contract bootstrap recovery)

본 task 는 task-2705 가 self-referential bootstrap 문제로 진입 불가했던 상태를 **1회성 bootstrap 예외 인가** 하에 cover 한다. 두 결함 라인 모두 fix:

1. **task md sha contract layer 0 구현** (★ task-2705 미완 + bootstrap 전략 명시 반영)
2. **dispatch_marker_writer.py 모듈 결함 2건 fix**:
   - chair_authorization_id 모듈 상수 하드코딩 제거
   - task_md_sha_before=null hardcode caller 결함 fix

## ★ Bootstrap 전략 10 (★ 회장 verbatim 박제)

1. **`dispatch_pre_sha`** 는 회장/ANU 승인 원본 기준으로 보존한다
2. **`dispatch_post_sha`** 를 **authoritative execution seed** 로 삼는다
3. **`executor_observed_sha`** 는 실제 봇 read 기준으로 검증한다
4. `dispatch_pre_sha != dispatch_post_sha` 여도, 차이가 **trailing whitespace strip / whitespace normalization** 이고 normalize 후 `content_verbatim_match=true` 이면 **ALLOW 가능**
5. `dispatch_post_sha == executor_observed_sha` 이면 실행 계약은 **유효** 로 본다
6. `dispatch_post_sha != executor_observed_sha` 이면 **HOLD**
7. **semantic/content 변경** 이면 **DENY**
8. 비교 불가 면 **`HOLD_LOCAL` 또는 `ESCALATE_CHAIR`** 로 분리
9. **ANU 가 임의 ALLOW 로 바꾸는 것은 금지**
10. 본 bootstrap 예외는 **task md sha contract 구현 전용 1회성 예외** 로 제한

## ★ 필수 포함 10 (★ 회장 verbatim 박제)

### 1. dispatch.py L4518 `.strip()` known fact

```python
task_desc = task_file_path.read_text(encoding="utf-8").strip()
```
- `.strip()` 가 ANU file 의 trailing whitespace (newline 포함) 제거
- ★ **본 case 의 1 byte 차이는 trailing whitespace strip 추정** (★ 확정 단정 금지 · "추정")
- normalize 함수가 `.strip()` 시뮬레이션 포함 → patch_type=`WHITESPACE_NORMALIZATION` 자동 분류

### 2. L3611-3636 rewrite path

```python
if source_task_file is not None and task_file.exists() and Path(source_task_file).resolve() == task_file.resolve():
    _existing_content = task_file.read_text(encoding="utf-8")
    if _existing_content is not None and _existing_content == task_desc:
        _skip_task_file_write = True
if not _skip_task_file_write:
    task_file.write_text(task_desc, encoding="utf-8")
```
- ★ ANU `--task-file memory/tasks/<task_id>.md` 전달 시 source==task_file 분기 진입
- 보강 task_desc 와 기존 file 비교 → 1 byte 차이로 불일치 → write 발동
- mtime 갱신 = dispatch.py write 시점

### 3. 1 byte trailing whitespace normalization case

- ★ **본 task-2705+1 의 첫 production validation case 가 곧 자기 자신** (★ task-2705 self-referential 의 재발 위험)
- 봇 contract 구현 시 본 1 byte case 를 `patch_type=WHITESPACE_NORMALIZATION` + `content_verbatim_match=true` + `continue_allowed=true` → **ALLOW 자동 분기** 처리해야 정합
- fixture 강제: `tests/harness/fixtures/v36_task_md_sha_replay_task_2705_1byte_strip.json`

### 4. `dispatch_post_sha` authoritative strategy

- 3 sha (pre/post/observed) 모두 측정 + marker 박제
- 봇 실행 허용 여부 = `post_sha == executor_observed_sha` 일치 우선
- pre/post 불일치 = normalize/content_verbatim_match 분기 (★ 회장 verbatim Bootstrap 전략 4·5·6·7·8)
- ★ ANU 임의 ALLOW 변경 금지 (★ 회장 verbatim 9)

### 5. `task_md_sha_before=null` fix

- 현재: `dispatch/__init__.py` L2992·L4029 caller 가 `None` 하드코딩 전달
- fix: caller 가 task md `dispatch_pre_sha` 측정 (★ ANU 측정 시점 또는 dispatch.py 진입 직후) + `dispatch_post_sha` 측정 (★ L3636 write 직후) 후 marker 에 전달
- 함수 signature 는 이미 `task_md_sha_before: Optional[str]` arg 받음 → caller 측 fix 만 필요

### 6. `chair_authorization_id` 하드코딩 fix

- 현재: `dispatch_marker_writer.py` L24 모듈 상수 `CHAIR_AUTHORIZATION_ID="CHAIR-AUTH-TASK-2704-V36-CONTROL-PLANE-P0-MVP-260528"` 박힘 + 함수 signature 에 arg 자체가 없음
- fix:
  - 모듈 상수 **제거**
  - `write_dispatch_marker` 함수 signature 에 `chair_authorization_id: Optional[str]` arg 추가
  - L151 `"chair_authorization_id": chair_authorization_id` 로 변경

### 7. dispatch_marker_writer.py 의 `CHAIR_AUTHORIZATION_ID` 상수 제거

- ★ #6 의 구체적 산출물 항목 박제 (★ 회장 verbatim)

### 8. caller 에서 `chair_authorization_id` 전달

- dispatch.py L2986·L4023 caller 위치에서 `chair_authorization_id` 인자 전달
- task별 dynamic 값 (★ task-2705+1 dispatch 시점에 본 task 의 chair_auth_id 전달)
- 회장 verbatim arg 추가 (★ #6 의 구체적 caller 항목)

### 9. caller 에서 `task_md_sha_before` 측정 후 전달

- caller 가 sha256 측정 함수 호출 (★ task_file.read_bytes() → sha256)
- 측정 시점 명세: dispatch.py 진입 직후 (`dispatch_pre_sha`) + L3636 write 직후 (`dispatch_post_sha`)
- safe-fail 강제 (★ task-2704 패턴 보존)

### 10. task-2705 VALID_HOLD lineage

- ★ 본 task-2705+1 은 task-2705 의 **후속** 이지 폐기 아님
- task-2705 의 모든 산출물 (HOLD marker · 보고서 · DUPLICATE_SPAWN_DETECTED) **보존**
- 본 task md 가 그 lineage 를 직접 인용 + bootstrap 전략 적용 결과 = task-2705 의 HOLD 가 ALLOW 로 변환되는 retrospective replay fixture 강제

## ★ 절대 금지 (★ 회장 verbatim 박제 + 추가)

- **기존 task-2705 를 ACCEPT 처리 금지** (★ VALID_HOLD 유지)
- **기존 task-2705 에 `.done` 생성 금지**
- **`finish-task.sh` 실행 금지** (★ task-2705 + 본 task 모두)
- **finish-task.sh / session-watchdog.sh / settings.json 수정 금지** (★ task-2703/2704/2705 패턴 보존)
- **finish-task profile contract 구현 금지** (★ #6 SEPARATE_VERIFICATION_REQUIRED)
- **actor attribution contract 구현 금지** (★ #8 P1 backlog)
- **Goal-to-Done / PHASE_AUTO / Core-Work 이원화 금지**
- **merge executor activation 금지**
- **PR 생성 / branch push / merge 금지**
- **task-2706 자동 발의 금지** (★ 회장 verbatim · 다음 작업 방향 ANU 단정 0)
- **재발사 (★ 기존 task-2705 재발사) 금지**
- **코드 수정 금지** (★ 본 초안 단계 · 발사 후 봇만 수정 허용)
- **ANU 본체 직접 구현 금지**
- **ANU 본체 단독 closeout 판정 금지**
- **"Hermes 직접 코딩 0" 단정 금지**
- **"설계 확정" 단정 금지** (★ 본 초안 = draft · 회장 확인 후 dispatch)
- **ANU 자가검증만으로 closeout PASS 처리 금지**
- **본 bootstrap 예외를 1회성 외 재사용 금지** (★ 회장 verbatim 10)

## allowed_resources

```yaml
allowed_resources:
  expected_files_new:
    - "scripts/harness/v36/task_md_sha_contract.py (layer 0 · 3 sha 측정 + normalize + ALLOW/HOLD/DENY 판정)"
    - "scripts/harness/v36/task_md_sha_marker_writer.py (★ 12 필드 marker write · safe-fail)"
    - "scripts/harness/v36/task_md_sha_normalize.py (★ .strip 시뮬레이션 + DISPATCH_META_SIDECAR + RETRY_HEADER + WHITESPACE_NORMALIZATION)"
    - "tests/harness/test_v36_task_md_sha_contract.py (★ 8 fixture + task-2705 1 byte strip replay)"
    - "tests/harness/test_v36_task_md_sha_normalize.py"
    - "tests/harness/fixtures/v36_task_md_sha_fixture_1_allow_no_patch.json"
    - "tests/harness/fixtures/v36_task_md_sha_fixture_2_allow_sidecar.json"
    - "tests/harness/fixtures/v36_task_md_sha_fixture_3_allow_retry_header.json"
    - "tests/harness/fixtures/v36_task_md_sha_fixture_4_allow_whitespace.json"
    - "tests/harness/fixtures/v36_task_md_sha_fixture_5_hold_unverifiable.json"
    - "tests/harness/fixtures/v36_task_md_sha_fixture_6_deny_semantic_change.json"
    - "tests/harness/fixtures/v36_task_md_sha_fixture_7_deny_forbidden_change.json"
    - "tests/harness/fixtures/v36_task_md_sha_fixture_8_e2e_integration.json"
    - "tests/harness/fixtures/v36_task_md_sha_replay_task_2705_1byte_strip.json (★ 본 task 의 핵심 replay fixture · trailing whitespace strip)"
    - "tests/harness/fixtures/v36_task_md_sha_replay_task_2703.json"
    - "memory/events/task-2705+1.* (보고/마커)"
    - "memory/reports/task-2705+1.md"
  allowed_existing_file_edits:
    - "dispatch/__init__.py (★ 최소 결선 · L2992/L4029 caller 에 chair_authorization_id + task_md_sha_before 전달 + L4518/L3636 sha 측정 hook · 기존 동작 변경 0 · safe-fail 강제)"
    - "scripts/harness/v36/dispatch_marker_writer.py (★ CHAIR_AUTHORIZATION_ID 모듈 상수 제거 + 함수 signature 에 chair_authorization_id arg 추가 + L151 변경 · 기존 marker schema 보존)"
  forbidden_files:
    - "scripts/finish-task.sh"
    - "scripts/session-watchdog.sh"
    - "/home/jay/.claude/settings.json"
    - "/home/jay/workspace/.claude/settings.json"
    - "utils/merge_queue_executor.py / utils/real_merge_hooks.py (★ activation 0)"
    - "anu_v3/goal_loop_planner.py / phase_auto*.py / core*.py / work*.py"
    - "scripts/harness/v36/finish_task_profile*.py"
    - "scripts/harness/v36/actor_attribution*.py"
    - "memory/tasks/task-2705.md (★ 기존 task-2705 task md 수정 금지)"
    - "memory/events/task-2705.task-md-sha-decision.json (★ task-2705 HOLD 마커 수정 금지)"
    - "memory/reports/task-2705.md (★ task-2705 봇 보고서 수정 금지)"
    - "PR #158 / #159 / #160 / task-2700·2700+1·2703·2704 branch"
    - "workspace_root 외부"
  commands:
    - "구현: 신규 py/json/test · dispatch.py + dispatch_marker_writer.py 최소 결선 (safe-fail 강제)"
    - "검증: pytest fixture/mock · production load evidence · marker schema validation · task-2705 replay PASS"
    - "★ real GitHub write 0 · merge 0 · branch push 0 · PR 생성 0 · finish-task.sh 수정 0"
    - "★ task-timers 위조 0 · manual .done 0 · G4 marker 삭제 0"
  merge_policy: "task_md_sha_bootstrap_recovery_local_verification_no_remote_writes_no_finish_task_change"
  ttl_hours: 18
```

## ★ Definition of Done (10 항목)

1. **3 sha 측정 결선**: `dispatch_pre_sha` + `dispatch_post_sha` + `executor_observed_sha` 모두 측정 + marker 박제 evidence
2. **5 patch type enum 분류 fixture coverage** (★ `WHITESPACE_NORMALIZATION` 별도 fixture 포함)
3. **content_verbatim_match 3 enum 분기 fixture PASS**
4. **continue_allowed 3 enum 결정 매트릭스 PASS**
5. **decision marker schema validation PASS**
6. **★ task-2705 1 byte trailing strip replay fixture PASS**: pre=93bc5c33… (14,827B) · post=3e3b15e9… (14,826B) · `WHITESPACE_NORMALIZATION` · `content_verbatim_match=true` · **ALLOW** 자동 분기 PASS
7. **dispatch_marker_writer.py CHAIR_AUTHORIZATION_ID 상수 제거 + chair_authorization_id arg 추가 + caller fix evidence**
8. **task_md_sha_before caller fix evidence**: dispatch.py L2992·L4029 에서 None 아닌 실제 sha 측정값 전달 trace
9. **regression 0 fail**: task-2703 246/246 + task-2704 회귀 + 본 task 신규 모두 PASS
10. **forbidden write 0 · settings.json 미수정 · finish-task.sh 미수정 confirmed · task-2705 lineage 산출물 미수정 confirmed**

## ★ regression scenarios (★ 9 fixture · task-2705 lineage 강제)

- fixture-1 ALLOW NO_PATCH
- fixture-2 ALLOW DISPATCH_META_SIDECAR
- fixture-3 ALLOW RETRY_HEADER_PREPEND
- fixture-4 ALLOW WHITESPACE_NORMALIZATION (★ task-2705 case 기반 + 추가 변형)
- fixture-5 HOLD unverifiable
- fixture-6 DENY semantic change
- fixture-7 DENY FORBIDDEN_SEMANTIC_CHANGE (chair_authorization_id 자동 수정 시뮬레이션)
- fixture-8 e2e 통합
- **★ fixture-9 task-2705 replay**: pre=93bc5c33… (14,827B) · post=3e3b15e9… (14,826B) · WHITESPACE_NORMALIZATION · ALLOW

## ★ rollback/safe-fail 기준 (★ 회장 verbatim hold 분류 보존)

- safe-fail 1: sha 측정 실패 → dispatch 본동작 차단 0
- safe-fail 2: marker write 실패 → 동상
- safe-fail 3: normalize 예외 시 UNKNOWN+unverifiable+continue_allowed=hold marker 생성
  - ★ 모든 hold 가 즉시 회장 보고 아님
  - `ESCALATE_CHAIR` = semantic 변경 가능성 / forbidden patch 의심 / executor 원문 계약 신뢰 불가
  - `HOLD_LOCAL` = 단순 측정 실패
  - `RETRYABLE_HOLD` = 일시적 read error
  - ANU 임의 ALLOW 변경 금지
- rollback: 본 contract 결선이 dispatch 동작 회귀 발생 시 dispatch/__init__.py 의 sha 측정 호출만 try/except silent skip
- 회귀 검증: task-2703 246/246 + task-2704 회귀 모두 유지

## ★ 발사 방식 (★ task-2703/2704 패턴 보존 · 회장 verbatim 진행 규칙 12)

- 1차 = **dispatch.py 단일 발사** · 직접 cron 동시 0
- fallback = 5 신호 교차 SPAWN_UNKNOWN/NOT_STARTED 확정 시 1회 한정 · 12 필드 marker 강제
- ★ ANU 자동 fallback safety-net cron 등록 금지
- ★ 1차+fallback 중복 spawn 감지 시 `DUPLICATE_SPAWN_DETECTED` 마커 즉시 + ANU callback + 임의 kill/stop 0

## ★ 보고 표현 강제 (★ 회장 verbatim 박제 보존)

> "Hermes는 주요 feature 구현자가 아니라 통합·조정자, Vulcan은 주요 구현, Maat는 검증. Hermes 소규모 직접 패치 가능성은 self-attestation만으로 완전 배제 불가."

## ★ 구현↔검증 분리 (★ task-2703/2704 패턴 보존)

- **Hermes (Opus)**: 설계·통합·조정 (★ 직접 코딩 0 self-attestation 한계 표현 강제)
- **Vulcan (Sonnet)**: 구현 (sha contract 코어 + normalize + marker writer + dispatch.py 결선 + dispatch_marker_writer fix)
- **Maat (Sonnet · 횡단)**: 독립 검증 (DoD 10 PASS/FAIL · executor 와 분리)
- ★ ANU 본체 단독 closeout 판정 금지

## ★ 종결

성공: **`V36_TASK_MD_SHA_BOOTSTRAP_RECOVERY_ACTIVE_AND_VERIFIED`**

→ task-2705 의 self-referential bootstrap HOLD 가 본 task-2705+1 의 산출물로 retrospective ALLOW 분류 가능. task-2705 VALID_HOLD 보존 + bootstrap 전략 적용 + 두 marker writer 결함 fix + dispatch_pre/post/observed 3 sha 체계 정합 + 본 bootstrap 예외 1회성 종료.

★ 회장 verbatim 2026-05-28 task-2705+1 bootstrap recovery. task-2705 VALID_HOLD 보존 · 폐기 0 · 무효화 0 · race 0. bootstrap 전략 10 + 필수 포함 10 + 금지 17. 1회성 예외 · 향후 재사용 금지. 본 초안 = draft · 회장 확인 후 dispatch.

끝