Skip to content

Commit 4752b26

Browse files
authored
Merge pull request #256 from Two-Weeks-Team/feat/group-a-foundation
feat(group-a): Foundation for Fairthon 75-Technique system (#224, #225, #226, #227)
2 parents 5709450 + 30c2720 commit 4752b26

129 files changed

Lines changed: 2740 additions & 2115 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

backend/app/api/routes/graph.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@
2121
}
2222
from app.core.exceptions import CorkedError, EmptyCellarError
2323
from app.database.repositories.evaluation import EvaluationRepository
24+
from app.graph.graph_factory import EvaluationMode
2425
from app.models.graph import (
2526
ReactFlowGraph,
2627
TraceEvent,
2728
ModeResponse,
28-
EvaluationMode,
2929
Graph3DPayload,
3030
)
3131
from app.services.graph_builder import (
32-
build_six_hats_topology,
32+
build_six_sommeliers_topology,
3333
build_full_techniques_topology,
3434
)
3535
from app.services.graph_builder_3d import build_3d_graph
@@ -66,11 +66,11 @@ def _check_ownership(evaluation: dict[str, Any], user, evaluation_id: str) -> No
6666
# Allow access to public demo evaluations without auth
6767
if evaluation_id in PUBLIC_DEMO_EVALUATIONS:
6868
return
69-
69+
7070
# Require auth for non-public evaluations
7171
if user is None:
7272
raise CorkedError("Authentication required to view this evaluation")
73-
73+
7474
if evaluation.get("user_id") != user.id:
7575
raise CorkedError(
7676
"Access denied: evaluation belongs to another user", status_code=403
@@ -84,14 +84,16 @@ def _determine_mode(evaluation: dict[str, Any]) -> EvaluationMode:
8484
evaluation: The evaluation document.
8585
8686
Returns:
87-
EvaluationMode (six_hats or full_techniques).
87+
EvaluationMode (six_sommeliers, grand_tasting, or full_techniques).
8888
"""
89-
# Check for explicit mode in evaluation data
90-
mode = evaluation.get("mode")
89+
# Check for explicit evaluation_mode first, then fall back to mode
90+
mode = evaluation.get("evaluation_mode") or evaluation.get("mode")
9191
if mode == EvaluationMode.FULL_TECHNIQUES.value:
9292
return EvaluationMode.FULL_TECHNIQUES
93-
# Default to six_hats mode
94-
return EvaluationMode.SIX_HATS
93+
if mode == EvaluationMode.GRAND_TASTING.value:
94+
return EvaluationMode.GRAND_TASTING
95+
# Default to six_sommeliers mode
96+
return EvaluationMode.SIX_SOMMELIERS
9597

9698

9799
@router.get("/{evaluation_id}/graph", response_model=ReactFlowGraph)
@@ -132,8 +134,8 @@ async def get_graph(
132134

133135
if mode == EvaluationMode.FULL_TECHNIQUES:
134136
graph = build_full_techniques_topology()
135-
else:
136-
graph = build_six_hats_topology()
137+
else: # SIX_SOMMELIERS, GRAND_TASTING
138+
graph = build_six_sommeliers_topology()
137139

138140
logger.info(f"[Graph] Returning {mode.value} graph for {evaluation_id}")
139141
return graph
@@ -159,8 +161,8 @@ async def get_graph_structure(
159161
mode = _determine_mode(evaluation)
160162
if mode == EvaluationMode.FULL_TECHNIQUES:
161163
graph = build_full_techniques_topology()
162-
else:
163-
graph = build_six_hats_topology()
164+
else: # SIX_SOMMELIERS, GRAND_TASTING
165+
graph = build_six_sommeliers_topology()
164166

165167
return graph
166168

@@ -185,8 +187,8 @@ async def get_graph_execution(
185187
mode = _determine_mode(evaluation)
186188
if mode == EvaluationMode.FULL_TECHNIQUES:
187189
graph = build_full_techniques_topology()
188-
else:
189-
graph = build_six_hats_topology()
190+
else: # SIX_SOMMELIERS, GRAND_TASTING
191+
graph = build_six_sommeliers_topology()
190192

191193
methodology_trace = evaluation.get("methodology_trace", [])
192194
if methodology_trace:
@@ -268,7 +270,7 @@ async def get_mode(
268270
) -> ModeResponse:
269271
"""Get current evaluation mode.
270272
271-
Returns the evaluation mode (six_hats or full_techniques)
273+
Returns the evaluation mode (six_sommeliers, grand_tasting, or full_techniques)
272274
for the specified evaluation.
273275
274276
Public demo evaluations can be accessed without authentication.

backend/app/core/config.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Application settings and configuration"""
22

33
import secrets
4-
from pydantic_settings import BaseSettings
4+
from pydantic_settings import BaseSettings, SettingsConfigDict
55
from typing import List
66

77

@@ -15,6 +15,12 @@ class Settings(BaseSettings):
1515
The default random value is only for development convenience.
1616
"""
1717

18+
model_config = SettingsConfigDict(
19+
env_file=".env",
20+
env_file_encoding="utf-8",
21+
case_sensitive=True,
22+
)
23+
1824
APP_NAME: str = "Somm.dev API"
1925
API_V1_STR: str = "/api"
2026

@@ -38,6 +44,7 @@ class Settings(BaseSettings):
3844

3945
# LLM APIs
4046
GEMINI_API_KEY: str = ""
47+
OPENAI_API_KEY: str = ""
4148

4249
# Vertex AI Express (API key auth)
4350
VERTEX_API_KEY: str = ""
@@ -79,10 +86,5 @@ def CORS_ORIGINS(self) -> List[str]:
7986
origins.append(self.FRONTEND_URL.replace("https://www.", "https://", 1))
8087
return origins
8188

82-
class Config:
83-
env_file = ".env"
84-
env_file_encoding = "utf-8"
85-
case_sensitive = True
86-
8789

8890
settings = Settings()

backend/app/core/exceptions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ class CorkedError(HTTPException):
2121
analogous to a spoiled or invalid request.
2222
"""
2323

24-
default_status_code = status.HTTP_400_BAD_REQUEST
24+
status_code = status.HTTP_400_BAD_REQUEST
2525
default_detail = "Invalid request data - the request is corked"
2626

2727
def __init__(self, detail: str = None, status_code: int = None):
2828
super().__init__(
29-
status_code=status_code or self.default_status_code,
29+
status_code=status_code or self.__class__.status_code,
3030
detail=detail or self.default_detail,
3131
)
3232

backend/app/core/logging.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import logging
77
import sys
8-
from datetime import datetime
8+
from datetime import datetime, timezone
99
from pathlib import Path
1010

1111

@@ -21,7 +21,7 @@ def setup_logging() -> logging.Logger:
2121
log_dir = Path(__file__).parent.parent.parent / "logs"
2222
log_dir.mkdir(exist_ok=True)
2323

24-
log_filename = log_dir / f"somm_{datetime.utcnow().strftime('%Y%m%d')}.log"
24+
log_filename = log_dir / f"somm_{datetime.now(timezone.utc).strftime('%Y%m%d')}.log"
2525

2626
logger = logging.getLogger("somm")
2727
logger.setLevel(logging.DEBUG)

backend/app/criteria/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Evaluation criteria module for BMAD 17-item scoring system."""

0 commit comments

Comments
 (0)