13 KiB
13 KiB
| phase | agent | agent_version | generated_at | workstream | concerns | concerns_checked | workers_spawned | planned_workers | actual_workers | self_verification | references | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| implementation | implementation-advisor | 1 | 2026-06-24T11:45:00+09:00 | W2-3-잼 평가 동결 스키마(심사점수/인기투표/시상집계 + jam_score_stats VIEW) | true | 1 | 1 | 1 |
|
|
구현 보고 — W2-3 잼 평가 동결 스키마
변경 목록
| 파일 | worker | 결과 요약 |
|---|---|---|
| docs/jam-eval-ddl.sql (신규, 194줄) | migration-writer w-001 | 권위 DDL. 설계 96~291줄 verbatim. 4테이블+1VIEW+9FK+4CHECK+4UNIQUE+4보조인덱스 |
| db/schema.sql (수정, 596→792줄, +196) | migration-writer w-001 | jam_judges 블록 뒤 동기 사본 append. 본문 byte-identical(diff 0) |
설계 파일 영향 맵(441~445줄)이 확정한 본 W2-3 산출물 = 정확히 이 2건. 매퍼/POJO/컨트롤러/JSP/테스트는 하류 W2-4/5/6 소유(447~453줄) → 본 advisor 생성 0(아래 §설계와의 차이 참조).
Bash 단계 (advisor 직접)
grep -c 'CREATE TABLE IF NOT EXISTS' docs/jam-eval-ddl.sql→ 4 (AC-T1 PASS)grep -c 'CREATE OR REPLACE VIEW' docs/jam-eval-ddl.sql→ 1 (AC-T1 PASS)grep -c 'CREATE UNIQUE INDEX' docs/jam-eval-ddl.sql→ 4 (AC-T3 PASS, >=4)- schema.sql 동기 사본: jam_criteria/jam_scores/jam_votes/jam_awards 각 1 + jam_score_stats VIEW 1 → 전수 존재 (AC-T1 동기 누락 검출 PASS)
grep -cE 'ALTER TABLE .*game_review|CREATE TABLE .*game_review' docs/jam-eval-ddl.sql→ 0 (AC-T5 단방향 write 0 PASS)- verbatim 정합:
diff(jam-eval-ddl 본문 vs schema.sql 신규 블록) → 0줄(권위=사본 드리프트 0) - append 경계: 596줄
ON "jam_judges" ("jam_id");(W2-2 끝) → 599줄 평가 헤더. 기존 블록 무변경. ./mvnw -o test-compile(JAVA_HOME=openjdk@21) → EXIT=0, test-classes 산출 확인(기존 코드 회귀 0). 실행 안 함(verification 영역).git status --short:M db/schema.sql,?? docs/jam-eval-ddl.sql— src/ 변경 0.
§33 인용 alias 적용 결과 (W2-3 핵심)
- jam_score_stats VIEW 컬럼 alias = 순수 소문자 snake_case 비인용 (
AS jam_id,AS game_id,AS weighted_total,AS simple_total,AS scored_criteria,AS judge_count). camelCase 문자 0 → Postgres 소문자 폴딩이 일어나도 식별자 불변(이미 소문자) → 케이스폴딩 버그 불가능. - §33의 camelCase 큰따옴표 강제는 하류 매퍼 SELECT alias 단계에 적용(설계 337/365줄, VP-7): VIEW 컬럼 snake_case → 매퍼가
SELECT weighted_total AS "weightedTotal"로 인용. 본 W2-3 은 매퍼 미생성 → 이 인용은 W2-4 verification 시점 검사(설계 위임). - 선례 game_review_stats 는 컬럼을
AS "snake_case"(인용)로, jam_score_stats 는 비인용 snake_case 로 둠 — 둘 다 소문자라 동작 동일, §33 위반 아님(인용/비인용 무관, 폴딩 영향 0). - fan-out 패턴(§33 가드): jam_score_stats 는
WITH per_criterion AS (... GROUP BY jam_id,game_id,criterion_key)로 jam_scores 를 출품작·기준 단위 선집계 후LEFT JOIN jam_criteria. 부모(평가)에 자식(축점수) 직접 JOIN 안 함 → COUNT/AVG 왜곡 없음. game_review_stats 선집계 선례 동형. 0-division:NULLIF(SUM(COALESCE(c."weight",1.0)),0)가드 그대로. 미채점 criterion 은 per_criterion 행 미생성으로 자동 제외.
동결 자연키/컬럼 정합 (하류 소비 계약 고정)
- 평가단위 = (jam_id, game_id) 자연키 (F8). jam_scores/jam_votes/jam_awards 전부 jam_id+game_id 직접 컬럼. FK = game_id→games, jam_id→jams(jam_entries.id surrogate 아님). ux_jam_entries_jam_game_active(schema.sql:521) 가 1:1 보장.
- 동결 컬럼 변경 0: 설계 DDL 블록을 한 글자도 변경 없이 구현(diff 0). jam_criteria(jam_id,criterion_key,display_name,sort_order,weight) / jam_scores(jam_id,game_id,judge_user_id,criterion_key,score) / jam_votes(jam_id,game_id,voter_user_id) / jam_awards(jam_id,game_id,award_track,rank,score_value) — 하류 W2-4/5/6 소비 계약 고정.
- 무결성 제약 전수(AC-T3): ux_jam_scores_jam_game_judge_criterion(1심사위원1기준1점), ux_jam_votes_jam_voter(1인1표), jam_scores_score_check(1~5), jam_awards_track_check(JUDGE/USER_RATING/POPULAR/GRAND) — 전수 존재.
- 트랙 4종 정합(AC-T2): award_track CHECK IN 4종 == 시상 산정 트랙 집합. F4 가드 고정.
설계와의 차이
계획=실제 1 worker, planned==actual. 그러나 orchestrator 지시문 "필수준수 3·4"(신규 Test.java 작성·@MockBean 등록) 미적용 — 사유 기록:
- 설계 권위(파일 영향 맵 441~455줄 + 비목표 §43-46 + concern 2)가 본 W2-3 범위를 스키마+계약 동결만으로 확정. 매퍼/POJO/컨트롤러/JSP/테스트는 전부 "하류 W2-4/5/6 소유 — 본 설계 미생성". 본 advisor 가 Java 신규 생성 시 ① 설계 파일영향맵 위반 ② 하류 소유 침범 ③ 동결 스키마 소비 계약 선점 — orchestrator 금지문("파일영향맵 밖 신규 파일 금지", "동결 변경 금지")과도 충돌.
- 따라서 본 W2-3 은 매퍼/컨트롤러 0개 생성 → 등록할 신규 @MockBean 0, 작성할 *Test.java 0. BibimbapApplicationTests 무변경(18빈 그대로) → contextLoads 회귀 없음.
- orchestrator "필수준수 3·4" 는 매퍼/컨트롤러가 생성되는 워크스트림(W2-1/W2-2 류) 전제의 누적 교훈이다. 본 W2-3 처럼 매퍼/컨트롤러 0 산출 워크스트림에는 적용 대상이 없다(빈/테스트 산출물 없음).
- 검증은 DB contract(L2 — VP-1~7 dev DB 실측) 차원으로 verification-advisor 가 수행(설계 §검증포인트 519줄: contextLoads @MockBean 은 매퍼 생성 하류 책임으로 명시).
- 그 외 동결 설계 대비 차이 0: DDL/VIEW/제약/alias verbatim, W2-1/W2-2 기존 파일 수정 0(append only, 기존 블록 무변경).
Verification 을 위한 힌트
- acceptance criteria 는 design.md(W2-3-eval-freeze-design.md) "검증 포인트"(VP-1~7) + "집합 전수 체크 AC"(AC-T1~T6) 참조.
- 본 변경으로 영향받는 테스트: 없음(Java 0 변경). 신규 검증은 dev DB contract(L2) 실측 — jam-eval-ddl 적용 후 무결성/집계 VIEW.
- L2 dev DB contract 권장: VP-1(UNIQUE/CHECK 거부), VP-2(jam_score_stats fan-out/NULL/0-division 샘플 실측), VP-5(트랙값 CHECK), VP-6(FK 적용 순서 — jam-ddl 후 jam-eval-ddl), VP-7(하류 매퍼 alias 는 W2-4 시점).
- DB 적용 미수행(NOT APPLIED) — verification 시
db/apply-local-ddl.sh실행은 verification-advisor 판단(advisor 는 적용 금지).
설계 "검증 포인트" verbatim echo
- VP-1 (AC-2/3 무결성, L2): jam_scores 같은 (jam_id,game_id,judge,criterion) 중복 INSERT → UNIQUE 거부. score 0/6 INSERT → CHECK 거부. jam_votes 같은 (jam_id, voter) 2표 INSERT → UNIQUE 거부(1인1표). dev DB contract 실측.
- VP-2 (AC-9 집계 정합, L2): jam_score_stats 가 동일 출품작에 다수 심사위원·다수 criterion 입력 시 ① fan-out 없이 weighted_total 정확(SUM(avg*weight)/SUM(weight)) ② criterion 일부 미채점 시 채점 기준만 반영 ③ weight 전부 0 인 경계에서 0-division 없이 NULL(NULLIF 가드) — 샘플 데이터 실측(game_review_stats BUG-1 fan-out 선례 재발 방지).
- VP-3 (AC-6 단방향, L1): 시상 USER_RATING 소비 SQL 이 game_review_stats 를 SELECT 만(write 0), game_reviews 에 jam FK 부재 확인(code 정합). 6축 컬럼 미참조 확인.
- VP-4 (AC-7 NULL/미달, L2): 리뷰 0개 출품작 avg_rating NULL → NULLS LAST 정렬 말단 + review_count<3 제외. review_count==3 경계 포함. 샘플 실측.
- VP-5 (AC-5 트랙값, L2): jam_awards award_track 에 'JUDGE'/'USER_RATING'/'POPULAR'/'GRAND' 외 값 INSERT → CHECK 거부.
- VP-6 (FK 적용 순서, L2): apply-local-ddl.sh 가 jam-ddl(W2-1) 적용 후 jam-eval-ddl 적용 시 FK 생성 성공(jams/jam_entries/games/users 선존재). 단독/역순 적용 시 FK 실패 검출.
- VP-7 (AC-12 alias, L2): 하류 jam_score_stats 매퍼 반환 키가 weightedTotal/simpleTotal/scoredCriteria/judgeCount 로 정합(집계 VIEW camelCase 큰따옴표 alias 확인 — GameReviewStatsMapper 케이스폴딩 BUG-2 선례 회피).
설계 "집합 전수 체크 AC" verbatim echo
- AC-T1 잼 평가 신규 테이블 전수 4건 + VIEW 1건 — docs/jam-eval-ddl.sql 의
CREATE TABLE IF NOT EXISTS4건(jam_criteria/jam_scores/jam_votes/jam_awards) ANDCREATE OR REPLACE VIEW1건(jam_score_stats):grep -c 'CREATE TABLE IF NOT EXISTS' docs/jam-eval-ddl.sql== 4 ANDgrep -c 'CREATE OR REPLACE VIEW' docs/jam-eval-ddl.sql== 1. AND db/schema.sql 에 동일 4테이블+1뷰 전수 존재(동기 사본 누락 검출). 테이블/뷰 추가·삭제 누락을 갯수로 동시 커버. [advisor 사전확인: ddl 4/1, schema 4/1 — PASS] - AC-T2 시상 트랙 전수 4종 정합 불변식 — jam_awards_track_check CHECK 의 IN 목록(JUDGE/USER_RATING/POPULAR/GRAND) 4종 == 시상 산정(W2-6)이 upsert 하는 award_track 집합. 검증: DDL CHECK IN 항목 4 AND (하류 W2-6 구현 시) 3개별 트랙 + GRAND 전수 산정 경로 존재. 트랙 추가·누락을 갯수 1로 커버(F4 핵심 가드). [advisor 사전확인: CHECK IN 4종 ddl/schema 각 1매치 — PASS, W2-6 산정경로는 하류]
- AC-T3 점수/투표 무결성 제약 전수 — 동결 핵심 UNIQUE/CHECK 4종 전수 존재: ux_jam_scores_jam_game_judge_criterion(1심사위원1기준1점), ux_jam_votes_jam_voter(1인1표), jam_scores_score_check(1~5), jam_awards_track_check(4트랙). 검증:
grep -c 'CREATE UNIQUE INDEX' docs/jam-eval-ddl.sql>= 4(criteria/scores/votes/awards 각 1) AND 위 4 제약명 전수 존재. 1건 누락 = 무결성 결함(1인1표/중복채점 우회) → FAIL. [advisor 사전확인: UNIQUE INDEX 4, 4제약명 전수 존재 — PASS] - AC-T4 평가 매퍼 시그니처 계약 전수
${0건(하류 검증) — 하류 W2-4/5/6 가 본 계약대로 구현한 신규 매퍼 전수에${매치 0:grep -rc '\${' <하류 jam-eval 매퍼들>== 0 (AC-11,${}금지). 부재 검증이라 리터럴 정당. 본 W2-3 은 매퍼 미생성 → 이 AC 는 하류 verification 시점 검사(계약 위임 명시). [advisor: 본 W2-3 매퍼 0 → 하류 W2-4/5/6 verification 시점] - AC-T5 단방향 무결성(write 0) 불변식 — game_reviews/game_review_axes/game_review_stats 가 본 동결로 인해 변경 0: docs/jam-eval-ddl.sql 에
game_reviews/game_review토큰의 ALTER/CREATE/INSERT/UPDATE 0건(읽기 계약뿐 — 주석/SELECT 형태 예시는 무방하나 DDL 변경문 0). 검증:grep -E 'ALTER TABLE .*game_review|CREATE TABLE .*game_review' docs/jam-eval-ddl.sql0건. 단방향 계약(G4) 위반(시상이 리뷰 스키마 손대기) 즉시 검출. [advisor 사전확인: grep 0건 — PASS] - AC-T6 FK 적용 순서 불변식 — jam-eval-ddl 의 FK 가 참조하는 선행 테이블 전수(jams/jam_entries/games/users) 가 apply 시점에 존재: 알파벳 글롭 순서상 jam-ddl/game-reviews-ddl 가 jam-eval-ddl 보다 먼저(공통 prefix 비교) → FK 생성 성공. 검증: apply-local-ddl.sh dry-run 또는 dev DB 전체 적용 후 jam_scores/jam_votes/jam_awards/jam_criteria 의 FK 4종 전수 생성 확인(pg_constraint). 순서 깨짐 시 FK 미생성 검출. [advisor 사전확인: jam-ddl < jam-eval-ddl < jam-judge-ddl 알파벳 순서 + game-reviews-ddl('g')도 선행 — 정적 PASS, FK 실생성은 L2 dev DB]
grounding 불일치 / concerns / 기존 파일 수정 / 미해결
- grounding 불일치: 없음. 설계 인용 앵커 전부 실측 정합(game_review_stats fan-out/인용 선례, ux_jam_entries_jam_game_active, GameReviewStatsMapper alias, jam-ddl 멱등 스타일, apply-local-ddl.sh 알파벳 글롭, schema.sql jam_judges 끝 596줄, BibimbapApplicationTests @MockBean 18). ownership.md 에 상세.
- concerns 처리: 설계 concerns 5건 전부 본 W2-3 구현 범위에서 검토 완료 — (1)평가단위 식별자: (jam_id,game_id) 자연키 채택 확정, jam_entries.id 직접 FK 미사용(설계 F8 그대로). (2)신규 매퍼 @MockBean: 본 W2-3 매퍼 0 → 하류 책임(설계 위임). (3)0-division/alias: NULLIF 가드 + VIEW snake/매퍼 camelCase 인용 2단(§33 정합). (4)최소리뷰수 N=3: 시상 산정 상수(W2-6 위치, 본 동결은 스키마만). (5)jam_entries UNIQUE 동결 유지: schema.sql:521 무변경 확인. 본 advisor 신규 concerns 0.
- W2-1/W2-2 기존 파일 수정 여부: db/schema.sql 만 수정 — jam_judges 블록 끝(596줄) 뒤 순수 append, 기존 W2-1(jams/entries/teams) + W2-2(jam_judges) 블록 무변경(설계 296줄 "jams/jam_entries 블록 뒤 신설" 근거). docs/*-ddl.sql 기존 파일 무변경. src/ 무변경 → W2-1/2 게이트·CSRF·#{} 동작 회귀 0.
- 미해결: 없음. 동결 스키마 단일권위 확정. 하류 W2-4/5/6 이 본 스키마 변경 없이 소비.