Imported from cano721/ai-harness (
skills/harness-init/SKILL.md). Install upstream withnpx skills add cano721/ai-harness --skill harness-init. Copyright stays with the author.
/harness-init — 프로젝트 AI 하네스 셋업 / 변경 / 동기화
현재 프로젝트(cwd)를 분석해 .ai-harness 하네스 구조를 스캐폴딩한다. 이후 /metrics로 관찰, /harvest로 개선하는 사이클의 시작점. 기존 하네스가 있으면 설정 변경 또는 생성물 동기화 모드로 동작한다.
인자: $ARGUMENTS — 아래 인터뷰 답을 미리 줄 수도 있음 (예: standard, tdd, codex, guard). 기존 프로젝트에서는 --sync(동기화 계획), --sync --apply(안전한 생성물 적용), --reconfigure(수준 인터뷰)를 쓴다. 인자가 없으면 현재 설정을 보여 주고 동기화 / 설정 변경 / 둘 다 중 선택하게 한다.
경로 표기: 아래 $ROOT = 이 SKILL.md가 있는 디렉터리의 두 단계 상위(플러그인 루트).
0. 모드 판정
- cwd에
.ai-harness/workspace.json있음 → 기존 workspace (아래 7-6으로) - cwd가 git repo가 아님 → 먼저
$ROOT/scripts/workspace-scan.sh scan --root .을 돌린다.candidate:true(하위에 독립 git 저장소 2개 이상)면 workspace 모드 (아래 7번으로).candidate:false면 사용자에게git init여부 확인 후 단일 프로젝트 흐름 .ai-harness/와AGENTS.md둘 다 없음 → 신규 셋업 (1번부터 진행)- 하나라도 있음 → 기존 하네스 모드 (아래 6번으로) — AGENTS.md만 있는 프로젝트도 기존 하네스로 취급, 절대 덮어쓰지 않는다
1. 프로젝트 분석 (질문보다 먼저 — 질문에 실측 컨텍스트를 담기 위해)
빌드 파일로 감지: 언어/프레임워크(build.gradle*, pom.xml, package.json, pyproject.toml, go.mod 등), 테스트 프레임워크·기존 테스트 규모(테스트 파일 수, 커버리지 게이트 유무), 빌드/실행 명령, git 컨벤션(최근 커밋 메시지·브랜치명 패턴 git log --oneline -30, git branch -a), 패키지/모듈 구조(주요 디렉토리와 의존 방향).
프론트엔드 스택 감지: package.json의 dependencies에 react·vue·svelte·@angular/core 등이 있으면 프론트엔드 프로젝트다. 이때 프론트 판단 Skill(아래 stack 게이트)의 생성 후보가 된다 — 백엔드 전용 저장소에는 만들지 않는다. FSD(Feature-Sliced Design) 여부도 함께 본다: src/ 아래 shared·entities·features·pages 레이어 디렉터리가 있거나 steiger.config.*가 있으면 FSD 사용으로 판단하고, 애매하면 §2에서 사용자에게 묻는다.
분석 결과는 문서 초안의 실측 근거가 된다 — 추측으로 채우지 않는다. 규모가 크면 탐색 서브에이전트(Explore 등)에 위임.
2. 수준 인터뷰 (AskUserQuestion — 엄격도는 사용자가 정한다)
하네스 엄격도는 프로젝트 성격에 따라 크게 다르다 (예: 프로덕션 백엔드는 TDD 강제 + 커버리지 게이트가 맞지만, 사이드 프로젝트에 그 수준은 과함). 기본값을 가정하지 말고 물어본다. 단, 1단계 실측을 질문 설명에 반영한다 (예: "현재 테스트 파일 0개" / "jacoco 게이트 이미 있음").
- 하네스 규모:
minimal(AGENTS.md+docs만) /standard(+워크플로·페르소나). Codex Skill 진입점은 아래 도구 통합에서 Codex를 선택할 때 추가한다.full은 규모가 아니라 아래 편집 가드 옵션의 이전 명칭이므로 새로 선택하지 않는다. - 테스트 정책:
TDD 강제(Red→Green→Refactor, test-engineer가 RED 전담) /테스트 필수(순서 무관, 구현 후 작성 허용) /권장만/없음(testing.md·test-engineer 생성 안 함)- 실측과 모순되면 지적: 기존 테스트가 0개인데 TDD 강제를 고르면 "기존 코드엔 characterization부터 필요" 경고
- git 통제 수준:
PR 필수(에이전트는 PR까지만, 병합은 사람) /직접 커밋 허용 - 도구 통합:
Codex/Claude/둘 다/통합 파일 없음. standard의 Codex Skill은Codex또는둘 다일 때만.agents/skills/에 생성한다. Claude용.claude/와CLAUDE.md는Claude또는둘 다일 때만 생성한다. - 편집 가드: 켜기 / 끄기. 가드는 규모와 독립적인 선택 옵션이며, 소스 수정 전에 관련 하네스 문서를 읽었는지 확인한다. transcript를 읽을 수 없으면 fail-open한다.
- 프론트 판단 Skill (§1에서 프론트엔드 스택을 감지했을 때만 묻는다):
생성/생성 안 함. 생성하면frontend-fundamentals·declarative-code·frontend-testing·no-unnecessary-effects를 프로젝트 로컬 Skill로 만든다(모두 읽기 전용 판단 지침). FSD Skill(feature-sliced-design)은 별도 하위 선택이며 §1에서 FSD를 감지했거나 사용자가 FSD를 쓴다고 답할 때만 추가한다 — FSD를 안 쓰는 프로젝트에 방법론 전체를 심으면 오도한다. 프론트엔드가 아니면 이 항목 자체를 건너뛴다.
답에 따라 생성물 조정: 워크플로 본문의 TDD 절차 유무, test-engineer 페르소나 유무, 선택한 도구의 어댑터와 agent별 모델 설정, guard hook 유무, AGENTS.md의 Git 룰 문구, 프론트 판단 Skill 생성 여부(및 FSD 포함 여부). 프론트 Skill을 생성하면 manifest의 stacks에 frontend를(FSD까지면 fsd도) 기록해 이후 동기화가 이 stack 게이트로 대상을 거른다. 모델은 사용자 인터뷰로 묻지 않고 아래 역할 기본값을 사용한다.
3. 생성 구조 (인터뷰 답 기준으로 가감)
AGENTS.md # 진입점 (아래 구성)
.ai-harness/
harness.json # 수준·안정적 project_id 매니페스트 (아래 참조) — 수준 변경 모드·/harvest가 읽음
docs/
code-conventions.md # 실측된 네이밍·구조·스타일 규칙
architecture.md # 모듈 구조, 기술 스택, 빌드/배포 (실측)
testing.md # 테스트 실행법, 프레임워크, 작성 규칙 (테스트 정책 '없음'이면 생략)
domain.md # 도메인 인덱스 (초기엔 표 틀만 — 도메인 문서는 필요해질 때 domain/{name}.md로 추가)
frontend.md # 프론트 판단 Skill을 생성할 때만. 디자인 시스템·테마 토큰명, 선언 사다리, FSD 여부 등 프로젝트 고유 사실 (실측). 프론트 Skill이 런타임에 읽는 프로젝트 컨텍스트
workflows/ # standard
implement-feature.md # 기능 개발 절차 (작은 검증 단위·완료 증거 원칙을 프로젝트 정책에 맞춰 구체화)
feature-delivery-graph.json # implement-feature의 프로젝트 로컬 노드·전이 계약
fix-bug.md # 버그 수정 절차 (재현·원인·회귀 검증 기준)
bug-fix-graph.json # fix-bug의 프로젝트 로컬 노드·전이 계약
review.md # 변경 검토·finding 종료 절차
review-graph.json # review의 프로젝트 로컬 노드·전이 계약
understand-change.md # 플러그인 `/understand-change`가 읽는 프로젝트별 설명 정책 (선택, 사람 소유)
agents/ # standard
explorer.md # 탐색 전담 (read-only)
developer.md # 구현 전담 (write scope: 소스+빌드 설정)
test-engineer.md # 테스트 전담 (write scope: 테스트 디렉토리만. 테스트 정책 '없음'이면 생략)
reviewer.md # 리뷰 전담 (read-only)
docs-updater.md # docs 영향 분석·갱신 전담 (Mode A read-only / Mode B write scope: .ai-harness/docs/)
hooks/
direct-edit-guard.sh # 편집 가드를 켰을 때만
.agents/
skills/ # Codex 또는 둘 다를 선택한 standard
implement-feature/
SKILL.md # .ai-harness 워크플로·그래프를 읽는 프로젝트 로컬 진입점
fix-bug/
SKILL.md # .ai-harness 워크플로·그래프를 읽는 프로젝트 로컬 진입점
review/
SKILL.md # .ai-harness 워크플로·그래프를 읽는 프로젝트 로컬 진입점
frontend-fundamentals/ # stack:frontend일 때만. 아래 4종은 templates/에서 복사한 자립 지침
SKILL.md
references/ # 통째로 함께 복사
declarative-code/
SKILL.md
frontend-testing/
SKILL.md
no-unnecessary-effects/
SKILL.md
feature-sliced-design/ # stack:fsd일 때만 (FSD opt-in)
SKILL.md
references/
.codex/
agents/ # Codex 또는 둘 다를 선택한 standard
explorer.toml # model·model_reasoning_effort가 지정된 read-only agent
test-engineer.toml
developer.toml
reviewer.toml
docs-updater.toml
CLAUDE.md # Claude 또는 둘 다를 선택했을 때만; 내용: "@AGENTS.md"
.claude/
agents/ # explorer/developer/test-engineer/reviewer/docs-updater 위임본. 각 파일 frontmatter에 §4 표의 `model` 필수
commands/ # Claude 슬래시 커맨드 진입점
skills/ # Claude 또는 둘 다 + stack:frontend일 때만. .agents/skills와 동일 프론트 판단 Skill 사본
workflows/ # Claude Dynamic Workflow 스크립트 (진입점이 scriptPath로 호출)
settings.json # 감지된 빌드/테스트 명령 allowlist (+ guard 시 PreToolUse hook)
4. 작성 원칙
- AGENTS.md 구성: Preflight(작업 시작 절차) / Hard constraints / Direct edit guard 룰(선택 시) / 워크플로·페르소나 표 / docs 목록 / Quick Commands(감지된 명령) / Git 컨벤션(실측 + 인터뷰 답)
- Hard constraints는 틀만 만들고 비워둔다 — "실측으로 검증된 룰만 추가. 추측 금지" 주석 한 줄. 이 섹션은
/harvest가 시간을 들여 채우는 영역 - docs는 실측 내용만. 확인 못 한 건 쓰지 말고 "코드를 source of truth로 확인" 문구로 대체
- 페르소나 write scope는 좁게 (test-engineer는 테스트 디렉토리만 등)
- settings.json allowlist는 read-only·빌드·테스트 명령만. deny에 force push
- direct-edit-guard.sh는 소스 경로 수정 전 code-conventions.md(테스트면 testing.md 추가) Read 여부를 transcript에서 grep — 미Read 시 exit 2 + 안내. transcript 접근 불가 시 fail-open(exit 0)
- 차단 메시지 첫 줄은 반드시
[Direct edit guard]접두어로 시작한다 (대괄호 포함).scripts/extract-claude.jq·scripts/extract-codex.sh가 이 접두어로만guard_block신호를 집계하기 때문이다. 접두어가 없으면 실제 차단이 계측에서 조용히 사라져/metrics·/harvest가 "차단 0건"으로 오판한다. 반대로 AGENTS.md 본문의Direct edit guard섹션 제목처럼 대괄호 없는 문구는 Read 출력에 섞여도 집계되지 않아야 하므로, 안내 본문에 대괄호 형태를 중복해 쓰지 않는다. 집계는 Claude에서는is_errortool_result, Codex에서는 출력 줄 시작의 접두어만 세므로, 훅은 stderr + exit 2로 차단하고 접두어를 첫 줄 첫 글자에 둔다. Claude Code는 훅 stderr를PreToolUse:<툴> hook error: [<훅 경로>]:로 감싸 tool_result에 넣으므로, 추출기는 줄 시작의 그 래퍼까지만 허용한다 — 훅이 접두어 앞에 자기 문구를 더 붙이면 집계에서 빠진다. /implement-feature는 플러그인 전역 Skill이 아니라standard초기화에서 생성하는 프로젝트 로컬 기능 개발 진입점이다.templates/implement-feature/를 기반으로 Codex는.agents/skills/implement-feature/SKILL.md, Claude는.claude/commands/implement-feature.md를 생성한다. 템플릿의 그래프는.ai-harness/workflows/feature-delivery-graph.json에도 복사하고, 두 진입점은 이 프로젝트 로컬 파일과.ai-harness/workflows/implement-feature.md, 필요한 docs를 먼저 읽어 프로젝트별 정책을 우선하도록 한다..ai-harness/는 프로젝트 특화 규칙의 단일 출처다.templates/implement-feature/references/feature-delivery-graph.json은 생성 원본이며, 프로젝트에 복사된.ai-harness/workflows/feature-delivery-graph.json이 Codex·Claude 공통 노드/전이 계약의 단일 출처다. Codex는 생성된 프로젝트 Skill과.codex/agents/위임으로 이를 해석한다. Claude를 선택했을 때는claude --version을 확인하고 2.1.154 이상에서만 프로젝트의.claude/workflows/implement-feature.js를 승인 후 구현·리뷰 루프에 선택적으로 사용한다고 안내한다. Dynamic Workflow가 없거나 실행 중 사용자 판단이 필요하면 생성된 프로젝트 command의 현재 세션 흐름으로 폴백한다.- 템플릿에서 생성할
implement-feature.md는 프로젝트 정책에 맞춰 구체화한다: 먼저 구현 범위·비범위·검증 케이스·예상 변경 영역·검증 명령을Implementation Brief로 사용자에게 보이고 명시 승인을 받을 때까지 파일을 수정하지 않는 계획 게이트를 둔다. 현재 대화에 같은 범위의 승인된 Brief가 있으면 재승인은 요구하지 않는다. 승인 뒤 요구사항을 관찰 가능한 검증 케이스와 1~3개 케이스의 delivery slice로 나눈다. 테스트 정책이 TDD일 때만 Red 실패 확인 → 최소 Green → 테스트를 바꾸지 않는 Refactor를 요구하고, 그 외 정책은 프로젝트가 정한 테스트 순서·필수 여부와 가능한 빌드/lint/type 검증을 따른다. 완료 전에는 blocking finding이 0개가 될 때까지 리뷰 → 원인별 수정 → targeted/전체 검증 → 재리뷰를 반복하며, 같은 원인이 두 번의 집중 수정 뒤에도 남으면 사용자 판단으로 올린다. 역할 분리는 선택한 도구와 작업 위험이 뒷받침할 때만 사용하며, 역할 도구가 없다는 이유로 단일 세션 작업을 중단하지 않는다. /fix-bug도 플러그인 전역 Skill이 아니라standard초기화에서 생성하는 프로젝트 로컬 버그 수정 진입점이다.templates/fix-bug/를 기반으로 Codex는.agents/skills/fix-bug/SKILL.md, Claude는.claude/commands/fix-bug.md를 생성한다. 템플릿의 그래프는.ai-harness/workflows/bug-fix-graph.json에도 복사한다. 승인 전에는 관찰·재현·원인 가설만 허용하고, 재현 불가이며 안전한 관측 계획도 없으면 수정하지 않고 사용자에게 필요한 환경·로그·기대 동작을 요청한다.- 템플릿에서 생성할
fix-bug.md는 관찰된/기대 동작, 영향, 재현 증거, 원인 가설과 반증 가능성, 회귀 검증, 최소 변경 범위를 담은Bug Fix Brief를 먼저 제시하고 명시 승인을 받을 때까지 파일을 수정하지 않는 게이트를 둔다. 승인 뒤 프로젝트 테스트 정책에 따라 회귀 테스트 또는 동등한 검증 증거를 만들고, targeted/전체 검증과 리뷰 → 원인별 수정 → 재검토를 수행한다. 같은 원인이 두 번의 집중 수정 뒤에도 남거나 제품·환경 판단이 필요하면 사용자에게 넘긴다. /review도standard초기화에서 생성하는 프로젝트 로컬 진입점이다.templates/review/를 기반으로 Codex는.agents/skills/review/SKILL.md, Claude는.claude/commands/review.md를 생성하고 graph를.ai-harness/workflows/review-graph.json에 복사한다. 초기 검토는 read-only이며, blocking finding이 있으면 대상 workflow로 수리한 뒤 필수 검증과 재검토를 거치기 전에는 완료하지 않는다./understand-change는 위 셋과 달리 플러그인 전역 Skill(skills/understand-change/)이며 프로젝트에 진입점을 생성하지 않는다. 코드를 수정하지 않는 설명 전용 흐름이라 테스트·Git 정책 같은 프로젝트 계약을 담지 않고, 프로젝트별 조정은 런타임에.ai-harness/workflows/understand-change.md를 읽어 해결한다. 따라서 관리 생성물·동기화 대상이 아니다. 초기화에서는 그understand-change.md만 사람 소유 보호 파일로 만들어 프로젝트 문서·검증 명령·공유 위치와 small / standard / deep 설명 깊이 기준을 연결한다(없어도 스킬은 내장 기본값으로 동작한다). 설명은 변경 전 배경, 직관, 실행 흐름, 위험, 직접 검증을 포함하며, standard·deep에서는 이해 확인 문제를 추가한다. deep 변경에서만 상태를 조작하거나 단계별 실행을 관찰하는 micro-world의 최소 형태를 제안하며, 사용자의 별도 승인 없이는 구현하지 않는다.- 프론트 판단 Skill(
frontend-fundamentals·declarative-code·frontend-testing·no-unnecessary-effects, FSD면feature-sliced-design추가)은implement-feature부류와 달리 워크플로 어댑터가 아니라templates/<name>/의 자립 지침을 프로젝트로 복사한 것이다. 코드를 직접 바꾸지 않는 읽기 전용 판단이지만 프론트엔드 전용이라 플러그인 전역 Skill로 두지 않는다 — 백엔드 저장소에 노출되면 노이즈이므로, 프론트엔드로 감지된 프로젝트에서만 stack 게이트(frontend/fsd)로 생성한다. Codex는.agents/skills/<name>/, Claude는.claude/skills/<name>/에 SKILL.md와references/를 통째로 복사한다. 각 Skill이 참조하는 프로젝트 고유 사실(디자인 시스템·테마 토큰명, 선언 사다리, FSD 여부)은templates를 일반화하며 빠졌으므로.ai-harness/docs/frontend.md에 실측으로 채운다(보호 파일 — 자동 갱신하지 않는다). Skill 본문은 이 문서가 있으면 우선하도록 이미 적혀 있다.feature-sliced-design·no-unnecessary-effects는 각각 MIT 라이선스 상류의 사본이며(THIRD-PARTY-LICENSES.md), 복사본에도 각 SKILL.md 하단의 저작권 문구가 남는다. - AGENTS.md 워크플로 표에는
/implement-feature·/fix-bug·/review를 프로젝트 진입점으로 싣고,/understand-change는 플러그인 제공 스킬로 구분해 표기한다 — 프로젝트 파일이 아니므로 하네스 동기화가 아니라 플러그인 설치로 제공된다는 점을 함께 적는다. 프론트 판단 Skill을 생성했으면 프로젝트 로컬 Skill로 표에 함께 싣는다. - Claude 어댑터도 프로젝트 로컬 workflow·graph를
@.ai-harness/...로 참조한다. Claude Code가 2.1.154 이상이면 승인 후 프로젝트의.claude/workflows/<name>.js를 선택적으로 사용할 수 있고, 그렇지 않으면 현재 세션 흐름으로 폴백한다. 워크플로는 이름으로 등록되지 않으므로 프로젝트 루트 기준 절대 경로를scriptPath로 넘겨 호출하고, 승인된 Brief를{ approved: true, brief: "..." }로 전달한다. 상대 경로는 셸 작업 디렉터리 기준으로 해석되어 실패할 수 있다. 사용하지 않는 도구의 디렉터리·설정 파일은 만들지 않는다. - 모델은 역할 agent 정의에 직접 지정한다. 이는 사용자 인터뷰 항목이 아니며, 기본 매핑은 아래와 같다.
model없는 역할 agent는 생성 실패로 취급한다 — Claude Code는 frontmatter에model이 없으면 부모 세션 모델을 상속하므로, reviewer가 sonnet으로 내려가거나 developer가 opus로 올라가 등급 설계가 무력화되고 비용도 부모 모델 기준으로 붙는다. 표에 없는 역할을 새로 만들면 그 역할의 기본 모델도 표에 함께 추가한다. 중요한 보안·데이터 마이그레이션·복잡한 장애 분석은 explorer/test-engineer에 맡기지 않고 developer 또는 reviewer로 승격한다.
| 역할 | Codex agent 설정 | Claude agent 설정 | 위임 기준 |
|---|---|---|---|
| explorer | gpt-5.6-terra, low, read-only |
haiku |
범위가 독립적인 코드 탐색·문서 확인만 |
| test-engineer | gpt-5.6-terra, medium |
sonnet |
재현·테스트 추가. 원인 분석이 복잡하면 developer로 승격 |
| developer | gpt-5.6, medium |
sonnet |
구현·수정의 기본 담당 |
| reviewer | gpt-5.6, high, read-only |
opus |
보안·데이터·설계·마이그레이션 검토에 우선 사용 |
| docs-updater | gpt-5.6-terra, medium |
sonnet |
코드 변경 뒤 docs 영향 분석·갱신 |
- 위임은 모델 등급과 무관하게 부모 컨텍스트·도구 호출 비용이 든다. 독립적이고 범위가 좁은 작업에만 쓰며, 단순 작업은 현재 세션에서 직접 처리한다.
- Codex 통합은
.codex/agents/*.toml에name,description,developer_instructions,model,model_reasoning_effort, 필요 시sandbox_mode를 쓴다. Claude 통합은.claude/agents/*.mdfrontmatter의model에 위 별칭을 쓴다. 선택한 도구에서 기본 모델이 사용 불가하면 설정을 억지로 대체하지 말고, 감지된 오류와 대체 후보를 사용자에게 보여 준다.
매니페스트 형식 (인터뷰 답 기록 — 수준 변경·/harvest의 정책 참조용):
{ "project_id": "<origin 저장소명 또는 사용자 확인 ID>", "level": "standard", "test_policy": "tdd", "git_policy": "pr-only", "integrations": ["codex"], "stacks": [], "edit_guard": false, "initialized": "YYYY-MM-DD", "harness_version": "<플러그인 버전>", "managed_files": { "<relative path>": { "content_sha256": "<생성 직후 해시>", "template_version": "<플러그인 버전>" } } }
5. 마무리
- 생성물 자기 검증 (보고보다 먼저) — 아래를 실행해 역할 agent의
model누락을 잡는다. 출력이 있으면 §4 표 기본값으로 채운 뒤 다시 실행하고, 출력이 빈 상태가 되기 전에는 2번으로 넘어가지 않는다.
shopt -s nullglob
for f in .claude/agents/*.md; do grep -q '^model:' "$f" || echo "model 누락: $f"; done
for f in .codex/agents/*.toml; do grep -q '^model[[:space:]]*=' "$f" || echo "model 누락: $f"; done
선택하지 않은 도구의 디렉터리는 애초에 없으므로 nullglob으로 루프를 건너뛴다(가드가 없으면 매치 없는 글롭이 리터럴로 바인딩돼 오탐이 난다). Codex 쪽은 model_reasoning_effort가 ^model에 걸리므로 =까지 anchor한다.
- 생성 파일 목록 + 각 파일이 실측에서 가져온 근거 요약 보고 (1번 검증을 통과한 뒤에만)
- 커밋/PR은 사용자 확인 후 (프로젝트 git 컨벤션 따름)
- 생성 직후 하네스가 관리하는 생성물(프로젝트 로컬 Skill/command, graph, agent 설정, settings)을 아래 명령으로 기록한다.
AGENTS.md,.ai-harness/docs/, 사람이 작성한 workflow 본문은 관리 목록에 넣지 않는다.
$ROOT/scripts/harness-sync-state.sh record --root . --version <플러그인 버전> \
--file <관리 생성물 상대 경로> [...]
- 선택한 도구의 진입점과 agent 모델 기본값을 안내: Codex는
.agents/skills/의 자연어 호출과.codex/agents/, Claude는.claude/commands/와.claude/agents/를 사용한다. 모델을 사용할 수 없다는 오류가 있으면 대체 후보를 사용자에게 제시한다. 이후 세션부터 활동이 자동 수집되며, 2~4주 뒤/metrics로 관찰,/harvest <프로젝트>로 개선 사이클을 시작한다.
6. 기존 하네스: 동기화와 설정 변경
- 현재 상태 파악:
.ai-harness/harness.json을 Read하고, 플러그인 루트release.json의 버전과 비교한다. manifest가 없으면 파일 구조로 역추정한다 — 워크플로·페르소나 유무 = standard, guard hook 유무 =edit_guard:true,.agents/skills와.claude유무 = 도구 통합, test-engineer·testing.md 유무 = 테스트 정책.stacks가 manifest에 없으면 파일로 역추정한다 —*/skills/frontend-fundamentals등 프론트 판단 Skill이 있으면frontend,*/skills/feature-sliced-design이 있으면fsd도 포함으로 본다. 기존level:"full"은level:"standard", edit_guard:true로 이관 제안한다. - 모드 선택:
--sync이면 인터뷰 없이 동기화 계획을 만들고,--sync --apply이면 아래 안전 규칙으로 적용한다.--reconfigure이면 2번 수준 인터뷰를 진행한다. 인자가 없으면 현재 설정·버전을 보여 주고 동기화 / 설정 변경 / 둘 다 중 사용자 선택을 받는다. - 동기화 계획: 관리 대상은
templates/managed-files.json이 단일 출처다. 아래 명령으로 현재 level·integration·stack에 맞는 대상과add/refresh/approval_required결정을 JSON으로 만들고, 사람이 읽을 수 있는 표와 최신 템플릿 diff를 함께 제시한다. plan은 artifact의stack이 manifeststacks에 없으면 건너뛴다 — 백엔드 프로젝트에는 프론트 Skill이 계획에 오르지 않고, 나중에 프론트 스택이 생겨--reconfigure로stacks에 추가하면 그때 add 대상이 된다. 과거 버전처럼managed_files이력이 없는 기존 파일은 untracked로 분류한다.
$ROOT/scripts/harness-sync-state.sh plan --root . \
--catalog "$ROOT/templates/managed-files.json"
- 추가 가능: 새로 도입된 graph, 프로젝트 로컬 Skill/command, agent 설정처럼 대상 파일이 없는 관리 생성물
- 자동 갱신 가능: 상태가
unchanged인 관리 생성물. 최신 템플릿으로 재생성하고 hash를 갱신한다. - 승인 필요:
modified또는untracked인 관리 생성물. 3-way 성격의 현재 파일/마지막 생성 해시/제안 템플릿 diff를 보여 주고, 파일별 사용자 승인을 받은 뒤에만 갱신한다. - 보호됨:
AGENTS.md,.ai-harness/docs/**, 사람이 작성한 workflow 본문. 자동 갱신하지 않으며 개선 제안 diff만 제공한다. - 코드↔docs drift (보호 파일에 대한 읽기 전용 리포트 — 자동 수정하지 않는다): 관리 생성물 동기화는 템플릿 대비 구조만 보므로, 빌드 파일이 바뀌고 문서가 그대로인 상태는 이 경로로만 드러난다. 아래를 실행해
missing_in_docs(빌드에 있는데 어느 문서에도 안 적힌 검증 태스크·스크립트·프로파일·태그)와stale_in_docs(문서가 부르는데 빌드에 없는 것)를 "보호 파일 후속 조치" 표에 행으로 싣는다.timestamps.docs_older_than_build가 true면 정확도 낮은 약한 신호로 함께 적되 그것만으로 행을 만들지는 않는다. 수정은 사용자 승인 또는 문서 담당 페르소나에게 넘긴다 — 문서는 보호 파일이라--apply에서도 건드리지 않는다.
$ROOT/scripts/docs-drift.sh scan --root .
기계로 확인 가능한 토큰만 본다: Gradle 검증 태스크(이름에 test/check/verify/lint/coverage/e2e/integration/regression/migrat/format 포함)와 JUnit `includeTags`/`excludeTags`, npm `scripts` 키, Maven 프로파일 `<id>`, pytest `markers`. 문서 쪽은 임의 단어가 아니라 **실제 호출 형태**(`./gradlew <task>`, `npm run <script>`, `-P<profile>`, `-m <marker>`)만 사용으로 인정하고, 태그만 서술 언급도 인정한다. `drift: false`면 이 행을 만들지 않는다. 문서를 이해하려 들지 않으므로 서술이 낡았는지는 판정하지 못한다 — 토큰이 맞는지만 본다.
- 후속 제안(
suggestions): plan 출력의suggestions배열을 계획 표와 함께 반드시 별도 "보호 파일 후속 조치" 표로 제시한다 — 건너뛰면 새 진입점이 미등재 반쪽 상태로 남는다.workflow_body_missing은 새 진입점이@로 참조하는.ai-harness/workflows/<name>.md본문 부재,agents_md_reference는 AGENTS.md 커맨드 표 미등재를 뜻한다. - 역할 agent
model드리프트 (위 분류와 별개인 수동 점검 — 역할 agent는managed-files.json대상이 아니어서plan출력에 나오지 않는다): §5의 1번 self-check 스니펫을 그대로 실행해model없는 역할 agent를 찾고, §4 표 기본값으로 채우는 한 줄 추가를 계획 표 맨 아래에 별도 행으로 싣는다. 이전 버전이 누락한 채 생성한 경우가 있고, 누락된 agent는 부모 세션 모델을 그대로 상속한다. 본문은 바뀌지 않으므로 diff는 한 줄이지만, 적용은 다른 항목과 같이 사용자 승인 뒤에 한다. 해시 기록 대상이 아니므로record도 하지 않는다. - 정리 대상(
retired): 카탈로그의retired목록이 명시적으로 내린 생성물 중 이 프로젝트에 흔적이 남은 것이다(예: 0.16.0에서 깔렸다가 플러그인 전역 Skill로 옮겨진/understand-change사본).present는 파일이 디스크에 남았는지,tracked는 manifest가 아직 기록 중인지를 뜻하며 둘은 따로 정리해야 한다. 계획 표에 반드시 함께 제시한다 — 방치하면 낡은 프로젝트 사본이 최신 플러그인 스킬을 가린다. 카탈로그에 없다는 사실만으로 추론하지 않는다:.codex/agents/*.toml처럼 init이 관리하지만 카탈로그가 선언한 적 없는 생성물이 있어, 추론하면 살아 있는 파일을 삭제 후보로 올린다.
- 적용 규칙:
--sync만 있으면 절대 파일·manifest를 변경하지 않는다.--sync --apply에서도 추가 가능·자동 갱신 가능 항목만 적용하고, 승인 필요 항목은 명시 승인 범위만 적용한다. 삭제·통합 해제는 항상 파일 목록과 별도 확인을 요구한다. 새 진입점(add) 적용 시suggestions를 함께 처리한다:workflow_body_missing은 프로젝트 정책(테스트 정책·검증 명령·docs 매핑)에 맞춰 워크플로 본문을 생성하되 관리 목록에는 기록하지 않는다 (이후 사람이 소유하는 보호 파일).agents_md_reference는 커맨드 표 한 줄 diff를 제안하고 사용자 승인 후에만 AGENTS.md를 편집한다 — 승인이 없으면 미등재 상태와 그 영향(Preflight 라우팅에서 새 워크플로가 제외됨)을 최종 보고에 명시한다.retired항목은 파일 목록을 보이고 사용자 확인을 받은 뒤에만present:true인 파일을 삭제하고,tracked:true인 항목은harness-sync-state.sh forget --file <path>로 manifest에서 지운다 —forget은 manifest만 정리하며 파일을 삭제하지 않으므로 해당하는 두 단계를 모두 수행한다. 확인을 못 받으면 파일과 manifest 항목을 그대로 두고 낡은 사본이 남았다는 사실을 보고한다. 적용 뒤 실제로 쓴 관리 생성물만harness-sync-state.sh record로 기록하고harness_version을 갱신한다. - 설정 변경: 재인터뷰 결과에 따라 diff만 적용한다. 테스트 정책 변경은 workflow 본문의 테스트 절차, test-engineer·testing.md, AGENTS.md 위임 규칙을 갱신하되, 기존 사용자 수정은 3번의 승인 필요 규칙을 따른다.
- 변경 요약, 건너뛴 보호 파일, 다음 동기화에서 검토할 untracked 파일을 보고한다. 커밋/PR은 사용자 확인 후에만 한다.
7. Workspace 모드 — 여러 독립 저장소가 한 폴더에 있을 때
cwd가 git 저장소가 아니고 하위에 독립 git 저장소가 둘 이상이면 workspace다. 이 모드는 라우팅 층만 만든다 — 워크플로·페르소나·hook·settings는 만들지 않고, 멤버 저장소의 하네스는 한 바이트도 바꾸지 않는다. 모노레포(git 루트 하나)는 workspace가 아니라 단일 프로젝트다.
Claude Code는 cwd의 .claude/만 로드하므로 workspace 세션에서는 멤버의 슬래시 커맨드·페르소나·편집 가드가 동작하지 않는다. 이는 플러그인이 해결할 수 없는 로더 한계다. 그래서 workspace 세션은 여러 저장소를 훑어보거나 교차 변경을 조율하는 용도이고, 한 저장소 안에서 깊게 구현할 때는 그 저장소에서 세션을 여는 것이 맞다 — 이 안내를 workspace AGENTS.md 첫 줄에 쓴다.
7-1. 감지
$ROOT/scripts/workspace-scan.sh scan --root . # 기본 depth 2
$ROOT/scripts/workspace-scan.sh scan --root . --depth 3 # 그룹 폴더가 더 깊을 때만
.git디렉터리만 멤버 후보다. 서브모듈·worktree는.git이 파일이라 제외되고node_modules아래는 내려가지 않는다.- 멤버
project_id는 멤버harness.json의 값을 우선하고, 없으면 origin 저장소명 → 폴더명 순으로 정한다(project_id_for_cwd와 같은 규칙). 출처는id_source(manifest/origin/path)로 붙는다.manifest·origin출처의project_id가 여럿이면 한 저장소의 clone이므로 멤버 하나로 접고 나머지 경로를also_paths에 둔다.path출처(폴더명 폴백)는 identity가 아니라서 접지 않는다 — 무관한teamA/backend·teamB/backend는 둘 다 멤버다. 다른 멤버 안에 중첩된.git(커밋된 vendor clone 등)은 그 멤버의 일부로 보고 멤버로 잡지 않는다. 접은 뒤 멤버가 1개면candidate:false다 — 같은 저장소의 worktree 폴더만 모인 곳은 workspace가 아니다. - 멤버마다
harness:true|false와 실측 정책(level·test_policy·git_policy·edit_guard)이 붙는다.harness:false인 멤버는 그 저장소에 하네스가 없다는 표시이며, 이 시점에 init하지 않는다.
7-2. 확인
멤버 표(경로·project_id·하네스 유무·테스트 정책·git 정책·also_paths)를 보이고 AskUserQuestion으로 workspace로 셋업 / 취소를 받는다. workspace 수준 인터뷰는 도구 통합(Claude / Codex / 둘 다) 하나만 묻는다. 규모·테스트 정책·편집 가드는 멤버 각자의 것이므로 여기서 묻지 않는다.
7-3. 생성물
AGENTS.md # 라우팅 전용 진입점 (보호 파일)
CLAUDE.md # "@AGENTS.md" — Claude 또는 둘 다를 선택했을 때만
.ai-harness/
workspace.json # 매니페스트. harness.json과 파일명이 달라 단일 프로젝트와 섞이지 않는다
매니페스트는 손으로 쓰지 않고 스크립트로 기록한다. 생략한 값은 기존 manifest에서 유지되고 harness_version은 현재 플러그인 버전으로 찍힌다. 첫 기록은 candidate:true일 때만 되고 git 저장소 안에서는 거부된다. 기존 manifest의 재기록(7-6)은 멤버가 줄어도 허용된다.
$ROOT/scripts/workspace-scan.sh write --root . --workspace-id <폴더명 또는 사용자 확인 ID> --integrations claude
managed_files는 없다. AGENTS.md·CLAUDE.md는 보호 파일이고 그 외 관리 생성물이 없으므로 harness-sync-state.sh를 거치지 않는다. 계측은 workspace 세션을 workspace_id로 귀속한다(project_id_for_cwd가 workspace.json을 git 판정보다 먼저 본다). 멤버별 편집 귀속은 후속 버전에서 다룬다.
7-4. AGENTS.md 구성
- 첫 줄 안내: 위 로더 한계와 쓰임새(훑어보기·교차 조율용, 깊은 구현은 멤버 저장소에서).
- Preflight: ① 작업 대상 파일 경로의 첫 세그먼트로 멤버를 정한다. ② 그 멤버의
AGENTS.md를 Read한다. ③ 멤버 워크플로는 슬래시 커맨드로 부를 수 없으므로<member>/.ai-harness/workflows/<name>.md를 직접 Read하고 절차를 따른다. ④ 멤버 페르소나(<member>/.claude/agents/*.md)는 위임 시general-purpose프롬프트에 지침을 인라인한다 — 역할 격리가 약해진다는 점을 함께 적는다. - 멤버 표: 경로 · project_id · 하네스 유무 · 테스트 정책 · git 정책.
harness:false멤버는 "해당 저장소에서/harness-init권장"으로 표기한다. - 교차 작업 규칙: 멤버 둘 이상을 건드릴 때 멤버별 별도 브랜치·PR, 컨벤션은 각 멤버 것만 적용(섞지 않음), 공유 계약(API 스키마·이벤트 포맷) 변경은 제공자 → 소비자 순서, 완료 보고는 멤버별 검증 결과를 분리.
- Hard constraints: 틀만 비워 둔다. 단일 하네스와 같이
/harvest가 채운다. - Quick Commands: 멤버별 빌드·테스트 명령을
(cd <member> && ...)형태로. 멤버 AGENTS.md의 실측 명령을 복사하고 없으면 비운다.
7-5. 멤버 init 후속 단계 (opt-in)
생성물을 쓴 뒤 harness:false 멤버가 있으면 AskUserQuestion(multiSelect)으로 지금 init할 멤버를 고르게 한다. 기본값은 전부 해제다 — 다른 팀 저장소에 합의 없이 하네스를 심는 일을 막는다. 고르지 않은 멤버는 표기만 남긴다.
- 선택된 멤버를 한 번에 하나씩 처리한다. 1~5번 절차를 그대로 쓰되 모든 경로를 멤버 루트 기준으로 둔다 — 분석은
git -C <member>·<member>/package.json처럼 경로를 명시하고, 기록은harness-sync-state.sh record --root <member>로 한다. - 인터뷰는 첫 멤버에서 2번의 전체 항목을 묻고, 두 번째 멤버부터는 앞 멤버의 답을 기본값으로 보여 "같음 / 다르게 답함" 하나만 묻는다. 실측이 기본값과 모순되면(앞 멤버는 TDD인데 이 멤버는 테스트 0개 등) 2번의 경고 규칙대로 지적한다.
- 멤버 하나가 끝나면 생성 파일 목록과 실측 근거를 보고하고 커밋 여부를 확인한 뒤 다음 멤버로 간다. 저장소마다 브랜치·PR이 따로이므로 한 멤버를 끝내기 전에 다음 멤버 파일을 만들지 않는다.
- 선택이 3개를 넘으면 앞의 3개만 처리하고 나머지는 "각 저장소에서
/harness-init"으로 안내한다. 상위 세션 컨텍스트 보호가 목적이다. 실측 분석은 Explore 서브에이전트에 위임할 수 있지만 인터뷰는 서브에이전트가 사용자에게 질문할 수 없어 메인 세션에서 한다. - 모두 끝나면
workspace-scan.sh write --root .로 매니페스트를 다시 기록하고(멤버가harness:true와 실측 정책으로 바뀐다), AGENTS.md 멤버 표는 diff를 보여 승인 후에만 편집한다.
7-6. 기존 workspace: 동기화
scan은 기존 workspace.json이 있으면 diff를 함께 낸다 — added(새 멤버 폴더), removed(사라진 멤버), changed(멤버의 하네스 유무·정책이 바뀜).
--sync만 있으면 표만 보이고 파일·manifest를 바꾸지 않는다.--sync --apply:added·changed는workspace-scan.sh write --root .로 manifest를 갱신한다.removed는 멤버 목록을 보이고 사용자 확인 후에만 write한다(폴더가 잠시 없는 것일 수 있다). AGENTS.md 멤버 표·Quick Commands는 보호 파일이므로 diff를 제안하고 승인 후 편집한다.- 멤버 저장소 자체의 동기화는 여기서 하지 않는다. 각 멤버에서
/harness-init --sync를 안내한다.