feat(group-a): Foundation for Fairthon 75-Technique system (#224, #225, #226, #227)#256
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. Walkthrough기법 정의 75건의 한국어→영어 전환, 기법 로딩에서 소스 기반 필터 제거(모든 기법 GitHub으로 처리), EvaluationMode 통일 및 확장(SIX_HATS → SIX_SOMMELIERS, GRAND_TASTING 추가, FULL_TECHNIQUES 유지), BMAD 17항목 평가 프레임워크 추가, 관련 API/서비스/테스트 및 프론트엔드 타입 업데이트가 포함됩니다. Changes
Sequence Diagram(s)sequenceDiagram
rect rgba(200,200,255,0.5)
participant Client
end
rect rgba(200,255,200,0.5)
participant API as "API /routes/graph.py"
participant Auth as "Auth/DB"
end
rect rgba(255,200,200,0.5)
participant GraphFactory as "graph_factory"
participant Builder as "services/graph_builder"
participant Registry as "techniques/registry"
end
Client->>API: 요청 (graph 요청, evaluation_id / evaluation_mode)
API->>Auth: 소유권/권한 확인
Auth-->>API: 권한 결과
API->>Registry: 필요시 기법 목록 요청 (get_all_techniques / has_readme_content)
Registry-->>API: 기법 목록 / README 여부
API->>GraphFactory: 모드 판별( evaluation_mode 우선 )
GraphFactory-->>API: 사용 가능한 모드, 선택된 모드
API->>Builder: topology 생성 요청 (mode → build_six_sommeliers_topology / full_techniques)
Builder-->>API: ReactFlowGraph 응답
API-->>Client: 그래프 페이로드 반환
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Possibly related PRs
Suggested labels
요약종합 분석Walkthrough이 PR은 기법 시스템의 대규모 현대화와 통일을 구현합니다. 75개 기법의 YAML을 한국어에서 영어로 전환하고, 소스별 필터링을 제거하여 모든 기법을 GitHub 데이터로 처리하게 변경합니다. 평가 모드를 통일하고(SIX_HATS → SIX_SOMMELIERS, GRAND_TASTING, FULL_TECHNIQUES 추가), BMAD 17항목 평가 프레임워크를 도입합니다. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello @ComBba, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request lays the groundwork for a comprehensive evaluation system by integrating and refining core components. It streamlines how evaluation techniques are managed and categorized, standardizes the modes of evaluation, and introduces a detailed, structured scoring rubric. These changes collectively enhance the system's flexibility, clarity, and robustness, preparing it for future expansions and more sophisticated evaluation processes. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a new 'BMAD 17-item evaluation canon' by adding bmad_items.py which defines 17 evaluation items across 4 categories (A, B, C, D) with detailed rubrics and scoring. A significant refactoring renames the 'Six Hats' evaluation mode to 'Six Sommeliers' and introduces a new 'Grand Tasting' mode, updating related imports, function names, docstrings, and model definitions across graph.py, graph_factory.py, models/graph.py, and graph_builder.py. The EvaluationMode enum is now centralized in app.models.graph and re-exported. The OPENAI_API_KEY is added to the backend configuration. Furthermore, the technique loading mechanism has been simplified by removing source-based filtering (determine_available_inputs, filter_techniques) and instead loading all 75 techniques directly. The TechniqueDefinition schema is updated to remove the name_ko field and rename input_source to fairthon_source, preserving original YAML values. A new utility function has_readme_content is added to check for README presence. Test files have been updated to reflect these changes, including new tests for BMAD items and adjustments to graph-related tests. A review comment suggests adding a comment to the else block in _determine_mode and similar logic in get_graph_structure and get_graph_execution for clarity regarding which modes are handled.
| @@ -133,7 +135,7 @@ async def get_graph( | |||
| if mode == EvaluationMode.FULL_TECHNIQUES: | |||
| graph = build_full_techniques_topology() | |||
| else: | |||
There was a problem hiding this comment.
Actionable comments posted: 3
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (9)
backend/app/techniques/definitions/balance/ecosystem-thinking.yaml (1)
68-68:⚠️ Potential issue | 🟠 Major
requiredSources키는fairthon_source로 변경해야 합니다.PR 목표에 따라 source 정보는 필터링에 쓰지 않고
fairthon_source로 보존해야 합니다. 현재 키는 새로운 로더/스키마와 불일치할 수 있습니다.🔧 제안 수정
-requiredSources: either +fairthon_source: eitherbackend/app/techniques/definitions/body/pre-mortem.yaml (1)
16-61:⚠️ Potential issue | 🟡 Minor프롬프트가 outputSchema 필드를 직접 요청하지 않아 결과 누락 위험
outputSchema에assumedFailure가 있는데 프롬프트는 이를 명시적으로 수집하지 않습니다. 모델 출력이 누락되거나 불안정해질 수 있으니 프롬프트에 필드별 출력 지시를 추가하세요.🛠️ 제안 수정안
-promptTemplate: '## Pre-mortem Analysis +promptTemplate: '## Pre-mortem Analysis @@ - Analyze if the project performed a Pre-mortem analysis. + Analyze if the project performed a Pre-mortem analysis. Provide the following outputs explicitly: + - assumedFailure: the assumed failure statement + - failureCauses: bullet list of causes + - warningSignals: bullet list of early warning signs + - preventionStrategies: bullet list of prevention actions + - reasoning: brief rationale for the scorebackend/app/techniques/definitions/palate/reversal-inversion.yaml (1)
54-59:⚠️ Potential issue | 🟠 MajoroutputSchema의
reversalEvidence필드는 두 개의 구분되는 분석 관점을 포함promptTemplate의 1번(관점 전환)과 2번(역발상 적용)이 모두
reversalEvidence필드에 매핑되어 있으나, 다른 palate 기법들(scamper, first-principles-thinking, provocation-technique 등)은 각 분석 관점마다 개별 필드를 생성합니다. 예를 들어 scamper.yaml은 7가지 SCAMPER 기법 각각에 대해 별도의 Evidence 필드(substituteEvidence, combineEvidence, adaptEvidence 등)를 가지고 있습니다.일관성을 위해 두 관점을 분리하는 것을 권장합니다:
perspectiveReversalEvidence(또는 유사 명칭): 반대 방향에서 문제에 접근한 증거reverseThinkingEvidence(또는 유사 명칭): "반대로 하면 어떻게 될까?" 질문 근거backend/app/services/evaluation_service.py (1)
190-193:⚠️ Potential issue | 🟡 Minor에러 메시지에
full_techniques모드가 누락되었습니다.
is_valid_mode()를 통해 유효성 검증은 올바르게 동작하지만, 에러 메시지가six_sommeliers와grand_tasting만 표시하고full_techniques를 누락하고 있습니다.EvaluationModeenum에서 동적으로 생성하는 것이 좋습니다.🔧 동적 에러 메시지 제안
- raise CorkedError( - f"Invalid evaluation mode: {evaluation_mode}. " - "Must be 'six_sommeliers' or 'grand_tasting'" - ) + from app.graph.graph_factory import list_available_modes + raise CorkedError( + f"Invalid evaluation mode: {evaluation_mode}. " + f"Available modes: {list_available_modes()}" + )backend/tests/test_techniques_loader.py (1)
1-26:⚠️ Potential issue | 🟡 Minor
load_techniques의 정상 동작 경로(happy path)에 대한 테스트가 누락되었습니다.현재 테스트는 YAML 파싱 오류와 스키마 검증 실패 케이스만 다루고 있습니다. 유효한 기법 정의를 포함한 YAML 파일이 정상적으로 로드되는 경우를 테스트하는 케이스를 추가하세요.
backend/app/models/graph.py (1)
227-229:⚠️ Potential issue | 🟡 Minor
hat_typeField description에 "Six Hats" 레거시 명칭이 남아 있습니다.Line 209의 클래스 docstring에는 "Six Sommeliers mode"로 업데이트되었지만, Line 228의
Field(description=...)에는 여전히"Optional hat type for Six Hats mode"로 되어 있습니다. 일관성을 위해 수정이 필요합니다.✏️ 수정 제안
hat_type: Optional[str] = Field( - default=None, description="Optional hat type for Six Hats mode" + default=None, description="Optional hat type for Six Sommeliers mode" )backend/tests/test_graph_api.py (1)
52-79:⚠️ Potential issue | 🟡 Minor
mock_evaluation_six_sommeliers및mock_evaluation_full_techniquesfixture 제거 필요두 fixture가 정의되어 있지만 이 테스트 파일 내 어떤 테스트 함수의 매개변수로도 사용되지 않습니다. 미사용 코드이므로 제거하세요.
backend/app/api/routes/graph.py (2)
159-159:⚠️ Potential issue | 🔴 Critical
_check_ownership호출 시evaluation_id인자 누락 — 런타임 TypeError 발생
_check_ownership의 시그니처는(evaluation, user, evaluation_id)3개 인자를 요구하지만, Line 159에서 2개 인자만 전달하고 있습니다.get_graph_structure엔드포인트 호출 시TypeError: _check_ownership() missing 1 required positional argument: 'evaluation_id'가 발생합니다.Line 185의
get_graph_execution엔드포인트에서도 동일한 문제가 있습니다.🐛 수정 제안
Line 159:
- _check_ownership(evaluation, user) + _check_ownership(evaluation, user, evaluation_id)Line 185:
- _check_ownership(evaluation, user) + _check_ownership(evaluation, user, evaluation_id)
132-141:⚠️ Potential issue | 🔴 Critical
GRAND_TASTING모드의 토폴로지 구현 누락
_determine_mode에서GRAND_TASTING을 별도 모드로 인식하지만,get_graph(Line 135-138),get_graph_structure(Line 162-165),get_graph_execution(Line 188-191)의 그래프 빌딩 로직에서는FULL_TECHNIQUES아닌 모든 모드가build_six_sommeliers_topology()로 처리됩니다.결과적으로
GRAND_TASTING평가는SIX_SOMMELIERS토폴로지를 반환받게 되어 시각화가 잘못됩니다.create_grand_tasting_graph는graph_factory.py에 등록되어 있지만, 토폴로지 계층에서 대응하는build_grand_tasting_topology()함수가 없어 불일치가 발생합니다.세 엔드포인트 모두에서
GRAND_TASTING경우를 명시적으로 처리하거나build_grand_tasting_topology()함수를 구현해야 합니다.
🤖 Fix all issues with AI agents
In `@backend/app/techniques/definitions/body/anti-solution.yaml`:
- Line 43: 파일들에서 반복된 문법 오류 "1 points" 대신 단수형 "1 point"를 사용해야 합니다;
backend/app/techniques/definitions/body/anti-solution.yaml 에서 보이는 "- 1 points:"
같은 모든 YAML 항목을 프로젝트 전체(약 80개 파일)에서 찾아 "- 1 points" 또는 "1 points:" 등 모든 변형을 "- 1
point" 또는 "1 point:"로 일괄 교체하고, 변경 후 YAML 파서(lint)를 돌려 문법 오류가 없는지 확인하세요; 검색/치환은
파일 확장자 .yaml/.yml에 한정하고 "points"가 실제 복수 수를 의미하는 다른 문맥을 건드리지 않도록 패턴 매칭(예: "\b1
points\b" 또는 "- 1 points:")으로 제한하세요.
In `@backend/app/techniques/definitions/body/swot-analysis.yaml`:
- Line 55: Replace the incorrect plural token "1 points" with the singular "1
point" wherever it appears (e.g., the line "1 points: No SWOT analysis" in
swot-analysis.yaml); perform a targeted search-and-replace for the exact token
"1 points" across the affected YAML files in the vintage, palate, finish,
terroir, body, balance, aroma, cellar directories and the swot-analysis files so
that only the "1" cases change (leave "2 points" and other plurals intact).
In `@backend/app/techniques/definitions/palate/cross-pollination.yaml`:
- Around line 35-36: Multiple technique definition YAMLs contain the incorrect
plural "1 points"; locate every occurrence of the YAML list entry pattern "- 1
points:" (e.g., in technique definition files) and change it to the singular "-
1 point:" so the score uses correct grammar; ensure you update every file where
the exact string "1 points" appears (preserving surrounding spacing and
punctuation) and run a quick grep to confirm no remaining instances.
🟡 Minor comments (41)
backend/app/techniques/definitions/balance/ecosystem-thinking.yaml-33-44 (1)
33-44:⚠️ Potential issue | 🟡 Minor점수 설명 문구의 문법 오류.
“1 points” → “1 point”로 수정하세요.
✏️ 제안 수정
- - 1 points: No ecosystem consideration + - 1 point: No ecosystem considerationbackend/app/techniques/definitions/vintage/scenario-planning.yaml-48-48 (1)
48-48:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이 올바릅니다.
✏️ 수정 제안
- - 1 points: No preparation for future + - 1 point: No preparation for futurebackend/app/techniques/definitions/aroma/five-whys.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형에는 "point"를 사용해야 합니다.
📝 수정 제안
- - 1 points: Covered only superficial symptoms + - 1 point: Covered only superficial symptomsbackend/app/techniques/definitions/palate/design-thinking.yaml-44-46 (1)
44-46:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
다른 점수 기준에서는 복수형("5 points", "4 points" 등)이 맞지만, 1은 단수형을 사용해야 합니다.
🔧 수정 제안
- - 1 points: No application of Design Thinking + - 1 point: No application of Design Thinkingbackend/app/techniques/definitions/palate/concept-blending.yaml-41-41 (1)
41-41:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이어야 합니다.
✏️ 수정 제안
- - 1 points: Single concept applied, no blending + - 1 point: Single concept applied, no blendingbackend/app/techniques/definitions/balance/resource-constraints.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor사소한 문법 오류: "1 points" → "1 point"
단수형에 맞게 수정이 필요합니다. 다른 라인(35-41)의 복수형 "points"는 올바르지만, 1은 단수로 표기해야 합니다.
📝 수정 제안
- - 1 points: Resource constraints ignored + - 1 point: Resource constraints ignoredbackend/app/techniques/definitions/body/pre-mortem.yaml-33-54 (1)
33-54:⚠️ Potential issue | 🟡 Minor채점 문구 불일치 및 문법 오류
프롬프트의 5점 기준에 “early warning system”이 포함되지만
scoring.criteria.5에는 빠져 있고, “1 points”는 문법상 오타입니다. 문구를 일치시키고 오타를 수정하세요.✏️ 제안 수정안
- - 5 points: Complete pre-mortem, early warning system, prevention strategy + - 5 points: Complete pre-mortem, early warning system, prevention strategy @@ - - 1 points: No pre-mortem + - 1 point: No pre-mortem @@ - 5: Complete pre-mortem, prevention strategy + 5: Complete pre-mortem, early warning system, prevention strategybackend/app/techniques/definitions/balance/porters-five-forces.yaml-44-46 (1)
44-46:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
Line 46에서
1 points는 문법적으로 올바르지 않습니다. 단수형인1 point로 수정해야 합니다.✏️ 수정 제안
- - 1 points: No competition analysis + - 1 point: No competition analysisbackend/app/techniques/definitions/vintage/value-mapping.yaml-48-48 (1)
48-48:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이어야 합니다.
✏️ 수정 제안
- - 1 points: Value proposition unclear or irrelevant to needs + - 1 point: Value proposition unclear or irrelevant to needsbackend/app/techniques/definitions/vintage/future-self-interview.yaml-42-42 (1)
42-42:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이므로
1 points가 아니라1 point여야 합니다.✏️ 수정 제안
- - 1 points: No future vision + - 1 point: No future visionbackend/app/techniques/definitions/finish/body-wisdom-dialogue.yaml-41-41 (1)
41-41:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이 올바릅니다.
✏️ 수정 제안
- - 1 points: Physical/sensory experience ignored + - 1 point: Physical/sensory experience ignoredbackend/app/techniques/definitions/finish/sensory-exploration.yaml-42-42 (1)
42-42:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이어야 합니다. 다른 점수 기준("5 points", "4 points" 등)은 복수형이 맞지만, 1은 단수형 "point"를 사용해야 합니다.
✏️ 수정 제안
- - 1 points: Sensory experience not considered + - 1 point: Sensory experience not consideredbackend/app/techniques/definitions/palate/random-stimulation.yaml-8-42 (1)
8-42:⚠️ Potential issue | 🟡 Minor영문 템플릿 전환이 잘 적용되었습니다.
설명, 프롬프트 템플릿, 채점 기준이 영문으로 올바르게 전환되었으며, 분석 관점과 채점 기준이 Random Stimulation 기법의 특성에 맞게 잘 구성되어 있습니다.
단, Line 40에 문법 오류가 있습니다:
1 points→1 point(단수형).✏️ 문법 수정 제안
- - 1 points: All connections are obvious and linear + - 1 point: All connections are obvious and linearbackend/app/techniques/definitions/aroma/data-mining.yaml-10-44 (1)
10-44:⚠️ Potential issue | 🟡 Minor영어 번역 및 프롬프트 템플릿이 잘 구성되어 있습니다.
한국어에서 영어로의 전환이 명확하고, 분석 관점과 채점 기준이 잘 정리되어 있습니다. 다만 Line 42에서 문법 오류가 있습니다:
1 points→1 point(단수형이어야 합니다)✏️ 수정 제안
- - 1 points: No data-driven decision making + - 1 point: No data-driven decision makingbackend/app/techniques/definitions/aroma/morphological-analysis.yaml-34-42 (1)
34-42:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
Line 42에서
1 points는 문법적으로 올바르지 않습니다. 단수형1 point로 수정해야 합니다.✏️ 수정 제안
- - 1 points: Single dimension approach + - 1 point: Single dimension approachbackend/app/techniques/definitions/aroma/constraint-mapping.yaml-42-42 (1)
42-42:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
다른 점수 기준은 복수형이 맞지만, 1점은 단수형 "point"를 사용해야 합니다.
✏️ 수정 제안
- - 1 points: No constraint analysis + - 1 point: No constraint analysisbackend/app/techniques/definitions/balance/technology-readiness-level.yaml-53-53 (1)
53-53:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이 맞습니다.
📝 수정 제안
- - 1 points: TRL 1 or Unable to evaluate + - 1 point: TRL 1 or Unable to evaluatebackend/app/techniques/definitions/balance/technology-readiness-level.yaml-22-22 (1)
22-22:⚠️ Potential issue | 🟡 Minor"TRL 9 Stages" 제목이 모호합니다
현재 "TRL 9 Stages"는 "TRL 9의 단계들"로 오독될 수 있습니다. 실제로는 TRL 1부터 TRL 9까지 총 9개의 TRL 단계를 설명하고 있으므로, 제목을 수정하는 것이 좋습니다.
📝 수정 제안
- ### TRL 9 Stages: + ### 9 TRL Stages:backend/app/techniques/definitions/balance/decision-tree-mapping.yaml-42-42 (1)
42-42:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point" (전체 파일에 걸친 체계적 수정 필요)
단수형에는 "point"를 사용해야 합니다. 검증 결과, 이 오류는
backend/app/techniques/definitions/디렉토리 내 78개 파일에서 일괄적으로 발견되었습니다. 해당 디렉토리의 모든 YAML 파일에 대해 일괄 수정을 권장합니다.✏️ 수정 예시
- - 1 points: No decision analysis + - 1 point: No decision analysisbackend/app/techniques/definitions/body/fmea.yaml-47-47 (1)
47-47:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
1은 단수이므로 "1 point"로 수정해야 합니다. 동일한 오류가 scoring criteria 섹션(Line 58)에도 존재합니다.
✏️ 수정 제안
- - 1 points: No failure analysis + - 1 point: No failure analysisLine 58도 함께 수정:
- 1: No failure analysis(Line 58은 숫자 키만 사용하므로 문제없음 — promptTemplate 내 Line 47만 수정 필요)
backend/app/techniques/definitions/finish/jobs-to-be-done.yaml-12-48 (1)
12-48:⚠️ Potential issue | 🟡 Minor영문 전환이 잘 되었으나, Line 46에 문법 오류가 있습니다.
"1 points"는 문법적으로 틀립니다. 단수형"1 point"로 수정해야 합니다.✏️ 수정 제안
- - 1 points: No customer job analysis + - 1 point: No customer job analysisbackend/app/techniques/definitions/vintage/permission-giving.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이므로 "1 point"로 수정해야 합니다. 참고로 Line 35의 "5 points"는 복수형이라 올바릅니다.
✏️ 수정 제안
- - 1 points: No awareness of self-limitation + - 1 point: No awareness of self-limitationbackend/app/techniques/definitions/palate/reversal-inversion.yaml-42-42 (1)
42-42:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형에는 "point"를 사용해야 합니다.
✏️ 수정 제안
- - 1 points: No trace of reverse thinking + - 1 point: No trace of reverse thinkingbackend/app/techniques/definitions/finish/persona-journey.yaml-45-45 (1)
45-45:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이 맞습니다.
✏️ 수정 제안
- - 1 points: No user definition + - 1 point: No user definitionbackend/app/techniques/definitions/finish/empathy-mapping.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이어야 합니다. 이 파일뿐만 아니라 backend/app/techniques/definitions/ 디렉토리의 70개 이상의 YAML 파일에서 동일한 오류가 반복되고 있습니다. 모든 파일의 "1 points"를 "1 point"로 일괄 수정하기를 권장합니다.
✏️ 수정 제안
- - 1 points: No empathy for users + - 1 point: No empathy for usersbackend/app/techniques/definitions/body/risk-matrix.yaml-13-14 (1)
13-14:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
Line 14에서
1 points는 문법적으로 틀립니다. 단수형1 point로 수정해야 합니다.✏️ 수정 제안
- - 1 points: No risk analysis\n" + - 1 point: No risk analysis\n"backend/app/techniques/definitions/aroma/fact-checking.yaml-44-44 (1)
44-44:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
사용자에게 표시되는 스코어링 기준 템플릿에서 단수형이 필요합니다. 이 문제는 77개의 YAML 파일에서 반복되고 있으므로 일괄 수정을 권장합니다.
변경 사항
- - 1 points: Basis of claims unclear or inaccurate + - 1 point: Basis of claims unclear or inaccuratebackend/app/techniques/definitions/aroma/mind-mapping.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor"1 points" → "1 point" 문법 오류
모든 YAML 파일의
promptTemplate에서- 1 points:가 반복되고 있습니다. 영어 문법상 단수일 때는 "1 point"가 맞습니다. 이 파일뿐 아니라 이번 PR의 모든 technique YAML에 동일한 오류가 있으므로 일괄 수정이 필요합니다.✏️ 수정 제안 (이 파일 기준)
- - 1 points: Ideas listed sporadically + - 1 point: Ideas listed sporadicallybackend/app/techniques/definitions/palate/first-principles-thinking.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor"1 points" → "1 point" 문법 오류 (전체 YAML 파일 공통)
"1 points"는 문법적으로"1 point"이어야 합니다. 이 오류가 리뷰 대상인 7개 YAML 파일 모두에서 동일하게 반복됩니다. 일괄 수정을 권장합니다.🔧 수정 예시 (이 파일 기준)
- - 1 points: Copied existing solutions as is + - 1 point: Copied existing solutions as isbackend/app/techniques/definitions/palate/scamper.yaml-59-59 (1)
59-59:⚠️ Potential issue | 🟡 Minor오타: "partial applied" → "partially applied"
Line 59의 scoring criteria에서
1 element partial applied는1 element partially applied가 되어야 합니다.📝 수정 제안
- 2: 1 element partial applied + 2: 1 element partially appliedbackend/app/techniques/definitions/vintage/strength-analysis.yaml-36-44 (1)
36-44:⚠️ Potential issue | 🟡 Minor사용자 대면 텍스트에서 "1 points" 문법 오류 — 전체 기법 파일에 걸쳐 광범위하게 발생
Line 44의
1 points는 문법적으로1 point가 되어야 합니다. 이 오류는 이 파일에만 제한되지 않으며, 실제로 69개 이상의 모든 기법 정의 YAML 파일에 걸쳐 일관되게 나타나고 있습니다 (strength-analysis.yaml, assumption-reversal.yaml, kano-model.yaml, scamper.yaml, pestle-analysis.yaml 등 모든 분류의 기법들).각 기법의 최저 점수 단계마다 이 패턴이 반복되므로, 프롬프트 텍스트가 LLM에 전달되거나 사용자에게 직접 표시될 때 문법적 일관성을 위해 전체 기법 파일에서 통일된 수정이 필요합니다.
backend/app/techniques/definitions/balance/chaos-engineering.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor사소한 문법 오류: "1 points" → "1 point"
1 points는 문법적으로1 point가 맞습니다. 이 패턴이 이 PR의 다른 YAML 파일들(failure-analysis, trait-transfer, business-model-canvas, six-thinking-hats 등)에서도 반복됩니다. 일괄 수정을 권장합니다.✏️ 수정 제안
- - 1 points: No consideration of failure/recovery + - 1 point: No consideration of failure/recoverybackend/app/techniques/definitions/aroma/5w1h.yaml-29-29 (1)
29-29:⚠️ Potential issue | 🟡 Minor대소문자 비일관성: "usage situation?" → "Usage situation?"
다른 항목들은 대문자로 시작하는데 ("What is the core function?", "Who are the target users?"), 이 항목만 소문자로 시작합니다.
backend/app/techniques/definitions/aroma/5w1h.yaml-46-46 (1)
46-46:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point" (cross-pollination.yaml과 동일).
backend/app/techniques/definitions/palate/cross-pollination.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point".
단수형이 올바릅니다. 프롬프트 템플릿과 스코어링 기준 모두에서 동일한 오류가 있습니다 (Line 43, Line 54).
✏️ 수정 제안
- - 1 points: No external reference + - 1 point: No external referenceLine 54도 동일:
- 1: No external reference(이 줄은 숫자만 있으므로 문제 없습니다)
backend/app/techniques/definitions/cellar/synthesis-framework.yaml-11-54 (1)
11-54:⚠️ Potential issue | 🟡 MinorLGTM - 영어 번역 및 스키마 확장이 적절합니다.
전반적으로 영어 번역과 outputSchema 확장이 잘 구성되어 있습니다. 한 가지 사소한 문법 오류가 있습니다: Line 43에서
1 points는1 point로 수정되어야 합니다 (단수형). 이 패턴이 다른 YAML 파일에서도 반복됩니다.backend/app/techniques/definitions/finish/emotional-journey.yaml-42-42 (1)
42-42:⚠️ Potential issue | 🟡 Minor"1 points" → "1 point" 문법 오류
opportunity-spotting.yaml과 동일한 문법 오류입니다.
backend/app/techniques/definitions/vintage/opportunity-spotting.yaml-34-44 (1)
34-44:⚠️ Potential issue | 🟡 Minor"1 points" 문법 오류
Line 44:
1 points는 문법적으로1 point가 맞습니다. 이 패턴은 다른 YAML 파일에서도 반복되고 있습니다 (emotional-journey, question-storming, meta-analysis, evolutionary-pressure 등). 사용자에게 표시되는 프롬프트 템플릿이므로 일괄 수정을 권장합니다.🔤 수정 제안
- - 1 points: No market opportunity analysis + - 1 point: No market opportunity analysisbackend/app/techniques/definitions/cellar/consensus-building.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이어야 합니다.
✏️ 수정 제안
- - 1 points: No synthesis, reflects single perspective + - 1 point: No synthesis, reflects single perspectivebackend/app/techniques/definitions/cellar/priority-matrix.yaml-14-14 (1)
14-14:⚠️ Potential issue | 🟡 Minor
promptTemplate내 문법 오류: "1 points" → "1 point"
promptTemplate의 채점 기준에서"1 points"라고 되어 있는데, 올바른 영문법은"1 point"입니다. 이 오류는 priority-matrix.yaml뿐만 아니라 전체 기법 정의 파일들(cellar, palate, finish, body, balance, aroma, vintage, terroir 카테고리)의 채점 기준 섹션에서 69개 파일에 걸쳐 반복적으로 나타나는 체계적인 문제입니다.backend/app/techniques/definitions/palate/provocation-technique.yaml-57-57 (1)
57-57:⚠️ Potential issue | 🟡 Minor
creativeleapEvidence→creativeLeapEvidencecamelCase 오류
outputSchema의 다른 필드들(provocativeIdeas,industryNormsChallenged)은 모두 올바른 camelCase를 사용하고 있으나,creativeleapEvidence는L이 소문자로 되어 있어 camelCase 규칙을 위반합니다. 올바른 형식으로 수정하세요.수정
- creativeleapEvidence: string + creativeLeapEvidence: string
🧹 Nitpick comments (25)
backend/app/techniques/definitions/finish/body-wisdom-dialogue.yaml (1)
53-58: outputSchema 필드와 promptTemplate 분석 관점 간 매핑 확인 필요promptTemplate에는 4가지 분석 관점(Sensory Experience, Physical Comfort, Instinctive Reaction, Embodied Cognition)이 정의되어 있으나, outputSchema의
reasoning필드는 "Embodied Cognition"과 직접 대응되지 않습니다.reasoning이 범용 추론 필드로 의도된 것인지, 아니면embodiedCognition같은 이름이 더 적합한지 확인해 주세요.backend/app/techniques/definitions/balance/technology-readiness-level.yaml (1)
56-64: scoring 기준과 promptTemplate 간 표기 불일치Line 60의
Prototype~Operational에서 틸드(~)를 범위 구분자로 사용하고 있지만, promptTemplate(Line 45)에서는Prototype to Operational stage로 "to"를 사용합니다. 사용자에게 노출되는 텍스트이므로 일관성을 맞추는 것이 좋습니다.📝 수정 제안
- 5: TRL 7-9, Prototype~Operational + 5: TRL 7-9, Prototype to Operationalbackend/tests/test_auth_scope.py (1)
59-60:Secure플래그가 이 테스트에서 실제로 검증되지 않습니다.
mock_github_settingsfixture(Line 16)가FRONTEND_URL을 항상"http://localhost:3000"으로 설정하기 때문에, 이 조건문은 항상False로 평가되어Secure플래그 assertion이 실행되지 않습니다.비-localhost URL을 사용하는 별도의 테스트 케이스를 추가하여 프로덕션 환경에서
Secure플래그가 올바르게 설정되는지 검증하는 것을 권장합니다.💡 예시: 추가 테스트 케이스
def test_oauth_secure_cookie_for_production_url(self): """Test that Secure flag is set when FRONTEND_URL is not localhost.""" with patch.object(settings, "FRONTEND_URL", "https://www.somm.dev"): response = client.get("/auth/github", follow_redirects=False) set_cookie_header = response.headers.get("set-cookie", "") assert "Secure" in set_cookie_headerbackend/app/techniques/definitions/finish/gut-check.yaml (1)
15-15:promptTemplate헤더 네이밍 불일치다른 모든 기법 파일은
## [Name] Analysis패턴을 따르고 있습니다 (예:## Mind Mapping Analysis,## OKR Analysis,## Balanced Scorecard Analysis). 이 파일만## Gut Check으로 "Analysis"가 빠져 있습니다. 다운스트림에서 헤더 패턴에 의존하는 로직이 있다면 문제가 될 수 있고, 일관성 측면에서도## Gut Check Analysis로 맞추는 것이 좋겠습니다.✏️ 수정 제안
-promptTemplate: '## Gut Check +promptTemplate: '## Gut Check Analysisbackend/app/techniques/definitions/palate/triz.yaml (1)
57-63: outputSchema에 "Technical Evolution" 관점에 대응하는 필드 누락프롬프트에서 5개 분석 관점을 제시하지만 (Line 24-32: Contradiction, Inventive Principles, Ideal Final Result, Resource Utilization, Technical Evolution), outputSchema에는
technicalEvolution관련 필드가 없습니다. 다른 기법 파일들은 분석 관점과 outputSchema 필드가 대응되는 패턴을 따르고 있으므로, 일관성을 위해 추가를 고려해 주세요.💡 제안
outputSchema: score: number contradictionsIdentified: string[] inventivePrinciplesUsed: string[] idealFinalResult: string resourceUtilization: string + technicalEvolutionPattern: string reasoning: stringbackend/app/criteria/bmad_items.py (2)
19-26: frozen 데이터클래스 내 mutable 컬렉션 사용
BMADCategory의items: List[str]와BMADItem의rubric: Dict[int, str]는frozen=True임에도 내부 변이가 가능합니다.frozen=True는 속성 재할당만 방지하며, 리스트나 딕셔너리 자체의 변이(.append(),[key] = value)는 막지 못합니다.정적 읽기 전용 레지스트리의 의도에 맞게
tuple과MappingProxyType(또는 간단히tuple만이라도) 사용을 권장합니다.♻️ 수정 제안
+from types import MappingProxyType +from typing import Dict, List, Tuple, Mapping + + `@dataclass`(frozen=True) class BMADItem: """Single BMAD evaluation item.""" item_id: str name: str description: str max_score: int category: str - rubric: Dict[int, str] + rubric: Mapping[int, str] `@dataclass`(frozen=True) class BMADCategory: """BMAD evaluation category.""" category_id: str name: str max_score: int - items: List[str] + items: Tuple[str, ...]
BMADCategory인스턴스 생성 시에도 리스트 대신 튜플을 전달해야 합니다:# 예시 BMADCategory( category_id="A", name="Problem Definition", max_score=25, items=("A1", "A2", "A3", "A4"), )
BMADItem의 rubric은MappingProxyType으로 감싸서 전달:rubric=MappingProxyType({1: "...", 3: "...", 5: "...", 7: "..."})
336-338:get_max_total()이 하드코딩된 값을 반환합니다현재
return 100으로 하드코딩되어 있어 항목의max_score합계와 동기화가 깨질 수 있습니다. PR 목표에 "total 100"이 명시되어 있어 의도적인 설계로 보이지만, 방어적으로 계산 기반 검증을 추가하는 것도 고려해 볼 수 있습니다.♻️ 대안: 계산 기반 반환 또는 assertion 추가
def get_max_total() -> int: """Return the maximum total score (always 100).""" - return 100 + total = sum(item.max_score for item in BMAD_ITEMS.values()) + assert total == 100, f"BMAD total must be 100, got {total}" + return totalbackend/tests/test_bmad_items.py (3)
9-16:importlib를 통한 동적 로딩은 경로 변경에 취약합니다.앱 임포트를 우회하기 위한 의도는 이해하지만, 모듈 경로가 변경되면 테스트가 불명확한 에러로 실패합니다. 일반적인 임포트(
from backend.app.criteria.bmad_items import ...)가 불가능한 경우, 최소한module_path.exists()검증을 추가하면 디버깅이 수월해집니다.🛡️ 경로 존재 검증 추가 제안
def _load_bmad_module(): """Load the bmad_items module directly without triggering app imports.""" backend_path = Path(__file__).parent.parent module_path = backend_path / "app" / "criteria" / "bmad_items.py" + assert module_path.exists(), f"bmad_items.py not found at {module_path}" spec = importlib.util.spec_from_file_location("bmad_items", module_path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module
19-29: 모듈 레벨 실행은 실패 시 전체 테스트 수집을 중단시킵니다.
_load_bmad_module()가 모듈 레벨(line 19)에서 실행되므로, 로딩 실패 시 pytest 수집 단계에서 전체 파일의 모든 테스트가 실패합니다.pytestfixture로 전환하면 개별 테스트 실패로 격리할 수 있습니다.♻️ fixture 기반 로딩 제안
`@pytest.fixture`(scope="module") def bmad(): return _load_bmad_module() # 각 테스트에서 bmad fixture를 통해 접근 # 또는 module-scope fixture에서 개별 심볼을 반환
73-74:get_max_total()은 하드코딩된 100을 반환합니다 — 실제 합산 검증과 중복될 수 있습니다.
get_max_total()구현이return 100으로 하드코딩되어 있어(관련 스니펫 참조), 이 테스트는 항상 통과합니다. Line 36-37의test_total_max_score_is_100이 실제 아이템 점수 합산을 검증하므로 더 유의미합니다.get_max_total()이 실제 합산 기반으로 변경될 경우를 대비해 현재 테스트를 유지하는 것도 괜찮지만, 하드코딩 값과 실제 합산 간 불일치 가능성을 인지해 두세요.backend/app/techniques/schema.py (1)
39-40: Pydantic v2에서는class Config가 공식적으로 deprecated되었습니다.
class Config는 Pydantic v2에서 여전히 동작하지만, 공식 문서에서 deprecated 상태입니다. 권장 방식은model_config = ConfigDict(populate_by_name=True)입니다.TechniqueMetadata(Line 20-21)와TechniqueDefinition(Line 39-40) 모두 이 패턴을 사용하고 있으므로, 함께 마이그레이션하는 것이 좋습니다.♻️ model_config로 마이그레이션
-from pydantic import BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field class TechniqueMetadata(BaseModel): + model_config = ConfigDict(populate_by_name=True) + complexity: Literal["low", "medium", "high"] = Field(default="medium") estimated_tokens: int = Field(default=500, alias="estimatedTokens") requires_web_search: bool = Field(default=False, alias="requiresWebSearch") requires_rag: bool = Field(default=False, alias="requiresRAG") source: Optional[str] = None - - class Config: - populate_by_name = True class TechniqueDefinition(BaseModel): + model_config = ConfigDict(populate_by_name=True) + id: str name: str # ... other fields ... fairthon_source: Optional[str] = Field(default=None, alias="requiredSources") - - class Config: - populate_by_name = Truebackend/tests/test_multi_mode.py (1)
134-140: 모듈 레벨에서 이미 import된pytest를 메서드 내부에서 중복 importLine 137에서
import pytest가 메서드 내부에서 다시 선언되고 있지만, Line 3에서 이미 모듈 레벨로 import되어 있습니다. 불필요한 중복입니다.♻️ 수정 제안
def test_old_six_hats_value_rejected(self): """Test that old 'six_hats' value is rejected.""" from app.graph.graph_factory import EvaluationMode - import pytest with pytest.raises(ValueError): EvaluationMode("six_hats")backend/tests/test_graph_contracts.py (2)
401-407: 테스트 의도와 fixture 데이터 불일치테스트 이름은
test_payload_missing_evaluation_id이지만,mode="invalid_mode_for_test"를 사용하고 있습니다.Graph3DPayload는 임의의 mode 문자열을 허용하므로 (Line 535-561 참조) 문제없지만, 테스트 의도를 더 명확히 하려면 유효한 mode 값을 사용하는 것이 좋습니다. 현재 상태에서는ValidationError가 missingevaluation_id때문인지 다른 이유인지 명확하지 않을 수 있습니다.♻️ 수정 제안
with pytest.raises(ValidationError): Graph3DPayload( - mode="invalid_mode_for_test", + mode="six_sommeliers", nodes=[node], edges=[], metadata=metadata, )
459-466: 테스트 fixture의edges데이터와metadata.total_edges불일치
edges=[](0개)이지만metadata의total_edges=1로 설정되어 있습니다. 모델에서 교차 검증하지 않는다면 테스트 통과에 문제는 없지만, 테스트 데이터의 일관성을 위해total_edges=0으로 수정하는 것이 좋습니다.♻️ 수정 제안
metadata 생성 부분(Line 448-457)에서:
- total_edges=1, + total_edges=0,backend/tests/test_technique_loading.py (4)
85-93: 검증 로직에 중복 조건이 있습니다.
valid_values집합에 이미"either","both","pdf","readme"가 포함되어 있으므로,or이후의 리스트 검사는 완전히 중복됩니다. 단순히assert value in valid_values로 충분합니다.♻️ 수정 제안
valid_values = {"either", "both", "pdf", "readme", "pdf_only", "readme_only"} for value in source_values: - assert value in valid_values or value in [ - "either", - "both", - "pdf", - "readme", - ], f"Unexpected fairthon_source value: {value}" + assert value in valid_values, f"Unexpected fairthon_source value: {value}"
137-145: 불필요한noqa: F401지시어를 제거하세요.
pytest.raises(ImportError)블록 내의 import는 실패가 예상되므로F401(unused import) 경고가 발생하지 않습니다. 정적 분석 도구(Ruff)에서도 이를 불필요한 지시어로 플래그하고 있습니다.♻️ 수정 제안
def test_filter_techniques_not_importable(self): """Test that filter_techniques is no longer importable from loader.""" with pytest.raises(ImportError): - from app.techniques.loader import filter_techniques # noqa: F401 + from app.techniques.loader import filter_techniques def test_determine_available_inputs_not_importable(self): """Test that determine_available_inputs is no longer importable from loader.""" with pytest.raises(ImportError): - from app.techniques.loader import determine_available_inputs # noqa: F401 + from app.techniques.loader import determine_available_inputs
247-249:"readme.MD"케이스 감도 테스트가 한 가지 패턴만 확인합니다.현재
"readme.MD"만 테스트하는데,"README.MD"또는"Readme.md"같은 mixed-case 패턴도 추가하면 케이스 비감도 검증이 더 견고해집니다. 선택 사항입니다.
15-57: 싱글톤 레지스트리 테스트 간 격리에 대한 확인.
TestTechniqueLoading의 일부 테스트는TechniqueRegistry.reset()을 호출하지만(Line 33, 43), 다른 테스트들은 호출하지 않습니다. 싱글톤 특성상 테스트 실행 순서에 따라 레지스트리 상태가 공유됩니다. 현재는 읽기 전용 접근이라 문제가 없지만, 추후 테스트가 확장되면pytestfixture로setup/teardown에서reset()을 일관되게 호출하는 것이 좋습니다.backend/app/techniques/registry.py (2)
143-159:get_all_techniques()와list_techniques()의 구현이 완전히 동일합니다.두 메서드 모두
self._ensure_loaded()후sorted(self._techniques, key=lambda t: t.id)를 반환합니다. 의미적 차이("필터링 없이"와 "결정적 순서")만 있고 실제 동작은 같습니다. 하나를 다른 하나에 위임하면 중복을 줄일 수 있습니다.♻️ 수정 제안
def get_all_techniques(self) -> List[TechniqueDefinition]: """Return all loaded techniques without filtering. Returns: List of all 75 technique definitions, sorted by ID. """ - self._ensure_loaded() - return sorted(self._techniques, key=lambda t: t.id) + return self.list_techniques()
339-374:has_readme_content유틸리티가 잘 구현되어 있습니다.다양한 readme 필드 형식, dict/str 파일 목록, 빈값/None 처리, 대소문자 비감도 등 다양한 엣지 케이스를 적절히 처리합니다.
한 가지 고려사항:
repo_context의 타입 힌트가Dict[str, Any]이지만None도 허용하는 로직(if not repo_context)이 있습니다. 타입 힌트를Optional[Dict[str, Any]]로 변경하면 호출자에게 더 명확합니다.♻️ 선택적 수정 제안
-def has_readme_content(repo_context: Dict[str, Any]) -> bool: +def has_readme_content(repo_context: Optional[Dict[str, Any]]) -> bool:backend/tests/test_yaml_english.py (2)
50-53: 하드코딩된 기법 개수75에 대한 고려현재 PR 목표가 정확히 75개 기법이므로 이 assertion은 유효합니다. 다만, 향후 기법 추가/삭제 시 이 테스트가 깨지므로, 추후 기법 수가 변동 가능하다면
>= 75또는 상수 추출을 고려해볼 수 있습니다.
58-70: 한국어 검사 범위가description과promptTemplate에만 한정됨
scoring.criteria값이나name등 다른 사용자 대면 필드에서도 한국어가 남아있을 수 있습니다. PR 목표에서 모든 한국어를 제거한다고 했으므로, 추가 필드 검사를 고려해볼 수 있습니다.♻️ 전체 텍스트 필드 한국어 검사 예시
+ def test_no_korean_in_scoring_criteria(self): + for tech in self.techniques: + scoring = tech.get("scoring", {}) + for key, value in scoring.get("criteria", {}).items(): + assert not KOREAN_PATTERN.search(str(value)), ( + f"{tech.get('id')} has Korean in scoring criteria" + ) + + def test_no_korean_in_names(self): + for tech in self.techniques: + name = tech.get("name", "") + assert not KOREAN_PATTERN.search(name), ( + f"{tech.get('id')} has Korean in name" + )backend/tests/test_graph_api.py (2)
100-107:TestAuthentication과TestAuthorization에 중복 테스트 로직
test_check_ownership_requires_auth_for_non_public(Line 100)과test_unauthenticated_non_public_returns_auth_error(Line 144)가 거의 동일한 로직을 검증합니다. 둘 다_check_ownership(evaluation, None, non_public_id)를 호출하고"Authentication required"CorkedError를 확인합니다.하나로 통합하거나, 각 테스트가 검증하는 시나리오의 차이를 명확히 하는 것이 좋습니다.
Also applies to: 144-153
162-199:TestNotFound의 세 테스트가 동일한 로직을 반복
test_get_graph_unknown_evaluation_raises_empty_cellar,test_get_timeline_...,test_get_mode_...세 테스트 모두_get_evaluation("unknown_eval")을 호출하고None을 확인하는 동일한 테스트 바디를 가지고 있습니다. Docstring은 서로 다른 엔드포인트를 암시하지만, 실제로는 같은 private 함수만 테스트하고 있습니다.각 엔드포인트의 실제 HTTP 응답(404)을 검증하거나, 하나의 테스트로 통합하는 것을 고려해보세요.
backend/app/api/routes/graph.py (1)
193-213: 실행 상태 오버레이의 하드코딩된 에이전트 수>= 5
completed_agents >= 5조건이SIX_SOMMELIERS토폴로지(5명의 병렬 에이전트)에만 유효합니다. 현재GRAND_TASTING모드도 동일한build_six_sommeliers_topology()를 사용하므로 당장 문제가 되지는 않지만,GRAND_TASTING이 별도 토폴로지를 갖게 되면 이 하드코딩이 버그의 원인이 됩니다.향후 모드별 토폴로지가 분리될 때 이 로직도 함께 업데이트해야 합니다.
| - 2 points: Mentioned negative examples only | ||
|
|
||
| - 1점: 안티-솔루션 사고 없음 | ||
| - 1 points: No anti-solution thinking |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, check the specific line in the target file
cat -n backend/app/techniques/definitions/body/anti-solution.yaml | sed -n '40,46p'Repository: Two-Weeks-Team/somm.dev
Length of output: 218
🏁 Script executed:
# Search for "1 points" pattern in all YAML files
rg -n '1 points' --type yamlRepository: Two-Weeks-Team/somm.dev
Length of output: 8976
🏁 Script executed:
# Also search for potential similar patterns with other numbers
rg -n '\b[0-9]+ points:' --type yamlRepository: Two-Weeks-Team/somm.dev
Length of output: 45354
문법 오류: "1 points" → "1 point" (전체 기술 정의 파일에서 반복)
단수형에는 "point"를 사용해야 합니다. 이 오류는 80개 이상의 YAML 파일에서 반복되므로 일괄 수정이 필요합니다.
✏️ 수정 제안
- - 1 points: No anti-solution thinking
+ - 1 point: No anti-solution thinking📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - 1 points: No anti-solution thinking | |
| - 1 point: No anti-solution thinking |
🤖 Prompt for AI Agents
In `@backend/app/techniques/definitions/body/anti-solution.yaml` at line 43, 파일들에서
반복된 문법 오류 "1 points" 대신 단수형 "1 point"를 사용해야 합니다;
backend/app/techniques/definitions/body/anti-solution.yaml 에서 보이는 "- 1 points:"
같은 모든 YAML 항목을 프로젝트 전체(약 80개 파일)에서 찾아 "- 1 points" 또는 "1 points:" 등 모든 변형을 "- 1
point" 또는 "1 point:"로 일괄 교체하고, 변경 후 YAML 파서(lint)를 돌려 문법 오류가 없는지 확인하세요; 검색/치환은
파일 확장자 .yaml/.yml에 한정하고 "points"가 실제 복수 수를 의미하는 다른 문맥을 건드리지 않도록 패턴 매칭(예: "\b1
points\b" 또는 "- 1 points:")으로 제한하세요.
| - 5 points: Effectively applied solutions from completely different industries | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for "1 points" pattern in all YAML files
rg -n "1 points" --glob '*.yaml' backend/app/techniques/definitions/Repository: Two-Weeks-Team/somm.dev
Length of output: 8976
🏁 Script executed:
#!/bin/bash
# Search for all point patterns to verify consistency
echo "=== Checking for 2 points ==="
rg -c "2 points" --glob '*.yaml' backend/app/techniques/definitions/ | grep -v ":0" | wc -l
echo "=== Checking for 3 points ==="
rg -c "3 points" --glob '*.yaml' backend/app/techniques/definitions/ | grep -v ":0" | wc -l
echo "=== Checking for 4 points ==="
rg -c "4 points" --glob '*.yaml' backend/app/techniques/definitions/ | grep -v ":0" | wc -l
echo "=== Checking for 5 points ==="
rg -c "5 points" --glob '*.yaml' backend/app/techniques/definitions/ | grep -v ":0" | wc -l
echo "=== Sample of 4 points usage ==="
rg -n "4 points" --glob '*.yaml' backend/app/techniques/definitions/ | head -3
echo "=== Sample of 5 points usage ==="
rg -n "5 points" --glob '*.yaml' backend/app/techniques/definitions/ | head -3Repository: Two-Weeks-Team/somm.dev
Length of output: 1056
전체 75개 YAML 파일에서 "1 points"를 "1 point"로 수정 필요
"1 points"는 문법적으로 틀렸습니다. 다른 점수("2 points", "3 points", "4 points", "5 points")와 달리, 1은 단수형 "point"를 사용해야 합니다. 이 문법 오류는 backend/app/techniques/definitions/ 디렉터리의 모든 75개 파일에서 일관되게 발견됩니다.
🤖 Prompt for AI Agents
In `@backend/app/techniques/definitions/palate/cross-pollination.yaml` around
lines 35 - 36, Multiple technique definition YAMLs contain the incorrect plural
"1 points"; locate every occurrence of the YAML list entry pattern "- 1 points:"
(e.g., in technique definition files) and change it to the singular "- 1 point:"
so the score uses correct grammar; ensure you update every file where the exact
string "1 points" appears (preserving surrounding spacing and punctuation) and
run a quick grep to confirm no remaining instances.
#226, #227) - #224: Remove input_source field, add fairthon_source for YAML preservation - Remove filter_techniques() and determine_available_inputs() from loader - Add get_all_techniques() and has_readme_content() to registry - #225: Replace 75 Korean YAML technique definitions with English Fairthon templates - Map Fairthon categories to wine-themed folder names - Remove nameKo field from schema and all YAMLs - #226: Unify EvaluationMode enum as single source of truth - Remove duplicate EvaluationMode from models/graph.py - Replace SIX_HATS with SIX_SOMMELIERS everywhere - Add FULL_TECHNIQUES mode - Update frontend TypeScript types - #227: Define BMAD 17-item evaluation canon (A1-D4, 100 points) - Create backend/app/criteria/ module with bmad_items.py - A=25pts, B=25pts, C=30pts, D=20pts - Fix pre-existing auth test failures (7 tests) - Update _check_ownership tests for 3-param signature - Fix Secure cookie assertion for localhost environment Closes #224, Closes #225, Closes #226, Closes #227
bbc7143 to
1be88eb
Compare
There was a problem hiding this comment.
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (8)
backend/app/techniques/definitions/finish/first-impression-analysis.yaml (1)
71-71:⚠️ Potential issue | 🟡 Minor45줄의 문법 오류: "1 points"를 "1 point"로 수정 필요
현재 코드에서 "1 points"로 표기되어 있으나 단수형이므로 "1 point"로 수정해야 합니다.
수정 제안
- 2 points: Somewhat negative, complex or confusing - - 1 points: Negative first impression, no interest generated + - 1 point: Negative first impression, no interest generatedbackend/app/techniques/definitions/finish/emotional-journey.yaml (1)
69-69:⚠️ Potential issue | 🟠 Major
requiredSources를 PR#224의표준 필드명fairthon_source로 변경하세요.PR
#224는"fairthon_source for YAML preservation"를 도입했으며, 스키마에서fairthon_source를 정규 필드명으로 정의하고requiredSources를 하위호환성을 위한 별칭으로 설정했습니다. 현재 이 파일을 포함해 79개 이상의 technique YAML 파일이 여전히 별칭 이름을 사용하고 있어 PR#224의의도와 불일치합니다.✏️ 수정 제안
-requiredSources: pdf_only +fairthon_source: pdf_only영향받는 파일: 79개+ technique YAML 파일 (모든 카테고리에 걸쳐 있음)
backend/app/services/evaluation_service.py (3)
189-193:⚠️ Potential issue | 🟡 Minor에러 메시지에
full_techniques모드가 누락되어 있습니다.
is_valid_mode는FULL_TECHNIQUES도 유효한 모드로 인식하지만, 에러 메시지는'six_sommeliers'와'grand_tasting'만 표시합니다. 사용자에게 혼란을 줄 수 있습니다.🔧 수정 제안
if not is_valid_mode(evaluation_mode): raise CorkedError( f"Invalid evaluation mode: {evaluation_mode}. " - "Must be 'six_sommeliers' or 'grand_tasting'" + "Must be 'six_sommeliers', 'grand_tasting', or 'full_techniques'" )
528-535:⚠️ Potential issue | 🟠 Major
grand_tasting모드에서 반환값이 항상jeanpierre_result를 참조합니다.
save_evaluation_results는grand_tasting모드일 때cellar_result에서 점수를 읽지만 (Line 269-278), 이 함수의 반환값은 항상jeanpierre_result를 사용합니다.grand_tasting모드에서는jeanpierre_result가 없을 수 있으므로score가 항상 0으로 반환됩니다.
run_full_evaluation(Line 461)에도 동일한 문제가 있습니다.🔧 수정 제안
await save_evaluation_results(evaluation_id, result, evaluation_mode) await eval_repo.update_status(evaluation_id, "completed") - jeanpierre = result.get("jeanpierre_result") or {} - return { - "evaluation_id": evaluation_id, - "status": "completed", - "score": jeanpierre.get("overall_score", 0), - "rating_tier": jeanpierre.get("rating_tier", ""), - } + if evaluation_mode == "grand_tasting": + cellar = result.get("cellar_result") or {} + aggregate_score = cellar.get("aggregate_score", 0) + return { + "evaluation_id": evaluation_id, + "status": "completed", + "score": int(aggregate_score * 20), + "rating_tier": "", + } + else: + jeanpierre = result.get("jeanpierre_result") or {} + return { + "evaluation_id": evaluation_id, + "status": "completed", + "score": jeanpierre.get("overall_score", 0), + "rating_tier": jeanpierre.get("rating_tier", ""), + }
384-386:⚠️ Potential issue | 🟡 Minor
FULL_TECHNIQUES모드는 현재 평가 실행이 불가능하지만, 향후 지원 시total_steps이 처리되지 않습니다.현재 시스템은
six_sommeliers(6단계)와grand_tasting(8단계)만 실행 가능하며 두 모드 모두total_steps계산이 정확합니다. 그러나FULL_TECHNIQUES모드는EvaluationMode열거형과 ReactFlow 시각화에 정의되어 있지만graph_factory에 미등록되어 평가 생성 시 검증 오류가 발생합니다. 만약 향후 이 모드가 지원되면 라인 386의 조건문이 처리하지 않아 진행률이 부정확해질 수 있습니다.현재는 실제 영향이 없지만, 방어적 프로그래밍 관점에서 모든 정의된 평가 모드에 대한 명시적 처리가 권장됩니다.
backend/app/models/graph.py (1)
227-229:⚠️ Potential issue | 🟡 Minor
hat_type필드 설명에 "Six Hats"가 남아 있습니다.
SIX_HATS가SIX_SOMMELIERS로 변경되었으므로 docstring(Line 209)과 Field description(Line 228)의 "Six Hats mode"를 업데이트해야 합니다.✏️ 수정 제안
- hat_type: Optional hat type for Six Sommeliers mode ... hat_type: Optional[str] = Field( - default=None, description="Optional hat type for Six Hats mode" + default=None, description="Optional hat type for Six Sommeliers mode" )Line 209 docstring도 동일하게 수정:
- hat_type: Optional hat type for Six Sommeliers mode + hat_type: Optional hat type for Six Sommeliers modebackend/app/api/routes/graph.py (1)
155-159:⚠️ Potential issue | 🔴 Critical
_check_ownership호출 시evaluation_id인수 누락 — 런타임 TypeError 발생
_check_ownership의 시그니처는(evaluation, user, evaluation_id)3개 인수를 필수로 요구합니다. Line 159와 Line 185에서evaluation_id를 전달하지 않아 런타임 시TypeError가 발생합니다. 이 두 엔드포인트(get_graph_structure,get_graph_execution)가 호출될 때 서버 500 오류가 발생합니다.🐛 수정 제안
evaluation = await _get_evaluation(evaluation_id) if not evaluation: raise EmptyCellarError(f"Evaluation not found: {evaluation_id}") - _check_ownership(evaluation, user) + _check_ownership(evaluation, user, evaluation_id)Line 185에도 동일하게 적용:
evaluation = await _get_evaluation(evaluation_id) if not evaluation: raise EmptyCellarError(f"Evaluation not found: {evaluation_id}") - _check_ownership(evaluation, user) + _check_ownership(evaluation, user, evaluation_id)backend/tests/test_graph_api.py (1)
162-199:⚠️ Potential issue | 🟡 Minor테스트 이름이 실제 검증 내용과 불일치
test_get_graph_unknown_evaluation_raises_empty_cellar,test_get_timeline_unknown_evaluation_raises_empty_cellar,test_get_mode_unknown_evaluation_raises_empty_cellar세 테스트 모두 이름에raises_empty_cellar가 포함되어 있지만, 실제로는_get_evaluation이None을 반환하는지만 검증합니다.EmptyCellarError가 발생하는지는 확인하지 않습니다.테스트 이름을
test_get_evaluation_returns_none_for_unknown으로 변경하거나, 실제 엔드포인트를 호출하여 404 응답을 검증하는 것을 고려해 보세요.
🟡 Minor comments (42)
backend/app/techniques/definitions/finish/jobs-to-be-done.yaml-38-46 (1)
38-46:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
Line 46에서
1 points는 문법적으로 올바르지 않습니다. 단수형인1 point로 수정해야 합니다.✏️ 수정 제안
- - 1 points: No customer job analysis + - 1 point: No customer job analysisbackend/app/techniques/definitions/palate/first-principles-thinking.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수 표현이므로 "1 point"로 수정해야 합니다. 다른 줄의 "5 points", "4 points" 등은 복수형이 맞지만, 1은 단수입니다.
✏️ 수정 제안
- - 1 points: Copied existing solutions as is + - 1 point: Copied existing solutions as isbackend/app/techniques/definitions/finish/kano-model.yaml-46-46 (1)
46-46:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형 점수에는 "point"를 사용해야 합니다.
✏️ 수정 제안
- - 1 points: Priorities not considered + - 1 point: Priorities not consideredbackend/app/techniques/definitions/body/pre-mortem.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형에는 "point"를 사용해야 합니다. 다른 항목들(5 points, 4 points 등)은 올바른 복수형이지만, 1은 단수입니다.
✏️ 수정 제안
- - 1 points: No pre-mortem + - 1 point: No pre-mortembackend/app/techniques/definitions/balance/technology-readiness-level.yaml-53-53 (1)
53-53:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이 올바릅니다.
📝 수정 제안
- - 1 points: TRL 1 or Unable to evaluate + - 1 point: TRL 1 or Unable to evaluatebackend/app/techniques/definitions/balance/technology-readiness-level.yaml-22-22 (1)
22-22:⚠️ Potential issue | 🟡 Minor"TRL 9 Stages" 제목이 모호합니다.
현재 "TRL 9 Stages"는 "TRL 9의 단계들"로 읽힐 수 있어 혼동을 줍니다. 실제 의미는 "9단계 TRL"이므로, 명확하게 수정하는 것이 좋습니다.
📝 수정 제안
- ### TRL 9 Stages: + ### TRL Stages (1-9):backend/app/techniques/definitions/balance/evolutionary-pressure.yaml-11-54 (1)
11-54:⚠️ Potential issue | 🟡 Minor한국어→영어 템플릿 전환이 잘 되었습니다.
설명, 프롬프트 템플릿, 채점 기준이 영어로 일관성 있게 변환되었으며, PR 목표(
#225)에 부합합니다.다만 Line 43에서 문법 오류가 있습니다:
"1 points"→"1 point"(단수형). Line 35의"5 points"등은 올바르지만, 1은 단수입니다.✏️ 문법 수정 제안
- - 1 points: Environmental changes ignored + - 1 point: Environmental changes ignoredbackend/app/techniques/definitions/vintage/scenario-planning.yaml-48-48 (1)
48-48:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이 올바른 표현입니다.
✏️ 수정 제안
- - 1 points: No preparation for future + - 1 point: No preparation for futurebackend/app/techniques/definitions/palate/reversal-inversion.yaml-42-42 (1)
42-42:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이 올바릅니다.
✏️ 수정 제안
- - 1 points: No trace of reverse thinking + - 1 point: No trace of reverse thinkingbackend/app/techniques/definitions/finish/sensory-exploration.yaml-42-42 (1)
42-42:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이 올바릅니다.
✏️ 수정 제안
- - 1 points: Sensory experience not considered + - 1 point: Sensory experience not consideredbackend/app/techniques/definitions/finish/gut-check.yaml-46-46 (1)
46-46:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형에 맞게 수정이 필요합니다.
✏️ 수정 제안
- - 1 points: Negative gut feeling "This won''t work" + - 1 point: Negative gut feeling "This won''t work"backend/app/techniques/definitions/body/zombie-apocalypse.yaml-42-42 (1)
42-42:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
다른 점수 기준은 복수형("5 points", "4 points" 등)이 올바르지만, 1은 단수형이어야 합니다.
제안된 수정
- - 1 points: Extreme scenarios ignored + - 1 point: Extreme scenarios ignoredbackend/app/techniques/definitions/terroir/metaphor-mapping.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
다른 점수 기준("5 points", "4 points" 등)은 복수형이 맞지만, 1은 단수형 "point"를 사용해야 합니다. 35번 줄의 "5 points"와 일관성을 유지하되 문법적으로 올바르게 수정하세요.
✏️ 수정 제안
- - 1 points: No metaphors + - 1 point: No metaphorsbackend/app/techniques/definitions/body/risk-matrix.yaml-10-12 (1)
10-12:⚠️ Potential issue | 🟡 Minordescription에 불필요한 후행 공백/개행 포함
YAML flow scalar 형식으로 인해 description 값 끝에 불필요한 개행과 공백이 포함됩니다. 문자열 비교나 UI 렌더링 시 의도치 않은 결과가 발생할 수 있습니다.
✏️ 수정 제안
-description: 'Technique to prioritize risks by classifying them into a 2D matrix of Likelihood and Impact. - - ' +description: 'Technique to prioritize risks by classifying them into a 2D matrix of Likelihood and Impact.'backend/app/techniques/definitions/body/risk-matrix.yaml-13-14 (1)
13-14:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
Line 14에서
1 points는 문법적으로 올바르지 않습니다. 단수형1 point로 수정해야 합니다.✏️ 수정 제안
- - 1 points: No risk analysis\n" + - 1 point: No risk analysis\n"backend/app/techniques/definitions/terroir/mythic-frameworks.yaml-42-42 (1)
42-42:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수 표현에는
point를 사용해야 합니다. 다른 항목들은 복수형이 맞지만,1에는 단수형이 적합합니다.✏️ 수정 제안
- - 1 points: No narrative structure + - 1 point: No narrative structurebackend/app/techniques/definitions/finish/first-impression-analysis.yaml-44-45 (1)
44-45:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이므로 "points"가 아닌 "point"가 올바릅니다.
제안된 수정
- - 1 points: Negative first impression, no interest generated + - 1 point: Negative first impression, no interest generatedbackend/app/techniques/definitions/palate/scamper.yaml-49-49 (1)
49-49:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이어야 합니다.
수정 제안
- - 1 points: No SCAMPER elements applied (Existing method as is) + - 1 point: No SCAMPER elements applied (Existing method as is)backend/app/techniques/definitions/palate/scamper.yaml-56-60 (1)
56-60:⚠️ Potential issue | 🟡 Minor오타: "partial applied" → "partially applied"
Line 59에서 부사형이 필요합니다. 또한, promptTemplate(Line 47)의 동일한 채점 기준과 표현이 일관되도록 확인해 주세요 — promptTemplate에는 "partially applied"로 되어 있지만 여기에는 "partial applied"로 되어 있습니다.
수정 제안
- 2: 1 element partial applied + 2: 1 element partially appliedbackend/app/techniques/definitions/vintage/yes-and-building.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor"1 points"를 "1 point"로 수정 필요
문법 오류: 단수 점수 "1"에는 "points"가 아닌 "point"를 사용해야 합니다. 이 패턴은 89개 이상의 YAML 기술 정의 파일에서 반복되므로, 일괄 수정을 권장합니다.
✏️ 수정 제안
- - 1 points: Idea denial/blocking + - 1 point: Idea denial/blockingbackend/app/techniques/definitions/balance/chaos-engineering.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이 맞습니다.
📝 수정 제안
- - 1 points: No consideration of failure/recovery + - 1 point: No consideration of failure/recoverybackend/app/techniques/definitions/finish/emotional-journey.yaml-42-42 (1)
42-42:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이 올바릅니다. 다른 점수 기준(5 points, 4 points 등)은 복수형이 맞지만, 1은 단수형을 사용해야 합니다.
✏️ 수정 제안
- - 1 points: Generally unpleasant or frustrating + - 1 point: Generally unpleasant or frustratingbackend/app/techniques/definitions/palate/provocation-technique.yaml-41-41 (1)
41-41:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
✏️ 수정 제안
- - 1 points: Conservative approach, no provocative elements + - 1 point: Conservative approach, no provocative elementsbackend/app/techniques/definitions/palate/provocation-technique.yaml-53-58 (1)
53-58:⚠️ Potential issue | 🟡 Minor
creativeleapEvidence는 camelCase 규칙이 깨져 있습니다 —creativeLeapEvidence여야 합니다.동일
outputSchema내 형제 필드들(provocativeIdeas,industryNormsChallenged)은 모두 camelCase를 따르고 있으나, 이 필드만L이 소문자입니다.🐛 수정 제안
- creativeleapEvidence: string + creativeLeapEvidence: string또한 41번 줄의 "1 points"는 문법적으로 "1 point"여야 합니다.
backend/app/techniques/definitions/finish/inner-child-conference.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형으로 수정이 필요합니다.
✏️ 수정 제안
- - 1 points: No pure curiosity/imagination + - 1 point: No pure curiosity/imaginationbackend/app/techniques/definitions/terroir/emotion-orchestra.yaml-42-42 (1)
42-42:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형에는 "point"를 사용해야 합니다. 다른 점수 기준(2~5)은 복수형 "points"가 맞지만, 1은 단수형이어야 합니다.
✏️ 수정 제안
- - 1 points: No consideration of emotion + - 1 point: No consideration of emotionbackend/app/techniques/definitions/vintage/what-if-scenarios.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형일 때는 "point"로 표기해야 합니다.
제안된 수정
- - 1 points: No What If thinking + - 1 point: No What If thinkingbackend/app/techniques/definitions/palate/quantum-superposition.yaml-46-46 (1)
46-46:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형이 올바릅니다. 다른 점수 기준("5 points", "4 points" 등)은 복수형이 맞지만, 1은 단수형 "point"를 사용해야 합니다.
✏️ 수정 제안
- - 1 points: Dichotomous thinking, no flexibility + - 1 point: Dichotomous thinking, no flexibilitybackend/app/techniques/definitions/cellar/balanced-scorecard.yaml-16-16 (1)
16-16:⚠️ Potential issue | 🟡 MinorHBR 참고 문헌 명칭이 일관되지 않습니다.
Line 16의
description에서는"75 Most Influential Management Ideas"로 표기하고 있으나, Line 73의academicReference에서는"75 Big Ideas"로 표기하고 있습니다. 동일한 출처를 가리키는 것이라면 명칭을 통일해 주세요.Also applies to: 73-73
backend/app/techniques/definitions/cellar/indigenous-wisdom.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"로 수정 필요
영어 문법상 단수 주어(1)는 단수 명사(point)를 사용해야 합니다. "1 points"는 문법적으로 올바르지 않으며, 모든 YAML 파일의 점수 평가 기준에서 일관되게 발생하는 오류입니다.
수정 예시
- - 1 points: No holistic perspective + - 1 point: No holistic perspective이 오류는 vintage, terroir, palate, finish, balance, aroma, body, cellar 등 모든 디렉토리에 걸쳐 68개 이상의 파일에 존재합니다.
backend/app/techniques/definitions/aroma/5w1h.yaml-29-29 (1)
29-29:⚠️ Potential issue | 🟡 Minor소문자 시작 문장 — 사소한 텍스트 품질 이슈입니다.
질문 부호 뒤에 소문자로 시작하는
"usage situation?"이 있습니다. 다른 항목들은 대문자로 시작하므로 일관성을 위해"Usage situation?"으로 변경하는 것이 좋겠습니다.🔤 수정 제안
- 4. **When**: When is it used? usage situation? + 4. **When**: When is it used? Usage situation?backend/app/techniques/definitions/cellar/meta-analysis.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor
"1 points"→"1 point"— 전체 75개 파일에서 동일한 문법 오류
promptTemplate내"- 1 points:"는 영어 문법상"- 1 point:"가 맞습니다. 리뷰 범위의 7개 파일뿐만 아니라backend/app/techniques/definitions하위의 모든 75개 기법 정의 YAML 파일에서 동일한 오류가 발견됩니다.수정 예시
- - 1 points: No synthesis + - 1 point: No synthesisbackend/app/techniques/definitions/cellar/six-thinking-hats.yaml-36-44 (1)
36-44:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
모든 YAML 파일의
promptTemplate에서1 points가 반복되고 있습니다. 영어 문법상 단수일 때는 "1 point"가 올바릅니다. 이 파일뿐 아니라 PR 내 모든 technique YAML에서 동일한 수정이 필요합니다.- - 1 points: Single perspective only + - 1 point: Single perspective onlybackend/app/techniques/definitions/finish/alien-anthropologist.yaml-43-43 (1)
43-43:⚠️ Potential issue | 🟡 Minor"1 points" 문법 오류 — "1 point"로 수정 필요
Line 43에서
1 points는 문법적으로 올바르지 않습니다. 단수형1 point로 수정해야 합니다. 이 오류는 promptTemplate(Line 43)과 scoring criteria(Line 54) 모두에 존재합니다.참고: 이 동일한 문법 오류가 다른 YAML 파일들(
porters-five-forces.yaml,priority-matrix.yaml,failure-analysis.yaml등)에서도 반복되므로, 전체 75개 YAML 파일에 대해 일괄 수정하는 것을 권장합니다.✏️ 수정 제안
- - 1 points: No pure outsider perspective + - 1 point: No pure outsider perspectivebackend/app/techniques/definitions/terroir/drunk-history-retelling.yaml-42-42 (1)
42-42:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
라인 42의 "1 points"는 단수형 "1 point"로 수정해야 합니다. 이는 기술 정의 파일 전체에 걸쳐 66개 이상의 동일한 문법 오류가 있습니다. 이 파일뿐만 아니라 모든 기술 정의 YAML 파일에서 채점 기준 최하단의 "1 points"를 "1 point"로 일괄 수정하는 것을 권장합니다.
✏️ 수정 제안
- - 1 points: Cannot simplify + - 1 point: Cannot simplifybackend/app/services/graph_builder.py-41-48 (1)
41-48:⚠️ Potential issue | 🟡 Minor독스트링의 토폴로지 설명이 실제 구현과 불일치합니다.
Line 44에서 "Start -> 6 parallel agents -> Synthesis -> End"라고 되어 있지만, 실제로는 5명의 소믈리에가 병렬로 실행되고 Jean-Pierre가 합성(synthesis) 노드입니다 (Line 63 참조).
✏️ 수정 제안
- Topology: Start -> 6 parallel agents -> Synthesis -> End + Topology: Start -> 5 parallel agents -> Synthesis (Jean-Pierre) -> Endbackend/tests/test_technique_loading.py-85-93 (1)
85-93:⚠️ Potential issue | 🟡 Minor
fairthon_source검증 조건이 중복됩니다.Line 86의
valid_values집합에 이미"either","both","pdf","readme"가 포함되어 있으므로, Line 88-93의or이후 조건은 항상 참이 되어 의미가 없습니다.♻️ 수정 제안
- valid_values = {"either", "both", "pdf", "readme", "pdf_only", "readme_only"} - - for value in source_values: - assert value in valid_values or value in [ - "either", - "both", - "pdf", - "readme", - ], f"Unexpected fairthon_source value: {value}" + valid_values = {"either", "both", "pdf", "readme", "pdf_only", "readme_only"} + + for value in source_values: + assert value in valid_values, f"Unexpected fairthon_source value: {value}"backend/tests/test_technique_loading.py-139-145 (1)
139-145:⚠️ Potential issue | 🟡 Minor불필요한
noqa: F401지시문을 제거하세요.이 import 문은
ImportError를 발생시킬 것으로 기대되므로, 실제로 미사용 import 경고(F401)가 발생하지 않습니다. 정적 분석 도구(Ruff)에서도 불필요한 noqa 지시문으로 경고하고 있습니다.✏️ 수정 제안
def test_filter_techniques_not_importable(self): """Test that filter_techniques is no longer importable from loader.""" with pytest.raises(ImportError): - from app.techniques.loader import filter_techniques # noqa: F401 + from app.techniques.loader import filter_techniques def test_determine_available_inputs_not_importable(self): """Test that determine_available_inputs is no longer importable from loader.""" with pytest.raises(ImportError): - from app.techniques.loader import determine_available_inputs # noqa: F401 + from app.techniques.loader import determine_available_inputsbackend/app/techniques/definitions/vintage/plus-points.yaml-46-46 (1)
46-46:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
1 points는 문법적으로 올바르지 않습니다. 단수형1 point로 수정해야 합니다. 이 패턴이 75개 YAML 파일 전체에 걸쳐 반복되므로 일괄 수정이 필요합니다.✏️ 수정 제안
- - 1 points: Difficult to find clear strengths + - 1 point: Difficult to find clear strengthsbackend/tests/test_yaml_english.py-72-74 (1)
72-74:⚠️ Potential issue | 🟡 Minor
name_ko(snake_case) 필드도 함께 검증 필요PR 목표에서
nameKo와name_ko모두 제거한다고 명시되어 있으나, 테스트에서는nameKo만 검사합니다.name_ko필드가 남아있을 가능성도 확인해야 합니다.♻️ 제안된 수정
def test_no_name_ko_field(self): for tech in self.techniques: assert "nameKo" not in tech, f"{tech.get('id')} still has nameKo field" + assert "name_ko" not in tech, f"{tech.get('id')} still has name_ko field"backend/app/techniques/definitions/body/fmea.yaml-47-47 (1)
47-47:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point"
단수형에는 "point"를 사용해야 합니다.
- - 1 points: No failure analysis + - 1 point: No failure analysisbackend/app/techniques/definitions/finish/body-wisdom-dialogue.yaml-41-41 (1)
41-41:⚠️ Potential issue | 🟡 Minor문법 오류: "1 points" → "1 point" (모든 YAML 파일에 일괄 적용 필요)
전체 기술 정의 YAML 파일(약 75개)에서 동일한 오류가 발견됩니다. 단수형 숫자 "1"과 함께 복수형 "points"를 사용한 것이 문법적으로 올바르지 않습니다.
수정 예시
- - 1 points: Physical/sensory experience ignored + - 1 point: Physical/sensory experience ignored모든 기술 정의 YAML 파일에서
1 points를1 point로 일괄 수정하세요.
🧹 Nitpick comments (15)
backend/app/techniques/definitions/palate/first-principles-thinking.yaml (1)
50-54:scoring.criteria와promptTemplate의 텍스트 불일치Line 54의
1: Copied existing solution(단수)과 Line 43의Copied existing solutions as is(복수)가 일치하지 않습니다. 둘 중 하나로 통일하는 것이 좋습니다.backend/app/techniques/definitions/finish/kano-model.yaml (1)
38-41: promptTemplate의 점수 기준과 scoring.criteria 간 미세한 불일치 확인 필요promptTemplate(Line 38)에서는
"5 classifications clear, priority optimized, strong Attractive quality"라고 되어 있지만, scoring.criteria(Line 53)에서는"5 classifications, priority optimized"로 "strong Attractive quality" 부분이 누락되어 있습니다. 마찬가지로 Line 40의"Must-be met, Attractive quality present"에서"Must-be met"부분이 Line 54에는 없습니다. 채점 시 혼동을 방지하려면 양쪽을 일치시키는 것이 좋습니다.backend/app/techniques/definitions/terroir/emotion-orchestra.yaml (1)
49-53: 동일한 문법 오류: scoring criteria 블록에서도 일관성 확인 필요
promptTemplate의 점수 기준과scoring.criteria블록이 동일한 내용을 중복하고 있습니다. 현재는scoring.criteria쪽은 점수 뒤에 "points"가 없어서 문법 문제는 없지만, 두 곳에 동일한 기준 텍스트가 중복 관리되고 있어 향후 불일치 위험이 있습니다.backend/app/techniques/definitions/palate/random-stimulation.yaml (1)
52-57:outputSchema에 "Creative Combination" 관점에 해당하는 필드가 누락되어 있습니다.
promptTemplate의 분석 관점 3번 "Creative Combination"에 대응하는outputSchema필드가 없습니다. 다른 3개 관점(Unexpected Connections, Non-linear Thinking, Serendipity)은 각각unexpectedConnections,nonlinearThinking,serendipityEvidence로 매핑되어 있습니다.creativeCombination필드 추가를 고려해 주세요.♻️ 수정 제안
outputSchema: score: number unexpectedConnections: string[] nonlinearThinking: string + creativeCombination: string serendipityEvidence: string reasoning: stringbackend/app/techniques/definitions/cellar/priority-matrix.yaml (1)
14-14:promptTemplate형식이 다른 YAML 파일들과 불일치이 파일의
promptTemplate는 double-quoted 문자열에\n이스케이프를 사용하고 있으나, 다른 YAML 파일들(alien-anthropologist.yaml,porters-five-forces.yaml등)은 single-quoted block scalar 형식을 사용합니다. 기능적으로는 동일하지만, 유지보수성과 가독성을 위해 형식을 통일하는 것이 좋습니다.ASCII 아트 매트릭스 때문에 이 형식을 선택한 것일 수 있지만, YAML block scalar(
|또는>)로도 동일하게 표현 가능합니다.backend/tests/test_multi_mode.py (1)
134-140: Line 137:import pytest가 중복됩니다.
pytest는 이미 Line 3에서 모듈 레벨로 임포트되어 있으므로 메서드 내부의 재임포트는 불필요합니다.♻️ 수정 제안
def test_old_six_hats_value_rejected(self): """Test that old 'six_hats' value is rejected.""" from app.graph.graph_factory import EvaluationMode - import pytest with pytest.raises(ValueError): EvaluationMode("six_hats")backend/app/models/graph.py (2)
354-357:Graph3DPayload.mode가str로 타입 지정되어 있습니다.
ReactFlowGraph.mode(Line 130)는EvaluationMode를 사용하는 반면,Graph3DPayload.mode는str입니다. 유효하지 않은 모드 값이 3D 페이로드에 유입될 수 있습니다. 이번 PR 범위에서 반드시 수정할 필요는 없지만, 일관성을 위해 향후 통일을 고려해 보세요.
548-551:ModeResponse.mode도str타입입니다.
EvaluationModeenum을 사용하면 API 응답에서 유효하지 않은 모드가 반환되지 않도록 보장할 수 있습니다.backend/app/techniques/registry.py (2)
152-159:get_all_techniques()는list_techniques()와 완전히 동일한 구현입니다.두 메서드의 본문이 동일합니다. 의미적 차이("필터링 없이"라는 의도)를 표현하고 싶다면 하나가 다른 하나에 위임하도록 하여 중복을 제거하는 것이 좋습니다.
♻️ 리팩터링 제안
def get_all_techniques(self) -> List[TechniqueDefinition]: """Return all loaded techniques without filtering. Returns: List of all 75 technique definitions, sorted by ID. """ - self._ensure_loaded() - return sorted(self._techniques, key=lambda t: t.id) + return self.list_techniques()
339-374:has_readme_content유틸리티는 기법 레지스트리와 관심사가 다릅니다.이 함수는 기법 정의/로딩과 직접적인 관련이 없고, 리포지토리 컨텍스트 분석을 담당합니다. 현재 위치도 동작에 문제는 없지만, 향후 유지보수를 위해 별도 유틸리티 모듈(예:
app.techniques.utils또는app.utils.repo)로 분리하는 것을 고려해 보세요.backend/app/services/graph_builder.py (1)
140-151:EvaluationMode.SIX_SOMMELIERS.value대신 enum 직접 전달을 고려하세요.
ReactFlowGraph.mode가EvaluationMode타입으로 정의되어 있으므로(관련 코드:backend/app/models/graph.pyLine 131),.value로 문자열을 전달하는 대신 enum 인스턴스를 직접 전달하면 타입 안전성이 향상됩니다. Pydantic이 문자열 coercion을 지원하므로 현재 코드도 동작하지만, enum을 직접 사용하는 것이 더 명확합니다.♻️ 리팩터링 제안
return ReactFlowGraph( - mode=EvaluationMode.SIX_SOMMELIERS.value, + mode=EvaluationMode.SIX_SOMMELIERS, nodes=nodes, edges=edges,Line 278에도 동일하게 적용:
return ReactFlowGraph( - mode=EvaluationMode.FULL_TECHNIQUES.value, + mode=EvaluationMode.FULL_TECHNIQUES, nodes=nodes, edges=edges,backend/tests/test_technique_loading.py (1)
18-48: 처음 세 개의 테스트(test_all_75_techniques_load,test_get_all_techniques_returns_all_75,test_technique_registry_get_all_techniques)가 거의 동일합니다.세 테스트 모두 기법 수가 75개인지 검증하며, 차이점은 레지스트리 리셋 여부와 호출 경로(모듈 레벨 vs 인스턴스 레벨)뿐입니다. 싱글톤 레지스트리는 프로세스 내에서 상태를 공유하므로,
reset()없이 실행되는 첫 번째 테스트와reset()후 실행되는 두 번째 테스트의 실질적 차이가 테스트 실행 순서에 의존합니다. 테스트 간 격리가 필요하다면 각 테스트에서reset()을 호출하는 것을 고려하세요.backend/tests/test_yaml_english.py (1)
58-70: 한국어 검사 범위가description과promptTemplate에만 한정됨
scoring.criteria값이나metadata.academicReference등 다른 텍스트 필드에도 한국어가 남아있을 수 있습니다. 보다 확실한 검증을 위해 전체 YAML 내용을 대상으로 검사하는 테스트를 추가하는 것을 고려해 보세요.♻️ 전체 텍스트 대상 한국어 검사 예시
+ def test_no_korean_in_any_text_field(self): + for tech in self.techniques: + raw_text = yaml.dump(tech, allow_unicode=True) + assert not KOREAN_PATTERN.search(raw_text), ( + f"{tech.get('id')} has Korean characters in YAML content" + )backend/app/api/routes/graph.py (1)
80-96:GRAND_TASTING모드에 대한 전용 토폴로지 빌더 부재
_determine_mode에서GRAND_TASTING을 인식하지만,get_graph/get_graph_structure/get_graph_execution엔드포인트에서는FULL_TECHNIQUES가 아닌 모든 모드에 대해build_six_sommeliers_topology()를 사용합니다. 현재 의도된 동작이라면 코드 코멘트로 명시해 두는 것이 좋겠습니다.backend/tests/test_graph_api.py (1)
368-402: 모드 감지 테스트가 핵심 시나리오를 잘 커버합니다
six_sommeliers,full_techniques,evaluation_mode필드 우선순위, 기본값 폴백 등_determine_mode의 핵심 분기를 모두 검증하고 있습니다.grand_tasting모드에 대한 테스트도 추가하면 더욱 완벽해질 것입니다.
- Add hypothesis to requirements.txt for property-based tests - Fix webgl.ts: use useSyncExternalStore instead of setState in useEffect - Migrate Pydantic class Config to ConfigDict (6 files) - Fix datetime.utcnow() deprecation (use timezone-aware datetime.now) - Remove unused imports and prefix unused vars with underscore (33 warnings) - Add else block comments for mode handling (Gemini review) - Fix grammar: '1 points' → '1 point' in 75 YAML files (CodeRabbit review)
- page.tsx: use useState lazy initializer for random velocities - GraphView3D.tsx: derive viewMode from webglSupported instead of useEffect
- Add status_code class attribute to CorkedError (was using default_status_code) - Update datetime.utcnow() to datetime.now(timezone.utc) in test_models_repository.py - Update graph structure tests for new enrichment nodes (code_analysis_enrich, web_search_enrich) - Update expected node counts: RAG enabled=10, RAG disabled=9 (includes __start__) - Update trajectory tests for new edge structure with enrichment nodes
Summary
Epic #223 — Group A Foundation 구현. Fairthon 75기법 평가 시스템 이식을 위한 기반 모듈 4개를 병렬로 구현했습니다.
Changes
#224 — 75기법 GitHub 재분류
input_source필드 제거,fairthon_source필드로 원본 YAML 값 보존filter_techniques(),determine_available_inputs()함수 제거get_all_techniques(),has_readme_content()유틸리티 추가evaluation_service.py업데이트 — 소스 기반 필터링 제거#225 — 영문 YAML 템플릿 교체
category필드를 와인 테마 폴더명으로 매핑 (problem-analysis → aroma 등)nameKo필드 제거 (schema + 모든 YAML)#226 — EvaluationMode 통일
EvaluationModeenum을models/graph.py에 단일 정의 (Single Source of Truth)SIX_HATS→SIX_SOMMELIERS전면 교체FULL_TECHNIQUES모드 추가_determine_mode()개선:evaluation_mode필드 우선 확인#227 — BMAD 17항목 평가 기준 정의
backend/app/criteria/모듈 신규 생성기존 테스트 버그 수정
_check_ownership3-파라미터 시그니처에 맞게 인증 테스트 수정Testing
test_bmad_items.py— 13 tests (BMAD 점수 합계, 카테고리별 검증)test_yaml_english.py— 6 tests (75개 YAML 로딩, 한국어 미포함 확인)test_technique_loading.py— 27 tests (기법 로딩, fairthon_source 보존)test_graph_factory.py— EvaluationMode enum 검증test_graph_schemas.py— 그래프 모델 스키마 검증test_graph_contracts.py— 모드별 그래프 토폴로지 검증test_graph_api.py— API 인증/권한/스키마 검증test_auth_scope.py— OAuth 스코프 검증Checklist
Next Steps
Closes #224, Closes #225, Closes #226, Closes #227
Summary by CodeRabbit
새로운 기능
개선사항