- 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>
93 lines
3.3 KiB
Python
93 lines
3.3 KiB
Python
import re
|
|
import sys
|
|
import json
|
|
|
|
def calculate_ambiguity_score(user_request, context={}):
|
|
score = 0
|
|
factors = []
|
|
|
|
# Factor 1: No file path (higher ambiguity)
|
|
file_path_pattern = r'(\/[\w.-]+\/[\w.-]+)|([A-Z]:\\[\w.-]+\\[\w.-]+)|(\.\/[\w.-]+)|(\.(js|ts|py|go|rs|java|tsx|jsx|vue|svelte|md|json|yaml|yml)$)'
|
|
if not re.search(file_path_pattern, user_request, re.IGNORECASE):
|
|
factors.append('no_file_path')
|
|
score += 0.15
|
|
|
|
# Factor 2: No technical terms
|
|
tech_terms = [
|
|
'api', 'database', 'server', 'client', 'component', 'module',
|
|
'function', 'class', 'interface', 'type', 'schema', 'endpoint',
|
|
'authentication', 'authorization', 'middleware', 'controller',
|
|
'service', 'repository', 'model', 'view', 'hook', 'context'
|
|
]
|
|
if not any(term in user_request.lower() for term in tech_terms):
|
|
factors.append('no_technical_terms')
|
|
score += 0.1
|
|
|
|
# Factor 3: No specific nouns (PascalCase or camelCase)
|
|
if not re.search(r'("[^"]+")|(\'[^\']+\')|([A-Z][a-z]+[A-Z][a-z]+)|([a-z]+[A-Z][a-z]+)', user_request):
|
|
factors.append('no_specific_nouns')
|
|
score += 0.15
|
|
|
|
# Factor 4: No scope definition
|
|
scope_patterns = [
|
|
r'only|just|specifically|exactly',
|
|
r'all|every|entire|whole',
|
|
r'from\s+\w+\s+to\s+\w+',
|
|
r'in\s+the\s+\w+\s+(?:file|folder|directory|module)'
|
|
]
|
|
if not any(re.search(p, user_request, re.IGNORECASE) for p in scope_patterns):
|
|
factors.append('no_scope')
|
|
score += 0.1
|
|
|
|
# Factor 5: Multiple interpretations
|
|
ambiguous_patterns = [
|
|
r'maybe|perhaps|or|either',
|
|
r'it|this|that|those|these',
|
|
r'stuff|things|something',
|
|
r'fix|update|change|modify'
|
|
]
|
|
pronoun_count = len(re.findall(r'\b(it|this|that)\b', user_request, re.IGNORECASE))
|
|
if pronoun_count >= 2 or any(re.search(p, user_request, re.IGNORECASE) for p in ambiguous_patterns):
|
|
factors.append('multiple_interpretations')
|
|
score += 0.2
|
|
|
|
# Factor 6: Short request
|
|
if len(user_request) < 30:
|
|
factors.append('short_request')
|
|
score += 0.15
|
|
|
|
# Factor 7: Context Conflict (New in v2)
|
|
# Check if request contradicts current phase
|
|
current_phase = context.get('current_feature_phase', 'PLAN')
|
|
phase_keywords = {
|
|
'PLAN': ['implement', 'code', 'build', 'deploy'],
|
|
'DESIGN': ['deploy', 'test', 'release'],
|
|
'DO': ['plan', 'design', 'architecture']
|
|
}
|
|
conflict_keywords = phase_keywords.get(current_phase, [])
|
|
for keyword in conflict_keywords:
|
|
if keyword in user_request.lower():
|
|
factors.append(f'context_conflict_with_{current_phase}')
|
|
score += 0.15
|
|
break
|
|
|
|
score = min(1.0, max(0.0, score))
|
|
return {"score": score, "factors": factors}
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) < 2:
|
|
print(json.dumps({"error": "No request provided"}))
|
|
sys.exit(1)
|
|
|
|
request = sys.argv[1]
|
|
# Simulate context from arg 2 if present
|
|
context = {}
|
|
if len(sys.argv) > 2:
|
|
try:
|
|
context = json.loads(sys.argv[2])
|
|
except:
|
|
pass
|
|
|
|
result = calculate_ambiguity_score(request, context)
|
|
print(json.dumps(result, indent=2))
|