chore(rebar): Pier_T_rebar 작업 폴더 초기 구성 및 외부 의존 파일 통합

- Code\rebar_pipeline, review_pipeline, pier-program을 정션에서 실제 폴더로 전환
- Code\rhino_mcp 및 CLAUDE_rhino배경.md 추가, .mcp.json은 PYTHONPATH로 새 위치 사용
- pier-program 내부 .git 제거(이력은 backup\pier-program_20261028.bundle에 보관)
- worktree 가이드 반영(CLAUDE.local.md, HANDOFF.md)
- D:\Rhino-MCP 경로 참조를 새 위치로 치환

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ahnyongjooandClaude Sonnet 5.5 committed 2026-10-28 11:20:18 +09:00
commit 964a841de1
3978 files changed
+58013356

No files matched your search

+283
View File
@@ -0,0 +1,283 @@
import os
import json
import datetime
import re
# ==========================================
# 1. Constants & Configuration (Ported from lib/core & lib/pdca)
# ==========================================
PDCA_PHASES = {
'PLAN': {'order': 1, 'name': 'Plan', 'icon': '📋'},
'DESIGN': {'order': 2, 'name': 'Design', 'icon': '📐'},
'DO': {'order': 3, 'name': 'Do', 'icon': '🔨'},
'CHECK': {'order': 4, 'name': 'Check', 'icon': '🔍'},
'ACT': {'order': 5, 'name': 'Act', 'icon': '🔄'},
'REPORT': {'order': 6, 'name': 'Report', 'icon': '📊'}
}
LEVEL_PHASE_MAP = {
"Starter": {
"required": ["PLAN", "DO", "CHECK"],
"optional": ["DESIGN"],
"skip": ["PHASE-1", "PHASE-2", "PHASE-4", "PHASE-7", "PHASE-9"]
},
"Dynamic": {
"required": ["PLAN", "DESIGN", "DO", "CHECK", "REPORT"],
"optional": ["PHASE-3", "PHASE-5", "PHASE-6"],
"skip": ["PHASE-9"]
},
"Enterprise": {
"required": ["PLAN", "DESIGN", "DO", "CHECK", "REPORT",
"PHASE-1", "PHASE-2", "PHASE-3", "PHASE-4",
"PHASE-5", "PHASE-6", "PHASE-7", "PHASE-8", "PHASE-9"],
"optional": [],
"skip": []
}
}
TEAM_STRATEGIES = {
"Starter": None,
"Dynamic": {
"teammates": 3,
"cto_agent": "cto-lead",
"roles": [
{"name": "developer", "agents": ["bkend-expert"], "phases": ["DO", "ACT"]},
{"name": "frontend", "agents": ["frontend-architect"], "phases": ["DESIGN", "DO"]},
{"name": "qa", "agents": ["qa-monitor", "gap-detector"], "phases": ["CHECK"]}
]
},
"Enterprise": {
"teammates": 5,
"cto_agent": "cto-lead",
"roles": [
{"name": "architect", "agents": ["enterprise-expert", "infra-architect"], "phases": ["DESIGN"]},
{"name": "developer", "agents": ["bkend-expert", "frontend-architect"], "phases": ["DO", "ACT"]},
{"name": "qa", "agents": ["qa-strategist", "qa-monitor", "gap-detector"], "phases": ["CHECK"]},
{"name": "reviewer", "agents": ["code-analyzer", "design-validator"], "phases": ["CHECK", "ACT"]},
{"name": "security", "agents": ["security-architect"], "phases": ["DESIGN", "CHECK"]}
]
}
}
# ==========================================
# 2. State Engine Logic
# ==========================================
class ContextManager:
"""
Manages global state, feature context, and project level detection.
Ported from lib/task/context.js & lib/pdca/level.js
"""
def __init__(self, state_file_path):
self.state_file_path = state_file_path
self.state = self._load_state()
def _load_state(self):
if not os.path.exists(self.state_file_path):
return {
"project_name": "Antigravity Project",
"project_level": "Dynamic", # Default
"current_feature": None,
"features": {},
"team_config": {
"enabled": False,
"max_teammates": 4
},
"last_bootup": None
}
try:
with open(self.state_file_path, 'r', encoding='utf-8') as f:
return json.load(f)
except json.JSONDecodeError:
return self._load_state() # Recursive retry with default if corrupt (handled by external reset usually)
def _save_state(self):
with open(self.state_file_path, 'w', encoding='utf-8') as f:
json.dump(self.state, f, indent=2, ensure_ascii=False)
def detect_project_level(self, project_root="."):
"""
Ported from lib/pdca/level.js: detectLevel()
"""
try:
files = os.listdir(project_root)
files_str = " ".join(files).lower()
# Enterprise Markers
if any(m in files_str for m in ['kubernetes', 'k8s', 'terraform', 'microservices', 'docker-compose']):
self.state['project_level'] = "Enterprise"
return "Enterprise"
# Dynamic Markers
if any(m in files for m in ['package.json', 'requirements.txt', 'go.mod', 'Cargo.toml', 'pom.xml']):
self.state['project_level'] = "Dynamic"
return "Dynamic"
except Exception:
pass
self.state['project_level'] = "Starter"
return "Starter"
def set_active_feature(self, feature_name):
self.state['current_feature'] = feature_name
if feature_name and feature_name not in self.state['features']:
self.state['features'][feature_name] = {
"phase": "PLAN",
"match_rate": 0,
"history": []
}
self._save_state()
def get_active_feature(self):
return self.state.get('current_feature')
def get_feature_status(self, feature_name):
return self.state.get('features', {}).get(feature_name)
class PDCAStatus:
"""
Manages Phase Transitions and Deliverable Checks.
Ported from lib/pdca/phase.js
"""
def __init__(self, context_manager):
self.ctx = context_manager
def validate_transition(self, feature_name, to_phase):
"""
Ported from lib/pdca/phase.js: validatePdcaTransition()
NOW INCLUDES LEVEL-BASED VALIDATION
"""
feature = self.ctx.get_feature_status(feature_name)
if not feature:
return {"valid": True, "reason": "New feature"}
from_phase = feature.get('phase', 'PLAN').upper()
to_phase = to_phase.upper()
from_order = PDCA_PHASES.get(from_phase, {}).get('order', 0)
to_order = PDCA_PHASES.get(to_phase, {}).get('order', 0)
# Allow going back
if to_order < from_order:
return {"valid": True, "reason": "Returning to earlier phase"}
# Check Level Requirements
level = self.ctx.state.get("project_level", "Dynamic")
level_config = LEVEL_PHASE_MAP.get(level, LEVEL_PHASE_MAP["Dynamic"])
# Iterate phases between from_phase and to_phase
# e.g. PLAN(1) -> DO(3). Check if DESIGN(2) is required.
for i in range(from_order + 1, to_order):
intermediate_phase_name = ""
for name, info in PDCA_PHASES.items():
if info['order'] == i:
intermediate_phase_name = name
break
if intermediate_phase_name and intermediate_phase_name in level_config['required']:
return {"valid": False, "reason": f"Cannot skip required phase: {intermediate_phase_name} ({level} Level)"}
# Cannot skip more than 1 phase generally (sanity check)
if to_order > from_order + 1:
# But allow if intermediate is NOT required
# The loop above handles the "Required" check.
# If we are here, it means intermediate phases were optional or skipped.
pass
return {"valid": True, "reason": "Transition allowed"}
def update_phase(self, feature_name, phase, match_rate=None):
phase = phase.upper() # Normalize
# Validate first
validation = self.validate_transition(feature_name, phase)
if not validation['valid']:
print(f"Warning: Invalid transition - {validation['reason']}")
# We enforce it anyway for now as agent override, but log it
feature = self.ctx.get_feature_status(feature_name)
if feature:
feature['phase'] = phase
if match_rate is not None:
feature['match_rate'] = match_rate
entry = {
"timestamp": datetime.datetime.now().isoformat(),
"action": "phase_update",
"phase": phase,
"match_rate": match_rate
}
feature['history'].append(entry)
self.ctx._save_state()
class Guardrails:
"""
Implements safety checks like Loop Detection.
Ported from hmcmkit (Hybrid JS -> Python approach)
"""
def __init__(self, context_manager):
self.ctx = context_manager
def check_loop(self, feature_name):
feature = self.ctx.get_feature_status(feature_name)
if not feature or 'history' not in feature:
return {"safe": True}
recent = feature['history'][-10:] if len(feature['history']) >= 10 else feature['history']
check_act_count = sum(1 for h in recent if h.get('phase', '') in ['CHECK', 'ACT'])
if check_act_count >= 8: # 4 cycles of check-act
return {"safe": False, "reason": "무한 루프 감지: CHECK/ACT 반복이 4회를 초과했습니다. 자동 수정을 멈추고 사용자에게 보고하세요."}
return {"safe": True}
class TeamCoordinator:
"""
Manages Team Strategy and Roles.
Ported from lib/team/strategy.js & lib/team/coordinator.js
"""
def __init__(self, context_manager):
self.ctx = context_manager
def get_team_strategy(self):
level = self.ctx.state.get("project_level", "Dynamic")
return TEAM_STRATEGIES.get(level, TEAM_STRATEGIES["Dynamic"])
def suggest_team_mode(self, user_message):
"""
Ported from lib/team/coordinator.js: suggestTeamMode()
"""
level = self.ctx.state.get("project_level", "Dynamic")
if level == "Starter":
return {"suggest": False, "reason": "Starter level does not support teams"}
# Logic: Message > 1000 chars or Keyword trigger
if len(user_message) >= 1000:
return {"suggest": True, "reason": "Long message detected (Major Feature)"}
keywords = ["team", "project lead", "cto", "role", "assign"]
if any(k in user_message.lower() for k in keywords):
return {"suggest": True, "reason": "Team keywords detected"}
return {"suggest": False}
def get_roles_for_phase(self, phase):
strategy = self.get_team_strategy()
if not strategy: return []
phase = phase.upper()
active_roles = []
for role in strategy['roles']:
if phase in role['phases']:
active_roles.append(role)
return active_roles
if __name__ == "__main__":
# Test Suite
# mgr = ContextManager(".hmcmkit/state.json")
pass