VibeLign 구조 계획 시스템 기획안
VibeLign 구조 계획 시스템 기획안
상태: 구현 완료 (문서 범위 반영) 목적: AI가 새 기능 추가 또는 편집 전에 코드 배치 위치를 VibeLign으로부터 사전 확정받는 시스템
1. 문제 정의
현재 상황
사용자: "OAuth 인증 추가해줘"
AI: auth.py 열기 → OAuth 코드 전부 거기 추가 → 파일 비대화
규칙(AGENTS.md)에 “구조화하라”고 명시되어 있어도 AI는:
- 기존 파일에 추가하는 것이 “안전”하다고 판단 (import 깨질 위험 없음)
- “구조화”의 기준이 모호 → 판단 회피
- 어디에 넣어야 하는지 알 방법이 없음
목표 상황
사용자: "OAuth 인증 추가해줘"
AI: vib plan-structure "OAuth 인증 추가" 실행
→ 계획: oauth_provider.py 신규, auth.py ANCHOR:AUTH_HANDLER만 수정
AI: 계획대로 파일 분산 작성 → 구조 유지
왜 B 방식(사전 구조 계획)인가
A 방식(줄 수 제한)의 문제: 파일이 200줄 초과 → 커밋 차단 → AI가 임의의 함수를 새 파일로 빼서 줄 수만 맞춤 → 구조는 여전히 엉망, 제한만 통과
B 방식은 “어디에 넣을지”를 사전에 확정하므로 구조가 근본적으로 유지됨.
2. 핵심 설계 원칙
- AI가 판단하는 것이 아니라 VibeLign이 판단하고 AI는 실행
- 모호한 규칙(“구조화해라”) 대신 구체적 지시(“oauth_provider.py에 넣어라”)
- 사용자는 처음 요청 하나만 — 나머지는 AI + VibeLign이 처리
- 계획은 파일로 저장 → 세션이 바뀌어도 AI가 참조 가능
- Phase 1에서는 현재 존재하는 메타데이터(
category,anchor_index,line_count, 경로 토큰)만 사용하고, 사람 수준의 “책임 추론”은 과장하지 않음
3. 전체 워크플로
사용자 관점 (단순)
사용자: "OAuth 인증 추가해줘" ← 이것만 하면 됨
↓
[VibeLign + AI가 자동 처리]
↓
사용자: 결과물 확인
내부 처리 흐름
사용자 요청
↓
AI: vib plan-structure "OAuth 인증 추가" 실행
↓
VibeLign 분석 (백엔드):
① 파일 크기 체크 → 기존 파일 한계 초과 여부
② project_map(코드맵) 카테고리/앵커/줄 수 조회 → 수정 후보 압축
③ 경로/폴더 패턴 매칭 → 도메인 키워드로 위치 확정
④ 앵커 가용성 체크 → 앵커 없으면 신규 파일 생성
↓
구조 계획 출력 + .vibelign/plans/<timestamp>.json 저장
↓
AI: 계획대로만 코딩
↓
watch --auto-fix: 앵커 자동 삽입 ← 앵커 집행 시스템 연동
vib guard: 계획 준수 여부 검증
project_map(코드맵)은 watch 엔진이 파일 변경마다
_refresh_project_map()으로 갱신할 수 있다. 단, watch가 실제 실행 중이고.vibelign/project_map.json이 이미 존재할 때만 최신성이 보장된다.
4. vib plan-structure 명령어 설계
입력
vib plan-structure "OAuth 인증 추가"
vib plan-structure --ai "OAuth 인증 추가" # LLM 연동 (선택)
vib plan-structure --scope vibelign/core/ "watch 기능 확장"
출력 (터미널)
[VibeLign] 구조 계획 생성 중...
기능: OAuth 인증 추가
분석: vibelign/core/auth.py (현재 187줄, 앵커 3개) → 한계 초과, 분리 필요
📋 구조 계획
─────────────────────────────────────
수정 허용:
vibelign/core/auth.py → ANCHOR: AUTH_HANDLER 구간만 (최대 20줄)
신규 생성:
vibelign/core/oauth_provider.py ← OAuth 공급자 로직
vibelign/core/oauth_tokens.py ← 토큰 관리 로직
금지:
auth.py에 OAuth 구현 코드 직접 추가
계획 저장: .vibelign/plans/20260409T123456_oauth_auth.json
─────────────────────────────────────
이 계획대로 작업하세요. 완료 후 vib guard로 검증.
저장 형식 (.vibelign/plans/*.json)
{
"id": "20260409T123456_oauth_auth",
"schema_version": 1,
"feature": "OAuth 인증 추가",
"created_at": "2026-04-09T12:34:56",
"mode": "rules",
"evidence": {
"candidate_files": ["vibelign/core/auth.py"],
"matched_categories": ["core"],
"matched_keywords": ["auth", "oauth", "token"],
"path_signals": ["core", "auth"],
"requires_planning": true,
"required_reasons": ["new_production_file", "multi_file_production_edit"]
},
"scope": {
"changed_path_classes": ["production_path"],
"new_file_paths": [
"vibelign/core/oauth_provider.py",
"vibelign/core/oauth_tokens.py"
],
"existing_file_paths": ["vibelign/core/auth.py"]
},
"allowed_modifications": [
{
"path": "vibelign/core/auth.py",
"anchor": "AUTH_HANDLER",
"reason": "OAuth 진입점 연결만",
"max_lines_added": 20,
"allowed_change_types": ["edit", "import_wiring"]
}
],
"required_new_files": [
{
"path": "vibelign/core/oauth_provider.py",
"responsibility": "OAuth 공급자 로직"
},
{
"path": "vibelign/core/oauth_tokens.py",
"responsibility": "토큰 관리 로직"
}
],
"forbidden": [
{
"type": "path_edit",
"path": "vibelign/core/auth.py",
"reason": "OAuth 구현 코드를 auth.py 본문에 직접 추가하면 파일 비대화 위험"
}
],
"messages": {
"summary": "OAuth 기능은 신규 모듈 2개로 분리하고 auth.py는 진입점 wiring만 허용",
"developer_hint": "guard는 allowed_modifications / required_new_files / forbidden 기준으로 실제 변경을 비교한다."
}
}
plan JSON schema 상세 규칙 (Phase 1)
id: plan 식별자..vibelign/plans/<id>.json파일명과 동일해야 함schema_version: 현재는1고정mode:rules또는ai(--ai경로 확장 대비)evidence.required_reasons[]: guard가planning_required를 설명할 때 그대로 재사용 가능한 이유 코드scope.changed_path_classes[]:production_path,support_path등 path class 기록allowed_modifications[]:path필수anchor는 anchor 기반 수정일 때 필수max_lines_added는 선택allowed_change_types[]는edit,import_wiring,registration,config_touch같은 제한 코드
required_new_files[]:- guard가 신규 파일 생성을 허용 목록과 비교할 때 사용
forbidden[]:- 문자열 배열 대신 객체 배열 사용
- 최소 필드:
type,reason path,anchor,pattern은 type별 선택 필드
messages.summary:- CLI 출력과 guard 요약 메시지의 기본 소스로 사용 가능
- plan이 파손되었거나 필수 필드가 없으면 guard는
fail또는plan_missing계열 상태로 처리
5. 위치 결정 알고리즘
동작 우선순위
- 규칙 기반 (API 없음, 기본 동작)
- LLM 연동 (선택적,
--ai옵션)
규칙 기반 4단계
Step 1: 파일 크기 체크 (기계적)
후보 파일 줄 수 > 150줄 → 신규 파일 생성 필수
후보 파일 앵커 수 > 5개 → 모듈 분리 권고
Step 2: project_map 메타데이터 기반 후보 압축
기능 설명 키워드 추출
↓
project_map의 category / anchor_index / line_count 확인
↓
후보 파일 압축 / 근거 부족 시 신규 파일 쪽으로 보수적 결정
project_map 없을 때 폴백:
.vibelign/project_map.json이 없거나 watch가 꺼져 있으면 Step 2를 건너뛰고 Step 3(경로/폴더 패턴 매칭)만으로 진행한다. 터미널에 경고를 출력한다:[VibeLign] project_map이 없습니다. 경로 패턴 기반으로만 분석합니다. 정확도를 높이려면 `vib watch`를 실행하거나 `vib scan`으로 맵을 생성하세요.project_map 없이도
vib plan-structure는 실행되지만 제안 정확도가 낮아질 수 있다.
Step 3: 폴더 패턴 매칭
"auth", "oauth", "login", "token" → core/auth* 계열
"cli", "command" → commands/
"watch", "monitor", "scan" → core/watch_*
"mcp", "handler" → mcp/
"test" → tests/
초기 버전에서는 이 매핑을 코드에 명시적으로 둔다. 자동 학습은 후속 단계 과제.
Step 4: 앵커 가용성 체크
수정 후보 파일 선정
↓
적합한 앵커 있음 → 그 구간에 추가
앵커 없음 → 신규 파일 생성으로 전환
앵커는 있지만 키워드와 매칭되는 앵커 없음
→ 보수적 결정: 신규 파일 생성 권고
→ (단, category 매칭이 강하면 가장 근접한 앵커 제안 가능)
앵커 매칭 실패 엣지 케이스: 파일에 앵커가 존재하더라도 feature 키워드와 의미적으로 연결되는 앵커가 없으면 신규 파일 생성으로 보수적 전환한다. category 매칭(Step 2)이 강한 경우에만 예외적으로 “가장 근접한 앵커 구간 사용”을 제안할 수 있으며, 이 경우 evidence에 근거를 기록한다.
규칙 기반 한계 및 LLM 폴백
| 상황 | 규칙 기반 | LLM (–ai) |
|---|---|---|
| 키워드 명확 (“auth”, “CLI”) | 정확 | 정확 |
| 키워드 모호 (“개선”, “수정”) | 실패 → 사용자에게 명확화 요청 | 컨텍스트로 판단 |
| 새 도메인 (기존 패턴 없음) | 신규 파일 생성 | 프로젝트 맥락 반영 |
규칙 기반이 위치를 확정 못하면:
[VibeLign] 기능 설명이 모호합니다.
더 구체적으로 설명하거나 --ai 옵션을 사용하세요.
예: vib plan-structure --ai "OAuth 인증 추가"
6. vib plan-structure 호출 강제 방법
세션 잠금 방식
vib plan-structure 실행 시 별도 session_plan.json을 만들기보다
기존 .vibelign/state.json의 세션 상태와 공존 가능한 형태로 계획 상태를 저장한다.
목표는 “계획 없이 바로 코딩”을 줄이는 것이지, 상태 파일을 이원화하는 것이 아니다.
Claude Code (진짜 강제)
앵커 집행 시스템과 동일한 단일 PreToolUse 훅을 공유한다 (vib claude-hook).
훅이 순서대로 두 가지를 검사:
AI가 Write/Edit 시도
↓
VibeLign PreToolUse 훅 (하나, 앵커 집행 시스템과 공유)
① plan-structure 세션 존재? (구조 계획 시스템)
→ 없음: 차단 + "vib plan-structure를 먼저 실행하세요"
② 앵커 있는가? (앵커 집행 시스템)
→ 없음: 경고 + 재작성 유도
↓
planning은 Claude 컨텍스트에서 strict + enable 상태일 때만 차단,
앵커는 경고를 보여주고 현재 Write를 한 번 막은 뒤 다시 쓰게 유도
훅 관리: vib claude-hook enable / disable / status
실제 로직은 hook_setup.py에, CLI는 vib_claude_hook_cmd.py에 분리.
strict는 전역값 하나가 아니라 컨텍스트별 계산값이다. git pre-commit, Claude PreToolUse, 수동
vib guard는 서로 독립적으로 strict/non-strict를 해석한다.
컨텍스트별 집행 강도 (앵커 집행 시스템과 동일 정책):
| 컨텍스트 | planning 강도 | 앵커 강도 |
|---|---|---|
| Claude Code PreToolUse | gating (차단) | 한 번 막고 다시 쓰게 유도 |
| git pre-commit | strict (차단) | strict (차단) |
| vib guard (수동 실행) | non-strict 기본 (경고) | non-strict 기본 (경고) |
vib guard --strict로 수동 실행 시 수동 guard 컨텍스트도 차단 동작으로 전환 가능. Claude Code PreToolUse의 planning이 gating인 이유: Write 도구 호출 전에 개입 가능하므로 사전 차단이 현실적임.
git 사용자 (커밋 시 강제)
커밋 시 planning 상태 존재 여부 검사:
계획 상태 없음 → 커밋 차단 (strict)
"vib plan-structure 없이 작업이 감지됐습니다"
어떤 변경에 강제를 적용할지는 §7
vib guard판정 규칙 표(Step A-D)를 따른다. 요약: 문서/테스트/config 수정 및 소규모 단일 파일 수정은planning_exempt, 신규 production 파일 생성 또는 multi-file 수정은planning_required.
AI별 강제 수준
| AI | 강제 방법 | 강도 |
|---|---|---|
| Claude Code | PreToolUse 훅 + 세션 잠금 | 진짜 강제 |
| git 사용자 | 기존 pre-commit hook 확장 경로에서 커밋 차단 | 커밋 시 강제 |
| Cursor / Codex / 기타 | AGENTS.md 규칙 | 권고 수준 |
7. 보조 안전망 (A 방식 병행)
vib plan-structure를 안 쓴 경우 최후 방어선:
파일 줄 수 > 200줄 AND 앵커 없음 → vib guard 경고
파일 줄 수 > 300줄 → git pre-commit 경고
차단이 아닌 “경고” → 코알못 사용자 혼란 방지 강한 차단은
--strict옵션으로 개발자만
guard 판정 규칙 표 (Phase 1 초안)
| 변경 유형 | 예시 | planning 상태 없음 | planning 상태 있음 + 준수 | planning 상태 있음 + 이탈 |
|---|---|---|---|---|
| 문서 수정 | docs/README.md 편집 |
planning_exempt |
planning_exempt |
planning_exempt |
| 테스트만 수정 | tests/test_watch_engine.py 추가/수정 |
planning_exempt |
planning_exempt |
planning_exempt |
| config-only 수정 | pyproject.toml, .claude/settings.json 수정 |
planning_exempt |
planning_exempt |
planning_exempt |
| 단일 파일 소규모 코드 수정 | 기존 production 파일 1개에서 국소 버그 수정 | planning_exempt 또는 warn |
준수로 처리 | 필요 시 warn |
| 기존 production 경로의 multi-file 코드 수정 | core/, service/, mcp/, commands/ 내 2개 이상 파일 수정 |
planning_required |
준수로 처리 | plan_exists_but_deviated |
| 새 production code file 생성 | vibelign/core/oauth_provider.py 신규 생성 |
planning_required |
준수로 처리 | plan_exists_but_deviated |
| 계획이 있는 구조 변경 | plan 파일에 허용된 파일/앵커 범위 내 수정 | 해당 없음 | pass | 해당 없음 |
| 계획을 벗어난 구조 변경 | plan에 없는 파일 생성, 금지 경로 수정, 허용 anchor 이탈 | planning_required 또는 fail |
해당 없음 | fail |
Phase 1 판정 메모:
planning_required: Claude PreToolUse에서는 사전 차단 후보, git/pre-commit에서는 fail 또는 강한 warn 후보planning_exempt: plan 없이 진행 가능, 단 일반 guard 규칙(앵커/구조/크기)은 별도 적용plan_exists_but_deviated: plan은 있었지만 실제 변경이 허용 범위를 벗어난 상태- “단일 파일 소규모 코드 수정”은 line count만으로 확정하지 않고, path와 새 파일 여부를 함께 본다
vib guard 구현 상세 spec (Phase 1)
1) 목표
vib guard는 구조 계획 시스템 관점에서 다음 3가지를 판정해야 한다.
- 현재 변경이
plan-structure없이 진행 가능한 변경인가? - 현재 변경이
plan-structure가 필요한 변경인가? - plan이 존재한다면 실제 변경이 plan 범위를 준수했는가?
Phase 1에서는 LLM 추론 없이 규칙 기반 판정만 사용한다.
2) 입력 데이터
vib guard는 최소한 아래 입력을 사용한다.
- 변경 집합
- git 환경: staged diff 우선
- 비 git 환경 또는 staged 없음: working tree 변경 파일
- 필요 시
since_minutes같은 기존 guard 옵션과 공존 가능
- 파일 메타데이터
- 경로
- 신규 생성 여부
- 삭제 여부
- 파일 유형(source / test / docs / config / other)
- line delta 또는 added lines
- 프로젝트 메타데이터
.vibelign/project_map.json이 있으면category,anchor_index,line_count참고- 없으면 경로 기반 분류로 폴백
.vibelign/config.json이 있으면small_fix_line_threshold설정값 참고 (없으면 기본값 30)
- planning 상태
.vibelign/state.json내부 planning session 상태- 현재 활성 plan id
- 연결된
.vibelign/plans/*.jsonplan 내용
3) 사전 분류 규칙
각 변경 파일은 아래 순서로 분류한다.
- 문서 파일:
docs/,*.md, handoff/report 문서 - 테스트 파일:
tests/,test_*.py,*.test.ts,*.spec.ts - config 파일:
pyproject.toml,package.json,.claude/settings.json,.vibelign/*.json,*.yaml,*.yml - source code 파일:
vibelign/, 앱 코드, 서비스 코드, 명령/핸들러 코드 - other: 위 어디에도 명확히 속하지 않는 파일
추가로 source code 파일은 경로 기준으로 다음 중 하나로 나눈다.
production_path:app/,core/,service/,services/,mcp/,commands/, 기타 실제 기능 코드 경로support_path:docs/,tests/, fixture, example, generated, temp 성격 경로
4) 판정용 집계 값
vib guard는 변경 집합에서 다음 값을 계산한다.
changed_file_countchanged_source_file_countchanged_production_file_countnew_production_file_countmulti_file_production_edit(production source file 2개 이상 변경 여부)has_only_docs_changeshas_only_test_changeshas_only_config_changeshas_small_single_file_fix_candidate
has_small_single_file_fix_candidate는 아래를 모두 만족할 때만 true다.
- 변경 파일이 정확히 1개
- 그 파일이 기존 production source file
- 신규 파일 생성이 아님
- added lines가 작은 범위(임계값은
.vibelign/config.json의small_fix_line_threshold설정값 사용, 기본값 30줄) - plan에서 다뤄야 할 구조 변경 신호가 없음
small_fix_line_threshold는 프로젝트별 조정 가능하지만, 이 값은 보조 신호일 뿐 단독 판정 기준이 아니다.
즉, threshold 초과만으로 곧바로 planning_required가 되지 않으며,
threshold 이하만으로 자동으로 planning_exempt가 되지도 않는다.
여기서 구조 변경 신호는 예를 들어 아래다.
- 새 파일 생성
- production 파일 2개 이상 변경
- 새로운 import/export wiring 추가가 큰 비중을 차지함
- 금지 경로 또는 새 모듈 경계 생성
5) plan 조회 규칙
vib guard는 planning 상태가 있더라도 무조건 pass하지 않는다.
조회 순서는 다음과 같다.
.vibelign/state.json에서 활성 planning 상태 확인- 활성 상태가 가리키는
plan_id확인 - 해당
.vibelign/plans/<plan_id>.json로드 - plan이 없거나 파손되었으면
plan_missing으로 간주
Phase 1에서 plan은 최소한 아래 필드를 가진다고 가정한다.
allowed_modifications[]pathanchormax_lines_added(선택)
required_new_files[]path
forbidden[]
6) 최종 판정 순서
vib guard의 구조 계획 판정은 아래 순서를 고정한다.
Step A — 면제 여부 먼저 판정
아래 중 하나면 우선 planning_exempt 후보로 본다.
- 문서만 변경
- 테스트만 변경
- config-only 변경
has_small_single_file_fix_candidate == true
단, 면제 후보라도 기존 일반 guard 규칙(앵커 손실, 구조 위험, 파일 비대화 등)은 별도로 계속 검사한다.
Step B — 계획 필요 여부 판정
아래 중 하나면 planning_required다.
new_production_file_count >= 1multi_file_production_edit == true- production path에서 구조 변경 신호 감지
Step C — plan 존재 여부 확인
planning_required인데 활성 plan이 없으면 결과는planning_requiredplanning_required이고 활성 plan이 있으면 Step D로 진행
Step D — plan 준수 여부 확인
각 변경 파일마다 아래를 검사한다.
- 신규 파일이면
required_new_files.path또는 명시적으로 허용된 신규 생성 대상에 포함되는가? - 기존 파일 수정이면
allowed_modifications.path에 포함되는가? - anchor 정보가 있으면 실제 수정이 허용 anchor 범위 내인가?
max_lines_added가 있으면 초과했는가?- forbidden 규칙과 충돌하는가?
판정 결과:
- 모두 통과 →
pass - plan은 있으나 일부 파일/anchor/line 제한 위반 →
plan_exists_but_deviated - forbidden 직접 위반 →
fail
7) 결과 상태 정의
Phase 1에서 구조 계획 관련 상태는 아래 5개를 사용한다.
pass: plan이 필요했고, 활성 plan도 있으며, 실제 변경이 plan을 준수함planning_exempt: 현재 변경은 plan 없이 진행 가능한 범위임planning_required: 현재 변경은 plan이 필요하지만 활성 plan이 없음plan_exists_but_deviated: 활성 plan은 있으나 실제 변경이 허용 범위를 벗어남fail: 명시 금지 규칙 위반 또는 plan/상태 파손으로 안전하게 진행 불가
8) strict / non-strict 동작
구조 계획 판정은 strict 여부에 따라 아래처럼 동작한다.
- non-strict
planning_exempt→ passplanning_required→ warnplan_exists_but_deviated→ warnfail→ fail
- strict
planning_exempt→ passplanning_required→ failplan_exists_but_deviated→ failfail→ fail
기본값 정책 (사용자 유형별):
| 사용자 유형 | 기본 strict | 설정 방법 |
|---|---|---|
| 코알못 / 일반 사용자 | non-strict (경고만) | 별도 설정 불필요 |
| git 개발자 | strict (차단) | 기존 pre-commit hook 확장 경로 설치 시 자동 적용 |
| Claude Code 사용자 | 사용자 선택형 (enable이면 strict / disable이면 non-strict) | VibeLign이 hook 자동 설치 후 on/off로 제어 |
non-strict를 기본으로 하는 이유: 코알못 사용자가 경고를 보고 학습하며 점진적으로 규칙을 익힐 수 있도록. git strict는 의도적으로 기존 pre-commit hook 확장 경로를 설치한 사용자에게 적용 — “설치했다는 것”이 곧 강제를 원한다는 동의. Claude는 설치와 활성화를 분리한다: 설치는 VibeLign이 자동화하고, strict 진입은 사용자가 기능을 enable 했을 때로 본다.
컨텍스트별 상태 결정표 (Phase 1 고정):
| 컨텍스트 | 설치 상태 | 활성 상태 | strict 결과 | 비고 |
|---|---|---|---|---|
| git pre-commit | 기존 pre-commit hook 확장 경로 설치됨 | 해당 없음 | strict | .git/hooks/pre-commit 기준 |
| git pre-commit | 설치 안 됨 | 해당 없음 | non-strict 아님 / 미적용 | 이 컨텍스트 자체가 없음 |
| Claude PreToolUse | hook 엔트리 설치됨 | claude_hook_enabled=true |
strict 후보 | Claude 컨텍스트에서만 의미 있음 |
| Claude PreToolUse | hook 엔트리 설치됨 | claude_hook_enabled=false |
non-strict | hook은 남고 enforcement만 skip |
수동 vib guard |
해당 없음 | --strict 있음 |
strict | CLI 실행 한 번에만 적용 |
수동 vib guard |
해당 없음 | --strict 없음 |
non-strict | 기본 경고 중심 |
구현 포인트:
strict는 전역 불리언이 아니라 컨텍스트별 계산 결과이며, 다른 컨텍스트의 설치 상태를 덮어쓰지 않는다.
strict 판정 우선순위:
- 명시 설정값이 있으면 그 값을 최우선 적용
- 명시 설정이 없고 git pre-commit hook 확장 경로가 설치되어 있으면 git 컨텍스트에서 strict
- 명시 설정이 없고 Claude PreToolUse 기능이 enable 상태이면 Claude 컨텍스트에서 strict
- 명시 설정이 없고 Claude PreToolUse 기능이 disable 상태이면 Claude 컨텍스트에서 non-strict
- 위 조건이 모두 없으면 기본값은 non-strict
즉, 일반 사용자는 별도 설정 없이 경고만 받고, git 개발자는 hook 설치 시 git 컨텍스트에서만 자동 strict, Claude 사용자는 hook은 자동 설치되더라도 기능 on/off를 직접 선택할 수 있다.
Claude Code hook 운영 원칙:
- Claude 프로젝트가 감지되면 VibeLign은 project-local
.claude/settings.json에 필요한 hook 엔트리를 자동 설치/복구할 수 있다 - 자동 설치/복구는
vib start및 관련 setup 명령에서만 수행하고, read-only 명령에서는 수행하지 않는다 - 단, PreToolUse 기능 활성 여부는 별도 상태로 관리한다
- 권장 명령 예시:
vib claude-hook enablevib claude-hook disablevib claude-hook status
- enable 상태면 Claude 경로는 strict 후보, disable 상태면 Claude 경로는 non-strict 유지
disable는 hook JSON 엔트리를 제거하는 것이 아니라, 설치된 hook의 enforcement 로직을 비활성화하는 뜻으로 사용한다- 수동 JSON 편집은 fallback일 뿐 기본 경로가 아니다
- git hook 설치 여부가 Claude enable/disable를 덮어쓰지 않는다. 두 컨텍스트는 독립적으로 판정한다
planning 상태 스키마 (.vibelign/state.json) 초안:
{
"planning": {
"active": true,
"plan_id": "20260409T123456_oauth_auth",
"feature": "OAuth 인증 추가",
"override": false,
"override_reason": null,
"created_at": "2026-04-09T12:34:56",
"updated_at": "2026-04-09T12:34:56"
}
}
planning.active=false또는 필드 없음 → 활성 plan 없음plan_id는.vibelign/plans/<plan_id>.json과 반드시 연결되어야 함override=true면 guard는 현재 세션을planning_exempt로 처리 가능updated_at은vib plan-structure,vib plan-override, 커밋 후 clear 시점에 갱신
9) 출력 계약
기존 guard envelope에 구조 계획 판정 결과를 아래 형태로 추가한다.
{
"ok": true,
"data": {
"status": "warn",
"planning": {
"status": "planning_required",
"strict": false,
"active_plan_id": null,
"summary": "새 production code file 생성이 감지되어 plan-structure가 필요합니다.",
"changed_files": [
"vibelign/core/oauth_provider.py"
],
"required_reasons": [
"new_production_file"
],
"deviations": [],
"exempt_reasons": []
}
}
}
필수 필드:
planning.statusplanning.strictplanning.active_plan_idplanning.summaryplanning.changed_files[]planning.required_reasons[]planning.deviations[]planning.exempt_reasons[]
10) 사용자 메시지 규칙
상태별 기본 메시지는 고정한다.
planning_exempt- “현재 변경은 plan-structure 없이 진행 가능한 범위입니다.”
planning_required- “구조 영향 가능성이 높은 변경이 감지되었습니다. 먼저
vib plan-structure를 실행하세요.”
- “구조 영향 가능성이 높은 변경이 감지되었습니다. 먼저
plan_exists_but_deviated- “활성 구조 계획은 존재하지만 실제 변경이 허용 범위를 벗어났습니다.”
fail- “구조 계획 검증에 실패했습니다. 금지 규칙 위반 또는 plan 상태 이상을 확인하세요.”
메시지는 항상 왜 이렇게 판정됐는지를 함께 붙여야 한다.
예:
- 새 production file 감지
- 허용되지 않은 파일 수정 감지
- 허용 anchor 범위 밖 수정 감지
- plan 파일 누락
11) Phase 1 비목표
아래는 Phase 1에서 하지 않는다.
- AST 수준의 정밀 semantic diff
- 함수 단위 책임 추론
- LLM 기반 의도 분류
- Codex/Cursor 등 비-Claude 환경에서의 사전 강제 보장
8. 앵커 집행 시스템과의 관계
이 시스템은 2026-04-09-anchor-enforcement-system.md와 함께 동작합니다.
역할 분리:
구조 계획 시스템 → "어느 파일에 넣을 것인가" 결정
앵커 집행 시스템 → "앵커가 있는가" 보장
함께 동작:
vib plan-structure → 파일 위치 확정
AI 코딩
watch --auto-fix → 앵커 자동 삽입
vib guard → 구조 계획 + 앵커 모두 검증
9. 필요한 변경 파일
| 파일 | 변경 유형 | 내용 |
|---|---|---|
vibelign/commands/vib_plan_structure_cmd.py |
신규 | vib plan-structure 명령어 |
vibelign/core/structure_planner.py |
신규 | 위치 결정 알고리즘 (4단계) |
vibelign/core/meta_paths.py |
수정 | plans 경로 및 관련 메타 경로 중앙화 |
vibelign/mcp/mcp_state_store.py 또는 연계 상태 저장 모듈 |
수정 | 기존 session state와 공존 가능한 planning 상태 저장 |
vibelign/commands/vib_guard_cmd.py |
수정 | 구조 계획 준수 여부 검증 추가 |
vibelign/cli/vib_cli.py |
수정 | 새 명령어 등록 |
vibelign/core/hook_setup.py |
수정 | 통합 PreToolUse 훅 로직 (앵커 집행 시스템과 공유) |
vibelign/commands/vib_claude_hook_cmd.py |
신규 (앵커 집행과 공유) | CLI 래퍼: enable/disable/status |
AGENTS.md |
수정 | 구조 계획 필수 규칙 추가 |
10. 미해결 과제
-
세션 잠금 만료 기준 — 해결됨
Phase 1에서는 이벤트 기반 만료를 사용한다. 시간 기반 만료는 사용하지 않는다.
만료 트리거:
git commit완료 시 → pre-commit hook이 state에서plan_id를 클리어vib plan-structure재실행 시 → 새 plan이 이전 plan을 대체 (단일 활성 plan 정책)vib plan-close명령 (Phase 1 최소 버전 포함)
vib plan-close최소 버전 (Phase 1 포함):- 별도 복잡한 archive/undo 없이
.vibelign/state.json의planning.active=false,plan_id=null세팅 - 이미 inactive 상태면 no-op
- 목적: 작업 취소 / 잘못 잡은 plan / 중도 종료 시 수동 해제 경로 제공
단일 활성 plan 정책 (Phase 1):
- 활성 plan은 항상 1개. 새
vib plan-structure실행 시 이전 plan은 archived 상태로 이동. - 연속 기능 작업 시 기능마다 새로 실행하는 것이 원칙.
기존 session과 공존:
.vibelign/state.json내에planning필드를 별도 추가해 기존 patch/verification session과 독립적으로 관리한다. 충돌 없음.
-
계획이 틀렸을 때 —
vib plan-override설계AI가 계획보다 더 나은 구조를 판단하거나, 계획 자체가 잘못됐을 때를 위한 탈출구.
명령어:
vib plan-override "<이유>"동작:
.vibelign/state.json의planning필드에override: true와override_reason,overridden_at기록- guard는 override 플래그가 있으면 현재 세션을
planning_exempt로 처리 - override는 다음 커밋 완료 또는 새
vib plan-structure실행 시 자동 해제
제약:
- 이유 없이(
"") override 금지 — guard가 빈 reason을 warn 처리 - override 사용 횟수는 guard 출력에 기록 (audit trail)
Phase 1 구현 범위: 상태 저장/조회만. guard 연동은 Ticket 6 이후 추가.
- Claude Code 외 AI 강제 방법
- Cursor, Codex 등에서 plan-structure 호출을 강제할 수단 없음
- 장기적으로 각 AI 플랫폼의 훅 시스템 지원 필요
- 강제 적용 대상 변경 유형 기준
plan-structure는 모든 수정에 강제하지 않고, 구조에 영향을 줄 가능성이 높은 변경에만 요구해야 함- Phase 1 기본 원칙:
- 새 production code file 생성 → 계획 필요
- 기존 app/core/service/mcp/commands 계열에 대한 multi-file 코드 수정 → 계획 필요
- 단일 파일의 소규모 버그 수정, 문서 수정, 테스트 추가/수정, config-only 수정 → 기본 면제
- 강제 여부 판단은 최소한 아래 신호를 함께 보아야 함:
- 파일 유형: source code / test / docs / config
- 파일 수: single-file / multi-file
- 새 파일 여부: 기존 파일 수정인지 신규 생성인지
- 경로 성격: production path인지 보조 path인지
- line count는 보조 신호로만 사용하고, 단독 기준으로 쓰지 않음
- guard와 hook은 최종적으로 다음 세 상태 중 하나를 판정해야 함:
planning_requiredplanning_exemptplan_exists_but_deviated
- 문서에 예시를 함께 고정해야 함:
docs/README.md수정 → 면제tests/test_watch_engine.py테스트 추가 → 면제vibelign/core/auth.py+vibelign/core/oauth_provider.py동시 수정/생성 → 계획 필요vibelign/mcp/mcp_patch_handlers.py한 파일에서 3줄 버그 수정 → 기본 면제
- project_map 최신성 → 해결됨
- watch 엔진이
_refresh_project_map()자동 호출 가능 - 단, watch가 꺼져 있거나 project_map이 아직 없으면 별도 생성/갱신 필요
- watch 엔진이
11. 구현 순서 (implementation plan)
진행 현황 업데이트 (2026-04-10):
- Phase 1 / Ticket 1-3: 구현 완료
vib plan-structure추가.vibelign/plans/*.json저장.vibelign/state.jsonplanning 상태 저장- Phase 2 / Ticket 4: 구현 완료
structure_planner.py규칙 엔진 1차 고도화 완료- representative case(
OAuth 인증 추가,watch 기능 확장,mcp handler 수정)와 candidate narrowing /anchor_index기반 viability / evidence 보강 테스트 반영 완료- Phase 3 / Ticket 5-7: 구현 완료
vib guardplanning 섹션, staged 우선 수집, active plan 비교, strict/non-strict 병합 구현 완료allowed_change_types, config threshold, Step A exemption ordering, mixed change-set deviation, reason-bearing exempt summary까지 Oracle sign-off 완료- Phase 4 / Ticket 8 + Claude PreToolUse 1차: 구현 완료
- git pre-commit 경로에서
vib guard --strict를 실제 차단 경로로 연결 완료 (Oracle sign-off 완료)- Claude
.claude/settings.jsonPreToolUse hook 자동 설치/복구,vib claude-hook enable|disable|status,vib start자동 설치 plumbing 완료 (Oracle sign-off 완료)vib pre-check의 narrowed gating slice 완료: stdin JSON 파싱, disabled/non-source skip,0/2계약, planning-required / plan-deviated / malformed-plan 차단, anchor-missing soft-block (Oracle sign-off 완료)- 단, 이 단계는 full
vib guardparity 아님. diff-aware multi-file 판단, anchor-range/max-lines/change-type 완전 동일성은 후속 강화 과제로 남음- Phase 5: 문서 범위 기준 완료
- regression-hardening slice 1 완료: multi-file production 수정 / strict escalation / forbidden hard fail 직접 고정
- regression-hardening slice 2 완료:
Claude hook disabled,git hook onlymatrix row 직접 고정- regression-hardening slice 3 완료:
test only,config only,단일 파일 소규모 수정row 직접 고정- regression-hardening slice 4 완료:
활성 plan + 허용 경로만 수정,활성 plan + 허용 범위 이탈,broken plan 파일row 직접 고정- regression-hardening slice 5 완료: guard broken-plan payload shape 검증을 precheck 수준에 가깝게 보강하고,
required_new_filesmalformed branch까지 직접 고정- regression-hardening slice 6 완료:
allowed_change_types의import_wiring/registration/config_touchpass branch 직접 고정- regression-hardening slice 7 완료:
anchor_outside_allowed_range/max_lines_added_exceededdirect parity branch 직접 고정- regression-hardening slice 8 완료: guard/precheck state-error branch(
missing_plan_file,invalid_state) exact contract 직접 고정- regression-hardening slice 9 완료:
disallowed_change_type및 일부 singleton deviation assertion-strength 강화- 현재 남은 것은 문서 범위 밖의 선택적 assertion-strength/parity 미세 강화 수준이며, 핵심 matrix row와 주요 runtime 분기는 직접 회귀 고정 완료
Phase 1 — plan JSON 생성 경로 추가
목표: vib plan-structure가 rules 기반 계획 파일을 생성하고 state에 활성 plan을 기록한다.
대상 파일
- 신규:
vibelign/commands/vib_plan_structure_cmd.py - 신규:
vibelign/core/structure_planner.py - 수정:
vibelign/core/meta_paths.py - 수정:
vibelign/cli/vib_cli.py - 수정:
vibelign/mcp/mcp_state_store.py또는 planning 상태 저장 모듈
구현 항목
MetaPaths에 plans 디렉터리 경로 추가vib plan-structure명령 추가- feature 문자열 입력 → 규칙 기반 위치 제안 생성
- 본 문서의 Phase 1 schema대로
.vibelign/plans/<id>.json저장 .vibelign/state.json에 활성 planning session 상태 저장
완료 조건
- 단일 명령으로 plan 파일 생성 가능
- 생성된 JSON이 schema 필수 필드를 모두 가짐
- state에서 활성
plan_id조회 가능
Phase 2 — planner 규칙 엔진 고도화
목표: path/category/anchor/line_count 기반으로 allowed_modifications, required_new_files, forbidden을 안정적으로 산출한다.
대상 파일
vibelign/core/structure_planner.py- 필요 시
vibelign/core/project_map.py,vibelign/core/project_scan.py
구현 항목
- feature 텍스트에서 keyword 추출
- path signal / category / anchor availability 조합으로 후보 파일 압축
- 신규 파일 생성 필요 여부 판단
- forbidden 규칙 객체 생성
messages.summary및 evidence 필드 생성
완료 조건
OAuth 인증 추가,watch 기능 확장,mcp handler 수정같은 대표 케이스에서 일관된 plan 산출- 근거 부족 시 보수적으로 신규 파일 생성 쪽으로 기울어짐
Phase 3 — vib guard planning 판정 추가
현재 상태: 완료. Oracle 최종 리뷰 기준으로 Phase 3 guard slice는 구현 및 검증이 끝났음.
목표: guard가 plan 필요 여부와 plan 준수 여부를 판정한다.
대상 파일
- 수정:
vibelign/commands/vib_guard_cmd.py - 필요 시 수정: guard envelope 생성 관련 코어 모듈
구현 항목
- 변경 집합 수집 (staged 우선, working tree 폴백)
- 파일 유형 / path class 분류
planning_required,planning_exempt,plan_exists_but_deviated,pass,fail상태 판정- plan 파일 로드 및 준수 비교
- JSON/text 결과에 planning 섹션 추가
완료 조건
- 본 문서의 guard spec 예시와 같은 envelope 출력
- strict / non-strict 동작 차이 반영
- plan 없는 구조 변경은 감지 가능
Phase 4 — Claude / git enforcement 연결
현재 상태: 완료 (현재 범위 기준, Oracle sign-off 완료).
- git pre-commit enforcement slice 완료
- Claude hook plumbing slice 완료
vib pre-checknarrowed gating slice 완료- 남은 것은 Phase 4의 필수 범위가 아니라, Claude 경로를 git guard 수준으로 더 가깝게 만드는 후속 강화 작업임
목표: Claude와 git 경로에서 planning 판정을 실제 차단/경고로 연결한다.
대상 파일
- 수정:
vibelign/core/git_hooks.py - 수정 또는 연계:
vibelign/core/hook_setup.py - 필요 시 수정: 관련 CLI install/setup 진입점
- 신규/수정: Claude hook enable/disable/status 진입점
구현 항목
- git pre-commit 경로에서
vib guard --strict결과 반영 - Claude 프로젝트 감지 시 hook 자동 설치/복구
- Claude PreToolUse에서 planning 상태 확인 후 사전 차단 또는 경고
- Claude hook enable/disable/status 상태 관리
- 기존 anchor enforcement 흐름과 충돌하지 않도록 통합
완료 조건
- git 사용자: 구조 계획 누락/이탈 시 커밋 차단 가능
- Claude 사용자: hook은 수동 JSON 편집 없이 사용 가능
- Claude 사용자: plan 없는 구조 변경에 대해 on/off 상태에 맞는 동작 수행 가능
Phase 5 — 테스트 및 회귀 고정
목표: planner/guard/enforcement 규칙이 회귀 없이 유지되도록 테스트를 추가한다.
대상 파일
- 신규 테스트:
tests/test_structure_planner.py - 신규 테스트:
tests/test_guard_planning.py - 필요 시 기존
tests/test_mcp_patch_session.py,tests/test_watch_engine.py보강
구현 항목
- exempt 케이스 테스트
- planning_required 케이스 테스트
- plan_exists_but_deviated 케이스 테스트
- strict/non-strict 차이 테스트
- plan 파일 누락/파손 테스트
완료 조건
- 대표 경로별 판정이 테스트로 고정됨
- plan/state 파손 시 안전 실패 동작 검증됨
구현 전 테스트 매트릭스 (우선 고정)
| 케이스 | 입력 상태 | 기대 결과 |
|---|---|---|
| docs only 수정 | docs/README.md 수정 |
planning_exempt |
| test only 수정 | tests/test_watch_engine.py 수정 |
planning_exempt |
| config only 수정 | .claude/settings.json 수정 |
planning_exempt |
| 단일 파일 소규모 수정 | production 파일 1개, threshold 이하, 새 파일 아님 | planning_exempt 또는 warn |
| 신규 production 파일 생성 | vibelign/core/foo.py 신규 |
planning_required |
| multi-file production 수정 | core/ 2개 이상 수정 |
planning_required |
| 활성 plan + 허용 경로만 수정 | allowed_modifications 범위 내 |
pass |
| 활성 plan + 허용 범위 이탈 | 허용되지 않은 파일/anchor 수정 | plan_exists_but_deviated |
| forbidden 위반 | 금지 경로 수정 | fail |
| broken plan 파일 | JSON 파손 또는 필수 필드 누락 | fail |
| Claude hook disabled | hook 설치됨 + claude_hook_enabled=false |
Claude 컨텍스트 non-strict |
| git hook only | pre-commit hook 설치됨, Claude disabled | git strict / Claude non-strict |
구현 시작 전에 이 표를 테스트 케이스 이름으로 바로 옮기면, 단계별 구현에서 방향이 흔들리지 않는다.
개발 착수용 작업 티켓 분해
Ticket 1 — planning state / meta path 뼈대 추가
목표
.vibelign/plans/경로와 planning state 저장소를 만든다.
핵심 작업
MetaPaths에 plans 경로 추가.vibelign/state.json에plan_id, planning session 메타 저장/조회 헬퍼 추가
완료 조건
- state에서 활성
plan_id를 읽고 쓸 수 있다 - plans 디렉터리를 안전하게 생성할 수 있다
Ticket 2 — vib plan-structure CLI 추가
목표
- 사용자가 feature 문자열로 구조 계획을 생성할 수 있게 한다.
핵심 작업
vib_plan_structure_cmd.py생성vib_cli.py에 명령 등록- planner 호출 후 plan JSON 저장
완료 조건
vib plan-structure "OAuth 인증 추가"실행 시 plan 파일이 생성된다
Ticket 3 — plan JSON schema 고정
목표
- guard가 직접 소비할 수 있는 plan JSON 형식을 확정한다.
핵심 작업
schema_version,mode,scope,messages필드 반영forbidden을 객체 배열로 저장allowed_change_types,required_reasons필드 반영
완료 조건
- 생성되는 plan이 본 문서 schema 필수 필드를 모두 포함한다
구현 순서 메모: planner 구현 전에 schema draft를 먼저 고정해야, Ticket 4에서 JSON 구조를 다시 뜯는 리스크를 줄일 수 있다.
Ticket 4 — structure_planner.py 1차 규칙 엔진 구현
목표
- rules 기반으로 candidate file, allowed modifications, required new files, forbidden 규칙을 생성한다.
핵심 작업
- keyword 추출
- category/path/anchor/line_count 기반 후보 압축
- 신규 파일 생성 필요 여부 판단
messages.summary,evidence.required_reasons생성
완료 조건
- 대표 입력 3종 이상에서 일관된 plan이 생성된다
Ticket 5 — vib guard에 planning 판정 추가
목표
- guard가 현재 변경이 exempt인지, planning required인지, plan deviation인지 판정한다.
핵심 작업
- staged/working tree 변경 수집
- docs/tests/config/source 분류
planning_required,planning_exempt,plan_exists_but_deviated,pass,fail계산
완료 조건
- JSON/text 결과에 planning 섹션이 추가된다
Ticket 6 — plan 준수 비교 로직 추가
목표
- 실제 변경이 plan 범위를 지키는지 비교한다.
핵심 작업
- 신규 파일 ↔
required_new_files비교 - 기존 파일 수정 ↔
allowed_modifications비교 - anchor /
max_lines_added/ forbidden 위반 감지
완료 조건
- plan deviation과 hard fail을 구분할 수 있다
Ticket 7 — strict / non-strict 정책 연결
목표
- 같은 planning 결과가 strict 여부에 따라 다르게 동작하게 한다.
핵심 작업
- non-strict: warn 중심
- strict:
planning_required,plan_exists_but_deviated를 fail 처리
완료 조건
- strict / non-strict 동작 차이가 테스트 가능한 형태로 드러난다
Ticket 8 — git pre-commit 연동
목표
- git commit 직전 planning 위반을 차단한다.
핵심 작업
- 기존
git_hooks.py흐름에vib guard --strict연동 - anchor enforcement / secrets hook과 충돌 없이 통합
완료 조건
- plan 없는 구조 변경이 pre-commit에서 차단된다
Ticket 9 — Claude PreToolUse 연동
목표
- Claude 환경에서 hook 자동 설치 + on/off 제어 + 사전 차단/경고를 구현한다.
핵심 작업
- Claude 프로젝트 감지 시 project-local hook merge-safe 설치
enable/disable/status상태 저장 및 조회- planning state 조회
- PreToolUse 훅에서
planning_required시 on/off 상태에 따라 차단/경고
완료 조건
- Claude Write/Edit 전에 planning 상태 기반 판정이 가능하다
- 코알못도 수동 JSON 편집 없이 Claude 보호 기능을 켜고 끌 수 있다
Ticket 10 — 테스트 세트 추가
목표
- planner / guard / enforcement 규칙을 회귀 테스트로 고정한다.
핵심 작업
- exempt 케이스
- planning_required 케이스
- plan_exists_but_deviated 케이스
- strict/non-strict 차이
- plan missing / broken plan 케이스
완료 조건
- 핵심 판정이 테스트로 고정되고 회귀가 잡힌다
권장 구현 순서
Ticket 1 → 2 → 3 → 4 → 5 → 6 → 7 → 10 → 8 → 9
이유: plan/state/schema를 먼저 고정해야 guard를 구현할 수 있고, guard 판정이 안정화되어야 hook enforcement를 붙여도 디버깅 비용이 폭증하지 않는다.
이 문서는 현재 구현 완료 상태를 반영한 기록 문서입니다. 남은 항목은 문서 범위 밖의 선택적 고도화입니다.