Skip to content

feat(group-a): Foundation for Fairthon 75-Technique system (#224, #225, #226, #227)#256

Merged
ComBba merged 6 commits into
mainfrom
feat/group-a-foundation
Feb 9, 2026
Merged

feat(group-a): Foundation for Fairthon 75-Technique system (#224, #225, #226, #227)#256
ComBba merged 6 commits into
mainfrom
feat/group-a-foundation

Conversation

@ComBba

@ComBba ComBba commented Feb 9, 2026

Copy link
Copy Markdown
Contributor

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 템플릿 교체

  • Fairthon 레포에서 75개 영문 YAML 파일 가져오기
  • category 필드를 와인 테마 폴더명으로 매핑 (problem-analysis → aroma 등)
  • nameKo 필드 제거 (schema + 모든 YAML)

#226 — EvaluationMode 통일

  • EvaluationMode enum을 models/graph.py에 단일 정의 (Single Source of Truth)
  • SIX_HATSSIX_SOMMELIERS 전면 교체
  • FULL_TECHNIQUES 모드 추가
  • _determine_mode() 개선: evaluation_mode 필드 우선 확인
  • 프론트엔드 TypeScript 타입 업데이트

#227 — BMAD 17항목 평가 기준 정의

  • backend/app/criteria/ 모듈 신규 생성
  • 17개 평가 항목 정의 (A1~D4, 총 100점)
    • A: Problem Definition (25pts)
    • B: Technical Design (25pts)
    • C: Implementation (30pts)
    • D: Documentation (20pts)

기존 테스트 버그 수정

  • _check_ownership 3-파라미터 시그니처에 맞게 인증 테스트 수정
  • localhost 환경에서 Secure 쿠키 플래그 조건부 검증

Testing

135 passed, 0 failed
  • 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

  • 코드가 프로젝트 컨벤션을 따름
  • 모든 테스트 통과 (135/135)
  • Breaking changes 없음 (기존 six_sommeliers, grand_tasting 모드 유지)
  • 기존 테스트 버그 수정 포함

Next Steps

Closes #224, Closes #225, Closes #226, Closes #227

Summary by CodeRabbit

  • 새로운 기능

    • 새로운 평가 모드 "Grand Tasting" 추가 및 전체 기법 모드 지원 확대
    • OpenAI API 키 설정 지원 추가
  • 개선사항

    • "Six Hats" 명칭을 "Six Sommeliers"로 변경
    • 모든 기법 정의의 영어 현지화 완료
    • 각 기법의 출력 스키마를 확장하여 추론·세부 인사이트 등 더 풍부한 분석 결과 제공

@ComBba ComBba self-assigned this Feb 9, 2026
@vercel

vercel Bot commented Feb 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
somm-dev Ready Ready Preview, Comment Feb 9, 2026 7:41am

Request Review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Feb 9, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@ComBba has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 16 minutes and 25 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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

Cohort / File(s) Summary
기법 YAML 영어화
backend/app/techniques/definitions/aroma/*, backend/app/techniques/definitions/balance/*, backend/app/techniques/definitions/body/*, backend/app/techniques/definitions/cellar/*, backend/app/techniques/definitions/finish/*, backend/app/techniques/definitions/palate/*, backend/app/techniques/definitions/terroir/*, backend/app/techniques/definitions/vintage/*
모든 75개 기법 YAML을 한국어→영어로 대체. nameKo 제거, description/promptTemplate/scoring 영어화, 다수 파일의 outputSchema 확장 및 메타데이터 필드 추가.
기법 시스템 리팩토링
backend/app/techniques/schema.py, backend/app/techniques/loader.py, backend/app/techniques/registry.py, backend/app/techniques/__init__.py
name_ko 제거. requiredSources를 그대로 보존하는 fairthon_source로 변경. determine_available_inputs·filter_techniques 제거(소스 기반 필터링 중단). get_all_techniques()·has_readme_content() 추가 및 all 변경.
평가 모드 통일 및 이동
backend/app/graph/graph_factory.py, backend/app/models/graph.py, backend/app/api/routes/graph.py, backend/app/services/graph_builder.py, frontend/src/types/index.ts
EvaluationMode 정의를 한 곳으로 통일(graph_factory), SIX_HATSSIX_SOMMELIERS로 명칭 변경, GRAND_TASTING 추가, FULL_TECHNIQUES 유지. 라우트와 빌더 함수명(build_six_hats_topologybuild_six_sommeliers_topology) 및 관련 참조 업데이트. mode 결정 로직이 evaluation_mode 필드를 우선 사용하도록 조정.
BMAD 기준 프레임워크 추가
backend/app/criteria/__init__.py, backend/app/criteria/bmad_items.py, backend/tests/test_bmad_items.py
BMAD 17항목(A1–D4, 합계 100점) 불변 데이터 모델(BMADItem/BMADCategory) 추가 및 조회 유틸리티(get_item, list_items, get_max_total 등)와 관련 단위테스트 추가.
설정·테스트·기타 변경
backend/app/core/config.py, backend/tests/conftest.py, backend/tests/*, backend/tests/test_yaml_english.py, backend/tests/test_technique_loading.py
환경변수 OPENAI_API_KEY 추가. 테스트 픽스처·기대값을 six_sommeliers로 갱신. 새로운 YAML 영어화·기법 로딩·레지스트리 관련 테스트 대거 추가 및 레거시 필터 관련 테스트 제거/수정. 그래프/캐시/컨트랙트 테스트에서 모드명 일괄 변경.

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: 그래프 페이로드 반환
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

Suggested labels

enhancement

요약

종합 분석

Walkthrough

이 PR은 기법 시스템의 대규모 현대화와 통일을 구현합니다. 75개 기법의 YAML을 한국어에서 영어로 전환하고, 소스별 필터링을 제거하여 모든 기법을 GitHub 데이터로 처리하게 변경합니다. 평가 모드를 통일하고(SIX_HATS → SIX_SOMMELIERS, GRAND_TASTING, FULL_TECHNIQUES 추가), BMAD 17항목 평가 프레임워크를 도입합니다.

Changes

Cohort / File(s) Summary
기법 YAML 영어화
backend/app/techniques/definitions/aroma/*, balance/*, body/*, cellar/*, finish/*, palate/*, terroir/*, vintage/*
모든 75개 기법 YAML을 한국어에서 영어로 번역. 설명, promptTemplate, 채점 기준을 영어로 변경. nameKo 필드 제거. 다수 파일에 outputSchema 확장(논리, 추론, 추가 분석 필드 추가). 메타데이터 블록 추가(복잡도, 토큰, 소스).
기법 시스템 리팩토링
backend/app/techniques/schema.py, backend/app/techniques/loader.py, backend/app/techniques/registry.py, backend/app/techniques/__init__.py
input_source 매핑 로직 제거. name_ko 필드 삭제. requiredSources를 fairthon_source로 보존. filter_techniques, determine_available_inputs 함수 제거. get_all_techniques(), has_readme_content() 추가. 모든 75개 기법이 필터링 없이 로드됨.
평가 모드 통일
backend/app/graph/graph_factory.py, backend/app/models/graph.py, backend/app/api/routes/graph.py, backend/app/services/graph_builder.py, frontend/src/types/index.ts
EvaluationMode를 graph_factory.py로 이동(단일 소스). SIX_HATS → SIX_SOMMELIERS로 변경. GRAND_TASTING, FULL_TECHNIQUES 추가. build_six_hats_topology → build_six_sommeliers_topology로 함수명 변경. 모든 참조 업데이트.
BMAD 기준 프레임워크
backend/app/criteria/__init__.py, backend/app/criteria/bmad_items.py, backend/tests/test_bmad_items.py
17항목 BMAD 평가 시스템 정의(A1-D4, 총 100점). 불변 데이터 구조(BMADItem, BMADCategory). 항목 및 카테고리 레지스트리. 유틸리티 함수(get_item, list_items, get_max_total).
설정 및 테스트 업데이트
backend/app/core/config.py, backend/tests/conftest.py, backend/tests/test_*.py
OPENAI_API_KEY 환경변수 추가. 테스트 픽스처와 기대값을 six_sommeliers 모드로 업데이트. 새 테스트 추가(YAML 영어화, BMAD 항목, 기법 로딩). 레거시 함수 및 필터링 로직 제거.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

Suggested labels

enhancement

Poem

🥕🍷
75개의 기법이 영어로 춤추네,
모드는 소믈리에처럼 정렬되고,
BMAD는 백 점의 향을 담아
필터 없이 모두 함께 빚어낸다.
토스트! 한 모금 더!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR title clearly summarizes the main change: implementing Group A Foundation for the Fairthon 75-Technique system, covering four parallel modules (#224-#227).
Linked Issues check ✅ Passed Code changes comprehensively implement all four linked issue requirements [#224-#227]: techniques reclassification, English YAML migration, EvaluationMode consolidation, and BMAD criteria definition.
Out of Scope Changes check ✅ Passed All changes directly support the four linked objectives. Test fixes (Secure cookie, ownership check) and environment variable updates are necessary supporting changes within scope.
Docstring Coverage ✅ Passed Docstring coverage is 93.33% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/group-a-foundation

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello @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

  • Fairthon 75-Technique System Foundation: This pull request establishes the foundational modules for the Fairthon 75-Technique evaluation system, integrating several key components in parallel.
  • Technique Reclassification and Filtering Logic Update: The input_source field has been removed from technique definitions, replaced by fairthon_source to preserve original YAML values. Source-based filtering functions (filter_techniques, determine_available_inputs) have been removed, and new utilities (get_all_techniques, has_readme_content) were added to manage techniques without prior filtering.
  • English YAML Template Replacement: All 75 YAML technique definition files have been updated to English, removing the nameKo field and mapping categories to wine-themed folder names (e.g., 'problem-analysis' to 'aroma').
  • EvaluationMode Standardization: The EvaluationMode enum is now centrally defined in models/graph.py as the single source of truth. SIX_HATS has been renamed to SIX_SOMMELIERS, and a new FULL_TECHNIQUES mode has been added. The mode determination logic now prioritizes the evaluation_mode field.
  • BMAD 17-Item Evaluation Criteria: A new module backend/app/criteria/ has been created to define 17 specific evaluation items (A1-D4) across four categories: Problem Definition (25pts), Technical Design (25pts), Implementation (30pts), and Documentation (20pts), totaling 100 points.
  • Test Bug Fixes: Existing test bugs related to _check_ownership parameter signature and conditional Secure cookie flag verification for localhost environments have been resolved.
Changelog
  • backend/app/api/routes/graph.py
    • Updated EvaluationMode import to app.graph.graph_factory.
    • Renamed build_six_hats_topology to build_six_sommeliers_topology.
    • Modified _determine_mode to prioritize evaluation_mode field and default to SIX_SOMMELIERS.
    • Adjusted _check_ownership to conditionally assert 'Secure' cookie for localhost.
  • backend/app/core/config.py
    • Added OPENAI_API_KEY to application settings.
  • backend/app/criteria/init.py
    • New file: Initialized evaluation criteria module.
  • backend/app/criteria/bmad_items.py
    • New file: Defined 17 BMAD evaluation items and their categories (Problem Definition, Technical Design, Implementation, Documentation) with detailed rubrics and scoring.
  • backend/app/graph/graph_factory.py
    • Removed local EvaluationMode enum definition.
    • Imported EvaluationMode from app.models.graph to ensure a single source of truth.
  • backend/app/models/graph.py
    • Centralized EvaluationMode enum definition.
    • Renamed SIX_HATS to SIX_SOMMELIERS.
    • Added GRAND_TASTING and FULL_TECHNIQUES to EvaluationMode.
    • Updated descriptions for ReactFlowGraph, Graph3DNode, Graph3DPayload, and ModeResponse to reflect new evaluation modes.
  • backend/app/services/evaluation_service.py
    • Removed imports for determine_available_inputs and filter_techniques.
    • Modified _prepare_repo_context to load all 75 techniques without source-based filtering.
  • backend/app/services/graph_builder.py
    • Updated EvaluationMode import to app.graph.graph_factory.
    • Renamed build_six_hats_topology to build_six_sommeliers_topology and updated its return mode.
  • backend/app/techniques/init.py
    • Removed determine_available_inputs and filter_techniques from imports and __all__.
    • Added get_all_techniques and has_readme_content to exports.
  • backend/app/techniques/definitions/*.yaml
    • Removed the nameKo field from all YAML technique definitions.
    • Translated descriptions and prompt templates to English.
    • Updated academicReference fields in some YAML files to English.
  • backend/app/techniques/loader.py
    • Removed determine_available_inputs and filter_techniques functions.
  • backend/app/techniques/registry.py
    • Added get_all_techniques method to TechniqueRegistry to retrieve all techniques without filtering.
    • Introduced has_readme_content utility function to check for README presence in repository context.
  • backend/app/techniques/schema.py
    • Removed name_ko field from TechniqueDefinition.
    • Replaced input_source with fairthon_source (Optional[str]) and removed the __init__ logic for requiredSources mapping.
  • backend/tests/conftest.py
    • Removed OPENAI_API_KEY from environment variable setup.
  • backend/tests/fixtures/graph/valid_reactflow_graph.json
    • Updated mode from six_hats to six_sommeliers.
  • backend/tests/test_auth_scope.py
    • Modified test_github_oauth_url_structure to conditionally assert 'Secure' cookie for localhost.
    • Refactored authentication and authorization tests for clarity and correctness with _check_ownership.
  • backend/tests/test_bmad_items.py
    • New file: Added comprehensive tests for the BMAD 17-item evaluation canon, verifying item counts, category sums, rubrics, and retrieval functions.
  • backend/tests/test_graph_api.py
    • Updated EvaluationMode import and mock evaluation fixture name.
    • Adjusted _determine_mode tests to reflect SIX_SOMMELIERS and evaluation_mode field priority.
  • backend/tests/test_graph_cache.py
    • Updated cache key generation tests to use six_sommeliers mode.
  • backend/tests/test_graph_contracts.py
    • Updated EvaluationMode import and enum value tests, including a test to reject the old six_hats value.
    • Updated graph mode values in ReactFlowGraph and Graph3DPayload tests.
  • backend/tests/test_graph_factory.py
    • Added test for FULL_TECHNIQUES enum value.
  • backend/tests/test_multi_mode.py
    • Updated EvaluationMode import and constants, including a test to reject the old six_hats value.
  • backend/tests/test_technique_loading.py
    • New file: Added tests for loading all 75 techniques, fairthon_source preservation, removal of input_source, and the has_readme_content utility.
  • backend/tests/test_techniques_loader.py
    • Removed tests for filter_techniques and determine_available_inputs as these functions are no longer present.
  • backend/tests/test_yaml_english.py
    • New file: Added tests to ensure all YAML technique definitions are in English, do not contain the nameKo field, and use wine-themed categories.
  • frontend/src/types/index.ts
    • Added full_techniques to the EvaluationMode type definition.
Activity
  • Four core modules for the Fairthon 75-Technique evaluation system were implemented in parallel.
  • Existing test bugs were identified and fixed, ensuring system stability.
  • All 135 tests passed successfully, covering new features and existing functionalities.
  • The pull request adheres to project conventions, includes comprehensive testing, and introduces no breaking changes, while maintaining compatibility with existing modes.
  • The next steps involve extending EvaluationState and mapping 'Hat' concepts to the new 'BMAD' criteria, completing Group A development.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread backend/app/api/routes/graph.py Outdated
@@ -133,7 +135,7 @@ async def get_graph(
if mode == EvaluationMode.FULL_TECHNIQUES:
graph = build_full_techniques_topology()
else:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

코드의 명확성과 향후 유지보수성을 위해, else 블록이 어떤 모드를 처리하는지 주석으로 명시하는 것이 좋습니다. 현재 구현은 GRAND_TASTING 모드를 암시적으로 처리하고 있어 혼란을 줄 수 있습니다. 이 의견은 get_graph_structureget_graph_execution의 유사한 로직에도 적용됩니다.

Suggested change
else:
else: # Handles SIX_SOMMELIERS and GRAND_TASTING

@ComBba ComBba changed the base branch from master to main February 9, 2026 07:08

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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: either
backend/app/techniques/definitions/body/pre-mortem.yaml (1)

16-61: ⚠️ Potential issue | 🟡 Minor

프롬프트가 outputSchema 필드를 직접 요청하지 않아 결과 누락 위험

outputSchemaassumedFailure가 있는데 프롬프트는 이를 명시적으로 수집하지 않습니다. 모델 출력이 누락되거나 불안정해질 수 있으니 프롬프트에 필드별 출력 지시를 추가하세요.

🛠️ 제안 수정안
-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 score
backend/app/techniques/definitions/palate/reversal-inversion.yaml (1)

54-59: ⚠️ Potential issue | 🟠 Major

outputSchema의 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_sommeliersgrand_tasting만 표시하고 full_techniques를 누락하고 있습니다. EvaluationMode enum에서 동적으로 생성하는 것이 좋습니다.

🔧 동적 에러 메시지 제안
-        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_type Field 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_sommeliersmock_evaluation_full_techniques fixture 제거 필요

두 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_graphgraph_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 consideration
backend/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 future
backend/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 symptoms
backend/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 Thinking
backend/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 blending
backend/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 ignored
backend/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 strategy
backend/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 analysis
backend/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 needs
backend/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 vision
backend/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 ignored
backend/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 considered
backend/app/techniques/definitions/palate/random-stimulation.yaml-8-42 (1)

8-42: ⚠️ Potential issue | 🟡 Minor

영문 템플릿 전환이 잘 적용되었습니다.

설명, 프롬프트 템플릿, 채점 기준이 영문으로 올바르게 전환되었으며, 분석 관점과 채점 기준이 Random Stimulation 기법의 특성에 맞게 잘 구성되어 있습니다.

단, Line 40에 문법 오류가 있습니다: 1 points1 point (단수형).

✏️ 문법 수정 제안
-  - 1 points: All connections are obvious and linear
+  - 1 point: All connections are obvious and linear
backend/app/techniques/definitions/aroma/data-mining.yaml-10-44 (1)

10-44: ⚠️ Potential issue | 🟡 Minor

영어 번역 및 프롬프트 템플릿이 잘 구성되어 있습니다.

한국어에서 영어로의 전환이 명확하고, 분석 관점과 채점 기준이 잘 정리되어 있습니다. 다만 Line 42에서 문법 오류가 있습니다:

1 points1 point (단수형이어야 합니다)

✏️ 수정 제안
-  - 1 points: No data-driven decision making
+  - 1 point: No data-driven decision making
backend/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 approach
backend/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 analysis
backend/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 evaluate
backend/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 analysis
backend/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 analysis

Line 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 analysis
backend/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-limitation
backend/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 thinking
backend/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 definition
backend/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 users
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/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 inaccurate
backend/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 sporadically
backend/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 is
backend/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 applied1 element partially applied가 되어야 합니다.

📝 수정 제안
-    2: 1 element partial applied
+    2: 1 element partially applied
backend/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/recovery
backend/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 reference

Line 54도 동일:

-    1: No external reference

(이 줄은 숫자만 있으므로 문제 없습니다)

backend/app/techniques/definitions/cellar/synthesis-framework.yaml-11-54 (1)

11-54: ⚠️ Potential issue | 🟡 Minor

LGTM - 영어 번역 및 스키마 확장이 적절합니다.

전반적으로 영어 번역과 outputSchema 확장이 잘 구성되어 있습니다. 한 가지 사소한 문법 오류가 있습니다: Line 43에서 1 points1 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 analysis
backend/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 perspective
backend/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

creativeleapEvidencecreativeLeapEvidence camelCase 오류

outputSchema의 다른 필드들(provocativeIdeas, industryNormsChallenged)은 모두 올바른 camelCase를 사용하고 있으나, creativeleapEvidenceL이 소문자로 되어 있어 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 Operational
backend/tests/test_auth_scope.py (1)

59-60: Secure 플래그가 이 테스트에서 실제로 검증되지 않습니다.

mock_github_settings fixture(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_header
backend/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 Analysis
backend/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: string
backend/app/criteria/bmad_items.py (2)

19-26: frozen 데이터클래스 내 mutable 컬렉션 사용

BMADCategoryitems: List[str]BMADItemrubric: Dict[int, str]frozen=True임에도 내부 변이가 가능합니다. frozen=True는 속성 재할당만 방지하며, 리스트나 딕셔너리 자체의 변이(.append(), [key] = value)는 막지 못합니다.

정적 읽기 전용 레지스트리의 의도에 맞게 tupleMappingProxyType (또는 간단히 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 total
backend/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 수집 단계에서 전체 파일의 모든 테스트가 실패합니다. pytest fixture로 전환하면 개별 테스트 실패로 격리할 수 있습니다.

♻️ 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 = True
backend/tests/test_multi_mode.py (1)

134-140: 모듈 레벨에서 이미 import된 pytest를 메서드 내부에서 중복 import

Line 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가 missing evaluation_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개)이지만 metadatatotal_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), 다른 테스트들은 호출하지 않습니다. 싱글톤 특성상 테스트 실행 순서에 따라 레지스트리 상태가 공유됩니다. 현재는 읽기 전용 접근이라 문제가 없지만, 추후 테스트가 확장되면 pytest fixture로 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: 한국어 검사 범위가 descriptionpromptTemplate에만 한정됨

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: TestAuthenticationTestAuthorization에 중복 테스트 로직

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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 yaml

Repository: 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 yaml

Repository: 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.

Suggested change
- 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:")으로 제한하세요.

Comment thread backend/app/techniques/definitions/body/swot-analysis.yaml Outdated
Comment on lines +35 to 36
- 5 points: Effectively applied solutions from completely different industries

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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 -3

Repository: 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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 | 🟡 Minor

45줄의 문법 오류: "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 generated
backend/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_modeFULL_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_resultsgrand_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_HATSSIX_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 mode
backend/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_evaluationNone을 반환하는지만 검증합니다. 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 analysis
backend/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 is
backend/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 considered
backend/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-mortem
backend/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 evaluate
backend/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 ignored
backend/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 future
backend/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 thinking
backend/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 considered
backend/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 ignored
backend/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 metaphors
backend/app/techniques/definitions/body/risk-matrix.yaml-10-12 (1)

10-12: ⚠️ Potential issue | 🟡 Minor

description에 불필요한 후행 공백/개행 포함

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 structure
backend/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 generated
backend/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 applied
backend/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/blocking
backend/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/recovery
backend/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 frustrating
backend/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 elements
backend/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/imagination
backend/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 emotion
backend/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 thinking
backend/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 flexibility
backend/app/techniques/definitions/cellar/balanced-scorecard.yaml-16-16 (1)

16-16: ⚠️ Potential issue | 🟡 Minor

HBR 참고 문헌 명칭이 일관되지 않습니다.

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 synthesis
backend/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 only
backend/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 perspective
backend/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 simplify
backend/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) -> End
backend/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_inputs
backend/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 strengths
backend/tests/test_yaml_english.py-72-74 (1)

72-74: ⚠️ Potential issue | 🟡 Minor

name_ko (snake_case) 필드도 함께 검증 필요

PR 목표에서 nameKoname_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 analysis
backend/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 points1 point로 일괄 수정하세요.

🧹 Nitpick comments (15)
backend/app/techniques/definitions/palate/first-principles-thinking.yaml (1)

50-54: scoring.criteriapromptTemplate의 텍스트 불일치

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: string
backend/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.modestr로 타입 지정되어 있습니다.

ReactFlowGraph.mode(Line 130)는 EvaluationMode를 사용하는 반면, Graph3DPayload.modestr입니다. 유효하지 않은 모드 값이 3D 페이로드에 유입될 수 있습니다. 이번 PR 범위에서 반드시 수정할 필요는 없지만, 일관성을 위해 향후 통일을 고려해 보세요.


548-551: ModeResponse.modestr 타입입니다.

EvaluationMode enum을 사용하면 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.modeEvaluationMode 타입으로 정의되어 있으므로(관련 코드: backend/app/models/graph.py Line 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: 한국어 검사 범위가 descriptionpromptTemplate에만 한정됨

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant