diff --git a/modules/_bundled/sirsoft-board/tests/Playwright/specs/user/board-list-context-round-trip.spec.ts b/modules/_bundled/sirsoft-board/tests/Playwright/specs/user/board-list-context-round-trip.spec.ts index 6eb9b588..e22a6a67 100644 --- a/modules/_bundled/sirsoft-board/tests/Playwright/specs/user/board-list-context-round-trip.spec.ts +++ b/modules/_bundled/sirsoft-board/tests/Playwright/specs/user/board-list-context-round-trip.spec.ts @@ -12,7 +12,7 @@ * 단위/렌더링: * - templates/_bundled/sirsoft-basic/src/__tests__/layouts/board-post-navigation-list-return.test.tsx * 가 실 `_navigation.json` 의 액션 params 로 mergeQuery 왕복을 고정 - * - .claude/scripts/audit/rules/layout-list-context-navigate-merge-query.cjs 가 전 저장소 재발 차단 + * - 저장소 전역 정적 검사가 목록 클러스터 내 navigate 의 mergeQuery 누락을 재발 차단 * 이 spec 은 브라우저 수준(실제 URL + 목록 API 요청 파라미터)을 담당한다. * * @scenario board-list-context-round-trip diff --git a/modules/_bundled/sirsoft-board/tests/scenarios/board-list-context-round-trip.yaml b/modules/_bundled/sirsoft-board/tests/scenarios/board-list-context-round-trip.yaml index f171fa49..d94010a3 100644 --- a/modules/_bundled/sirsoft-board/tests/scenarios/board-list-context-round-trip.yaml +++ b/modules/_bundled/sirsoft-board/tests/scenarios/board-list-context-round-trip.yaml @@ -35,7 +35,6 @@ test_files: - modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts - modules/_bundled/sirsoft-page/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts - templates/_bundled/sirsoft-admin_basic/src/__tests__/layouts/admin-list-context-round-trip.test.ts - - .claude/scripts/audit/__tests__/layout-list-context-navigate-merge-query.test.cjs validation: note: | diff --git a/modules/_bundled/sirsoft-ecommerce/src/Repositories/CouponIssueRepository.php b/modules/_bundled/sirsoft-ecommerce/src/Repositories/CouponIssueRepository.php index 734efe08..0de1aecf 100644 --- a/modules/_bundled/sirsoft-ecommerce/src/Repositories/CouponIssueRepository.php +++ b/modules/_bundled/sirsoft-ecommerce/src/Repositories/CouponIssueRepository.php @@ -178,7 +178,7 @@ class CouponIssueRepository implements CouponIssueRepositoryInterface // coupon 관계를 직렬화하지 않지만, 이 목록은 훅 // `sirsoft-ecommerce.user_coupon.filter_list_result` 로 확장에 그대로 전달된다. // 제3자 확장이 쿠폰 원본 정의(쿠폰명·할인율·사용조건)를 읽고 있을 수 있어 현행 유지 - // (PO 결정 2026-08-04). 번들 템플릿에는 아직 대응 마이페이지 화면이 없다. + // (프로젝트 결정 2026-08-04). 번들 템플릿에는 아직 대응 마이페이지 화면이 없다. relations: ['coupon'], resultCap: PaginationLimits::resultCap('ecommerce.coupon_issues'), ); diff --git a/modules/_bundled/sirsoft-ecommerce/src/Services/CashReceiptService.php b/modules/_bundled/sirsoft-ecommerce/src/Services/CashReceiptService.php index 30adcf4b..e985440d 100644 --- a/modules/_bundled/sirsoft-ecommerce/src/Services/CashReceiptService.php +++ b/modules/_bundled/sirsoft-ecommerce/src/Services/CashReceiptService.php @@ -705,7 +705,7 @@ class CashReceiptService /** * 프로바이더 원응답에서 민감 키를 마스킹합니다. * - * PO 결정: 전체 응답을 보관하되 알려진 민감 키를 재귀적으로 가린다. + * 프로젝트 결정: 전체 응답을 보관하되 알려진 민감 키를 재귀적으로 가린다. * * @param mixed $response 원응답 * @return array|null 마스킹된 응답 (배열이 아니면 null) diff --git a/modules/_bundled/sirsoft-ecommerce/src/Support/ShopPathResolver.php b/modules/_bundled/sirsoft-ecommerce/src/Support/ShopPathResolver.php index 26464ab6..437d8a80 100644 --- a/modules/_bundled/sirsoft-ecommerce/src/Support/ShopPathResolver.php +++ b/modules/_bundled/sirsoft-ecommerce/src/Support/ShopPathResolver.php @@ -28,7 +28,7 @@ namespace Modules\Sirsoft\Ecommerce\Support; * 를 이 계약이 도입된 `>=1.1.0` 이상으로 선언해야 한다. * * 시그니처를 바꾸거나 제거할 때는 위 소비 확장을 전수 확인하고 각 확장의 최소 버전 - * 제약을 함께 올린다 (CLAUDE.md "버전 동기화 의무" ②). + * 제약(`dependencies.modules.sirsoft-ecommerce`)을 함께 올린다. * * @since 1.1.0 */ diff --git a/modules/_bundled/sirsoft-ecommerce/tests/Playwright/playwright.config.ts b/modules/_bundled/sirsoft-ecommerce/tests/Playwright/playwright.config.ts index 5fbf831a..25ce1451 100644 --- a/modules/_bundled/sirsoft-ecommerce/tests/Playwright/playwright.config.ts +++ b/modules/_bundled/sirsoft-ecommerce/tests/Playwright/playwright.config.ts @@ -2,7 +2,7 @@ * 이커머스 모듈 Playwright E2E 설정. * * 코어 `playwright.config.ts` 와 동일한 base URL 해석 우선순위를 따른다 — 모듈도 활성 호스트가 - * 가변(개발자/CI/PO 환경별로 다른 도메인)이므로 하드코딩 회피. + * 가변(개발자/CI/운영 환경별로 다른 도메인)이므로 하드코딩 회피. * * Base URL 해석: * 1. PLAYWRIGHT_BASE_URL 환경변수 (CI/명시적 오버라이드) diff --git a/modules/_bundled/sirsoft-ecommerce/tests/Playwright/specs/shop/dbank-checkout-deposit-due.spec.ts b/modules/_bundled/sirsoft-ecommerce/tests/Playwright/specs/shop/dbank-checkout-deposit-due.spec.ts index 8905e4bb..a177751f 100644 --- a/modules/_bundled/sirsoft-ecommerce/tests/Playwright/specs/shop/dbank-checkout-deposit-due.spec.ts +++ b/modules/_bundled/sirsoft-ecommerce/tests/Playwright/specs/shop/dbank-checkout-deposit-due.spec.ts @@ -28,7 +28,8 @@ * 부작용: ②③ 은 실제 주문을 생성한다(결제 대기 상태). 무통장입금은 외부 PG 를 거치지 않으므로 * 샌드박스 의존이 없고, 생성된 주문은 설정된 기한이 지나면 미입금 자동취소 대상이 된다. * - * @see .claude/docs/frontend/troubleshooting-backend.md 사례 21 + * 회귀 배경: 입금기한 일수 설정이 문자열로 영속되면 기한 산정이 Carbon 의 strict 타입 경계에서 + * TypeError 를 던져 해당 주문 요청이 전부 500 이 되던 결함이 있었다. */ import { test, expect, authenticatePage } from '../../fixtures/ecommerce-auth'; import type { Page } from '@playwright/test'; diff --git a/modules/_bundled/sirsoft-ecommerce/tests/scenarios/cart-wishlist-image-column-pruning.yaml b/modules/_bundled/sirsoft-ecommerce/tests/scenarios/cart-wishlist-image-column-pruning.yaml index 576c9fea..af915688 100644 --- a/modules/_bundled/sirsoft-ecommerce/tests/scenarios/cart-wishlist-image-column-pruning.yaml +++ b/modules/_bundled/sirsoft-ecommerce/tests/scenarios/cart-wishlist-image-column-pruning.yaml @@ -39,7 +39,7 @@ notes: | (`OrderCalculationService`)가 그 관계를 직접 읽고, 미로드 시 항목마다 재조회하므로 좁히면 페이로드 대신 쿼리가 늘어난다. 게다가 계산기가 `is_active` 를 거르지 않아 로드 경로에 따라 배송비가 달라질 수 있다 — 계산 경로를 함께 손대야 안전한 축이라 본 이슈에서 다루지 않는다 - (PO 결정, 2026-08-05). + (프로젝트 결정, 2026-08-05). E2E 미해당: 응답 형태가 불변이라 브라우저 경로에 새 분기가 없다. 소비 사실 고정은 레이아웃 원문 검사(`cartWishlistImageConsumers.test.ts`)가 담당한다. diff --git a/modules/_bundled/sirsoft-ecommerce/tests/scenarios/cash-receipt-ui-and-refund-bank.yaml b/modules/_bundled/sirsoft-ecommerce/tests/scenarios/cash-receipt-ui-and-refund-bank.yaml index dfde18d1..f9b09fa8 100644 --- a/modules/_bundled/sirsoft-ecommerce/tests/scenarios/cash-receipt-ui-and-refund-bank.yaml +++ b/modules/_bundled/sirsoft-ecommerce/tests/scenarios/cash-receipt-ui-and-refund-bank.yaml @@ -11,7 +11,7 @@ description: | 리터럴 객체다. 슬롯에 주입된 모듈 폼이 _local 에 값을 써도 그 body 에 실릴 방법이 없다 — 결제 버튼에 id 가 없어 overlay 로 타겟할 수 없고, inject_props 는 컴포넌트 props 전용이라 actions[].params.body 에 도달하지 못한다. 그대로 두면 구매자가 신청해도 주문에 아무 기록이 남지 않는다. - → PO 결정: body 를 통짜 표현식으로 바꾸고 확장 병합 칸(...(_local.checkoutExtraPayload ?? {})) 한 개를 연다. + → 프로젝트 결정: body 를 통짜 표현식으로 바꾸고 확장 병합 칸(...(_local.checkoutExtraPayload ?? {})) 한 개를 연다. 템플릿은 현금영수증을 알지 않고, 모듈은 그 칸에만 쓴다. 확장 미주입 시 payload 는 전환 전과 동일하다. 발견한 사전 결함(본 세션에서 수정): @@ -29,7 +29,7 @@ description: | · 발급 버튼과 재발급 버튼의 노출 조건이 배타적이지 않아 FAILED 상태에서 둘 다 떴다. · 이력 표가 원시값을 노출했다 — 취소 행에 "발급 완료", 실패 행 일시 "-"(issued_at null), issue/FAILED. - 환불계좌는 PG·현금영수증 프로바이더와 무관한 순수 주문 정보이므로 템플릿이 직접 소유한다(PO 결정). + 환불계좌는 PG·현금영수증 프로바이더와 무관한 순수 주문 정보이므로 템플릿이 직접 소유한다(프로젝트 결정). 취소 시점 갱신은 레이아웃이 아니라 cancelOrderHandlers.ts 가 수행한다 — 취소 POST body 를 그 핸들러가 조립하기 때문이다. @@ -215,7 +215,7 @@ effects: - portable_override_applies_below_1024_on_render # 실렌더: 세로 스택 전환 (F5) - portable_override_absent_at_1024_on_render # 실렌더: 1024px 부터 base 복귀 - # 데이터 위생 (감사 지적 C8, PO 결정 2026-07-10) + # 데이터 위생 (감사 지적 C8, 프로젝트 결정 2026-07-10) - cash_receipt_request_not_persisted_for_non_dbank # 발급 불가 주문에 암호문 미보관 # 자진발급 설정 안내 (감사 지적 W-5) diff --git a/modules/_bundled/sirsoft-ecommerce/tests/scenarios/order-admin-list-context-round-trip.yaml b/modules/_bundled/sirsoft-ecommerce/tests/scenarios/order-admin-list-context-round-trip.yaml index c3a3855a..26289235 100644 --- a/modules/_bundled/sirsoft-ecommerce/tests/scenarios/order-admin-list-context-round-trip.yaml +++ b/modules/_bundled/sirsoft-ecommerce/tests/scenarios/order-admin-list-context-round-trip.yaml @@ -22,7 +22,6 @@ effects: test_files: - modules/_bundled/sirsoft-ecommerce/tests/Playwright/specs/admin/order-admin-list-context-round-trip.spec.ts - modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts - - .claude/scripts/audit/__tests__/layout-list-context-navigate-merge-query.test.cjs validation: note: | diff --git a/modules/_bundled/sirsoft-ecommerce/tests/scenarios/review-list-image-payload-contract.yaml b/modules/_bundled/sirsoft-ecommerce/tests/scenarios/review-list-image-payload-contract.yaml index 1caadd73..cfef76cb 100644 --- a/modules/_bundled/sirsoft-ecommerce/tests/scenarios/review-list-image-payload-contract.yaml +++ b/modules/_bundled/sirsoft-ecommerce/tests/scenarios/review-list-image-payload-contract.yaml @@ -3,7 +3,7 @@ feature: 리뷰 목록의 첨부 이미지 계약 고정 (#518 / 공개 #76) description: | #518 원안은 리뷰 목록에서 `images` 를 빼고 대표 1장 + `image_count` 로 줄이려 했다. 소비처를 재실측한 결과 그 판단이 빗나갔다 — 관리자·공개 두 목록 모두 첨부 이미지를 - 실제로 그린다. 착수하지 않는다 (PO 결정, 2026-08-05). + 실제로 그린다. 착수하지 않는다 (프로젝트 결정, 2026-08-05). 이 매니페스트는 "줄였다" 를 기록하는 것이 아니라 **줄일 수 없다는 사실을 고정**한다. 제거 시 조용히 깨지기 때문이다: 썸네일이 `(review.images ?? []).length > 0` 가드 뒤에 diff --git a/modules/_bundled/sirsoft-page/tests/Playwright/playwright.config.ts b/modules/_bundled/sirsoft-page/tests/Playwright/playwright.config.ts index 0bdbfc5d..702867dd 100644 --- a/modules/_bundled/sirsoft-page/tests/Playwright/playwright.config.ts +++ b/modules/_bundled/sirsoft-page/tests/Playwright/playwright.config.ts @@ -2,7 +2,7 @@ * 페이지 모듈 Playwright E2E 설정. * * 코어 `playwright.config.ts` 및 이커머스 모듈 설정과 동일한 base URL 해석 우선순위를 따른다 — - * 모듈도 활성 호스트가 가변(개발자/CI/PO 환경별로 다른 도메인)이므로 하드코딩 회피. + * 모듈도 활성 호스트가 가변(개발자/CI/운영 환경별로 다른 도메인)이므로 하드코딩 회피. * * Base URL 해석: * 1. PLAYWRIGHT_BASE_URL 환경변수 (CI/명시적 오버라이드) diff --git a/modules/_bundled/sirsoft-page/tests/scenarios/page-admin-list-context-round-trip.yaml b/modules/_bundled/sirsoft-page/tests/scenarios/page-admin-list-context-round-trip.yaml index 2e741f63..43271fa0 100644 --- a/modules/_bundled/sirsoft-page/tests/scenarios/page-admin-list-context-round-trip.yaml +++ b/modules/_bundled/sirsoft-page/tests/scenarios/page-admin-list-context-round-trip.yaml @@ -19,7 +19,6 @@ effects: test_files: - modules/_bundled/sirsoft-page/tests/Playwright/specs/admin/page-admin-list-context-round-trip.spec.ts - modules/_bundled/sirsoft-page/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts - - .claude/scripts/audit/__tests__/layout-list-context-navigate-merge-query.test.cjs validation: note: | diff --git a/plugins/_bundled/sirsoft-gdpr/resources/extensions/mypage_privacy_tab.json b/plugins/_bundled/sirsoft-gdpr/resources/extensions/mypage_privacy_tab.json index 439b0c6e..bded153a 100644 --- a/plugins/_bundled/sirsoft-gdpr/resources/extensions/mypage_privacy_tab.json +++ b/plugins/_bundled/sirsoft-gdpr/resources/extensions/mypage_privacy_tab.json @@ -534,7 +534,7 @@ ] }, { - "comment": "항목 리스트 (이슈 #430 재설계) — 상태 배지 + 동의/철회 버튼 방식. 필수=상태 배지 '항상 적용' + 잠금 버튼(액션 없음), 선택=상태 배지(동의함/거부함/미설정) + 동의·철회 버튼(확인 모달 경유). 동의일 컬럼은 사용자 화면에서 제거(동의한 항목만 라벨 아래 날짜 표시, 감사 로그 전체는 관리자 화면에만 존재). 초기 설계였던 on/off 스위치는 user 템플릿 스타일 회귀 + PO 지시로 배지+버튼 방식으로 대체됨(2026-07-21).", + "comment": "항목 리스트 (이슈 #430 재설계) — 상태 배지 + 동의/철회 버튼 방식. 필수=상태 배지 '항상 적용' + 잠금 버튼(액션 없음), 선택=상태 배지(동의함/거부함/미설정) + 동의·철회 버튼(확인 모달 경유). 동의일 컬럼은 사용자 화면에서 제거(동의한 항목만 라벨 아래 날짜 표시, 감사 로그 전체는 관리자 화면에만 존재). 초기 설계였던 on/off 스위치는 user 템플릿 스타일 회귀 + 프로젝트 지시로 배지+버튼 방식으로 대체됨(2026-07-21).", "type": "basic", "name": "Div", "if": "{{(gdprMeConsents?.data?.consents ?? []).length > 0}}", diff --git a/plugins/_bundled/sirsoft-gdpr/resources/js/__tests__/layouts/admin_plugin_settings.test.tsx b/plugins/_bundled/sirsoft-gdpr/resources/js/__tests__/layouts/admin_plugin_settings.test.tsx index 178eb42f..c1b3bc4e 100644 --- a/plugins/_bundled/sirsoft-gdpr/resources/js/__tests__/layouts/admin_plugin_settings.test.tsx +++ b/plugins/_bundled/sirsoft-gdpr/resources/js/__tests__/layouts/admin_plugin_settings.test.tsx @@ -564,7 +564,7 @@ describe('admin/plugin_settings.json — 3 카드 (operator / cookie_banner / au /** * sequence handler 구조 회귀 가드 — actions 배열이 params 안에 잘못 중첩되어 - * (CLAUDE.md 절대 금지 패턴) 있었던 결함. 엔진(ActionDispatcher.handleSequence)이 + * (레이아웃 JSON 금지 패턴) 있었던 결함. 엔진(ActionDispatcher.handleSequence)이 * 두 위치를 모두 인식하는 fallback을 갖고 있어 동작 자체는 정상이었지만, 정석 * 위치(actions가 액션 객체의 top-level)로 바로잡는다. */ diff --git a/plugins/_bundled/sirsoft-gdpr/resources/js/__tests__/layouts/mypage_privacy_tab.test.tsx b/plugins/_bundled/sirsoft-gdpr/resources/js/__tests__/layouts/mypage_privacy_tab.test.tsx index 79e3e349..f60a5f14 100644 --- a/plugins/_bundled/sirsoft-gdpr/resources/js/__tests__/layouts/mypage_privacy_tab.test.tsx +++ b/plugins/_bundled/sirsoft-gdpr/resources/js/__tests__/layouts/mypage_privacy_tab.test.tsx @@ -312,7 +312,7 @@ describe('extensions/mypage_privacy_tab.json — 마이페이지 GDPR 동의 매 * @effects mypage_status_date_line_consented_only */ it('이슈 #430/#509 — 동의·철회 이력이 있는 항목만 날짜 줄 노출 (서버가 status_at_formatted 제공)', () => { - // PO 결정(2026-07-20) + 이슈 #509 16번 갱신: 날짜는 "동의한 항목" + "철회 이력이 있는 항목". + // 프로젝트 결정(2026-07-20) + 이슈 #509 16번 갱신: 날짜는 "동의한 항목" + "철회 이력이 있는 항목". // 거부·신규 미설정은 서버가 status_at_formatted 를 null 로 내려주므로 날짜 줄이 렌더되지 않는다. // 프론트는 status_label && status_at_formatted 가 둘 다 있을 때만 날짜 줄을 그리며, 값 자체는 // 서버가 상태별(동의일/철회일)로 계산해 내려주므로 프론트 조건식은 상태 무관 동일하게 유지된다. @@ -328,7 +328,7 @@ describe('extensions/mypage_privacy_tab.json — 마이페이지 GDPR 동의 매 * @effects mypage_status_date_line_revoked_color_distinction */ it('이슈 #509 16번 — 동의·철회 날짜 줄을 서로 다른 색으로 균형있게 강조 (동의=초록/철회=빨강, 배지·관리자 이력 화면과 동일 톤)', () => { - // 철회만 강조되고 동의는 밋밋해 보인다는 PO 피드백 반영 — 동의도 철회와 대등하게 강조한다. + // 철회만 강조되고 동의는 밋밋해 보인다는 사용성 피드백 반영 — 동의도 철회와 대등하게 강조한다. // status === 'revoked' 면 text-red-600/dark:text-red-400, 그 외(동의)는 text-green-600/dark:text-green-400. const text = serializeForSearch(section); expect(text).toContain("consent?.status === 'revoked'"); diff --git a/plugins/_bundled/sirsoft-gdpr/tests/Playwright/playwright.config.ts b/plugins/_bundled/sirsoft-gdpr/tests/Playwright/playwright.config.ts index e932044a..c37f013c 100644 --- a/plugins/_bundled/sirsoft-gdpr/tests/Playwright/playwright.config.ts +++ b/plugins/_bundled/sirsoft-gdpr/tests/Playwright/playwright.config.ts @@ -2,7 +2,7 @@ * GDPR 플러그인 Playwright E2E 설정. * * 코어 `playwright.config.ts` 와 동일한 base URL 해석 우선순위를 따른다 — 플러그인도 활성 호스트가 - * 가변(개발자/CI/PO 환경별로 다른 도메인)이므로 하드코딩 회피. + * 가변(개발자/CI/운영 환경별로 다른 도메인)이므로 하드코딩 회피. * * Base URL 해석: * 1. PLAYWRIGHT_BASE_URL 환경변수 (CI/명시적 오버라이드) @@ -76,6 +76,12 @@ export default defineConfig({ ], use: { baseURL: resolveBaseUrl(), + // spec 이 한국어 화면 문구를 단언하므로 로케일을 고정한다. + // 로케일 우선순위는 localStorage g7_locale → 서버 응답값 → 'ko' 이고, 서버값은 미인증 + // 요청에서 Accept-Language 로 결정된다(SetLocale 미들웨어). Playwright 의 locale 옵션이 + // 그 헤더를 만들므로, 지정하지 않으면 첫 페이지 로드가 en-US 로 나가 화면이 영어로 렌더되고 + // 엔진이 그 값을 localStorage 에 저장해 이후 인증해도 세션 전체가 영어로 고정된다. + locale: 'ko-KR', trace: 'retain-on-failure', screenshot: 'only-on-failure', ignoreHTTPSErrors: true, diff --git a/plugins/_bundled/sirsoft-gdpr/tests/Playwright/specs/admin/policy-version-snapshot-link.spec.ts b/plugins/_bundled/sirsoft-gdpr/tests/Playwright/specs/admin/policy-version-snapshot-link.spec.ts index 1dcca1f4..01acf3d8 100644 --- a/plugins/_bundled/sirsoft-gdpr/tests/Playwright/specs/admin/policy-version-snapshot-link.spec.ts +++ b/plugins/_bundled/sirsoft-gdpr/tests/Playwright/specs/admin/policy-version-snapshot-link.spec.ts @@ -1,6 +1,6 @@ /** * E2E: 관리자 환경설정 > 쿠키 배너 > 정책 버전 > 보기 — 본문 페이지 링크 (#509 체크리스트 12번) - * + 관리자 환경설정 카드 제목 색상 회귀 가드 (PO 스크린샷 발견) + * + 관리자 환경설정 카드 제목 색상 회귀 가드 (브라우저 스크린샷으로 발견) * + 정책 버전 이력 토글 sequence handler 회귀 가드 * * @scenario admin_gdpr_policy_version_snapshot_open_policy_page_link @@ -13,11 +13,11 @@ * 모달의 본문 페이지 링크 href 를 검증할 수 있다. * * 또한 카드 제목(H3)이 에러/경고 전용 시맨틱(text-error-strong, red 계열)을 오용해 - * "운영 주체" 등 일반 카드 제목이 빨간색으로 표시되던 결함을 PO 가 스크린샷으로 발견해 + * "운영 주체" 등 일반 카드 제목이 빨간색으로 표시되던 결함을 브라우저 스크린샷으로 발견해 * section-heading-md(중립 톤)로 수정 — 실제 렌더링된 색상을 브라우저에서 검증한다. * * 정책 버전 이력 토글 버튼의 sequence handler 가 actions 를 params 안에 잘못 중첩하고 - * 있던 결함(CLAUDE.md 절대 금지 패턴)도 함께 발견 — 엔진이 두 위치 모두 인식하는 + * 있던 결함(레이아웃 JSON 금지 패턴)도 함께 발견 — 엔진이 두 위치 모두 인식하는 * fallback을 갖고 있어 동작 자체는 정상이었으나 정석 위치(top-level)로 바로잡았다. * 실제 클릭 시 이력 표가 펼쳐지는지(=sequence 의 setState 가 실행됐는지)를 검증한다. * diff --git a/plugins/_bundled/sirsoft-gdpr/tests/Playwright/specs/public/cookie-banner-guest-login-reappear.spec.ts b/plugins/_bundled/sirsoft-gdpr/tests/Playwright/specs/public/cookie-banner-guest-login-reappear.spec.ts index ba1aa209..ee03cc25 100644 --- a/plugins/_bundled/sirsoft-gdpr/tests/Playwright/specs/public/cookie-banner-guest-login-reappear.spec.ts +++ b/plugins/_bundled/sirsoft-gdpr/tests/Playwright/specs/public/cookie-banner-guest-login-reappear.spec.ts @@ -6,7 +6,7 @@ * * 배경: `_global.gdprBannerDismissedFor` 가 "닫힘 여부"(boolean)가 아니라 "누가 닫았는지" * (사용자 식별자)를 저장하도록 수정되기 전에는, 게스트로 배너를 닫은 뒤 동의 이력이 없는 - * 다른 계정으로 로그인해도 배너가 계속 숨겨져 있는 결함이 있었다 (PO 가 스크린샷으로 재현·지적). + * 다른 계정으로 로그인해도 배너가 계속 숨겨져 있는 결함이 있었다 (브라우저 스크린샷으로 재현·지적). * 현재는 cookie_banner.json 의 노출 조건이 `_global.gdprBannerDismissedFor !== (사용자 식별자)` * 로 비교하므로, 로그인으로 사용자가 바뀌면(게스트 uuid → 회원 uuid) 다시 노출되어야 한다. * diff --git a/plugins/_bundled/sirsoft-gdpr/tests/Unit/Http/Resources/GdprUserConsentResourceTest.php b/plugins/_bundled/sirsoft-gdpr/tests/Unit/Http/Resources/GdprUserConsentResourceTest.php index b728a7e3..56039642 100644 --- a/plugins/_bundled/sirsoft-gdpr/tests/Unit/Http/Resources/GdprUserConsentResourceTest.php +++ b/plugins/_bundled/sirsoft-gdpr/tests/Unit/Http/Resources/GdprUserConsentResourceTest.php @@ -66,7 +66,7 @@ class GdprUserConsentResourceTest extends PluginTestCase public function test_rejected_optional_maps_to_rejected_status_with_no_date_label(): void { - // PO 결정(2026-07-20) — 날짜/라벨은 "동의한 항목만" 노출. 거부는 상태만 rejected 로 내려주고 + // 프로젝트 결정(2026-07-20) — 날짜/라벨은 "동의한 항목만" 노출. 거부는 상태만 rejected 로 내려주고 // status_label·status_at_formatted 는 null (프론트가 날짜 줄을 렌더하지 않음). $consent = new GdprUserConsent([ 'consent_key' => 'cookie_analytics', diff --git a/tests/Feature/Api/Admin/LanguagePackControllerTest.php b/tests/Feature/Api/Admin/LanguagePackControllerTest.php index 81811a76..cdd41ff5 100644 --- a/tests/Feature/Api/Admin/LanguagePackControllerTest.php +++ b/tests/Feature/Api/Admin/LanguagePackControllerTest.php @@ -701,13 +701,13 @@ class LanguagePackControllerTest extends TestCase } /** - * 번들 설치도 외부 소스와 동일하게 활성화 권한 게이트를 적용한다 (PO 결정, 2026-08-04). + * 번들 설치도 외부 소스와 동일하게 활성화 권한 게이트를 적용한다 (프로젝트 결정, 2026-08-04). * * 설치(install)와 활성화(manage)를 별도 권한으로 두는 정책을 네 경로 전부에 같은 강도로 * 적용한다 — 어느 경로로 들어오느냐가 권한 경계를 바꾸면 그 경로가 우회로가 된다. * * 검토 단계에서는 "번들은 저장소 동봉 신뢰 자산이라 임의 PHP 반입 경로가 아니다" 를 근거로 - * 면제했으나, PO 가 네 경로 일관 적용을 선택했다. 그 결과 설치 권한만 가진 운영자가 활성 + * 면제했으나, 네 경로에 일관 적용하는 것으로 결정했다. 그 결과 설치 권한만 가진 운영자가 활성 * 팩을 재설치하면 그 팩이 `installed` 로 내려가고, 다시 켜려면 관리 권한이 필요하다. * * @scenario vector=install_from_bundled, actor_permission=install_only diff --git a/tests/Feature/DevTools/DevtoolsRouteCacheTest.php b/tests/Feature/DevTools/DevtoolsRouteCacheTest.php index bbd7f0ab..f725b272 100644 --- a/tests/Feature/DevTools/DevtoolsRouteCacheTest.php +++ b/tests/Feature/DevTools/DevtoolsRouteCacheTest.php @@ -38,7 +38,7 @@ class DevtoolsRouteCacheTest extends TestCase * 덤프 위임이 실제로 수행됐는지 확인할 때 쓰는 섹션. * * 하네스 자식 프로세스는 실 `storage/debug-dump` 에 쓴다 (경로가 `storage_path()` 고정). - * PO 가 브라우저에서 받아 둔 덤프를 테스트가 덮어쓰지 않도록 이 파일만 스냅샷·복원한다. + * 개발자가 브라우저에서 받아 둔 덤프를 테스트가 덮어쓰지 않도록 이 파일만 스냅샷·복원한다. */ private const PROBE_SECTION = 'logs'; @@ -83,7 +83,7 @@ class DevtoolsRouteCacheTest extends TestCase self::removeDirectory(dirname(__DIR__, 3).'/'.self::$cacheRelDir); } - // PO 의 덤프 데이터를 원상 복구 (자식 프로세스가 실 storage 에 썼다). + // 개발자의 덤프 데이터를 원상 복구 (자식 프로세스가 실 storage 에 썼다). $probePath = dirname(__DIR__, 3).'/storage/debug-dump/'.self::PROBE_FILE; if (self::$probeExisted && self::$probeBackup !== null) { file_put_contents($probePath, self::$probeBackup); diff --git a/tests/Playwright/specs/admin/admin-trailing-slash-route.spec.ts b/tests/Playwright/specs/admin/admin-trailing-slash-route.spec.ts index c15b77a5..707ec5ca 100644 --- a/tests/Playwright/specs/admin/admin-trailing-slash-route.spec.ts +++ b/tests/Playwright/specs/admin/admin-trailing-slash-route.spec.ts @@ -7,7 +7,7 @@ * 풀린 상태로 `/admin/` 에 접근하면 대시보드 → 로그인 리다이렉트 흐름 대신 404 가 * 노출됐다. 수정: `Router.match()` 진입 시 끝 슬래시를 정규화한다. * - * 단위 테스트(Router.test.ts)가 매칭 로직을 잠그지만, PO 가 실제로 브라우저에서 + * 단위 테스트(Router.test.ts)가 매칭 로직을 잠그지만, 실제 브라우저에서 * 재현한 증상이므로(단위 green + 브라우저 깨짐 방지) 브라우저 레벨로도 잠근다. * * @scenario admin_trailing_slash_unauthenticated + admin_no_trailing_slash_unauthenticated diff --git a/tests/Playwright/specs/admin/localinit-tab-roundtrip-store-sync.spec.ts b/tests/Playwright/specs/admin/localinit-tab-roundtrip-store-sync.spec.ts index 45d58004..8466898a 100644 --- a/tests/Playwright/specs/admin/localinit-tab-roundtrip-store-sync.spec.ts +++ b/tests/Playwright/specs/admin/localinit-tab-roundtrip-store-sync.spec.ts @@ -32,7 +32,8 @@ * 단위 테스트는 이 결함을 잡지 못한다 — React 렌더 사이클과 복수 루트 렌더러의 effect 실행 * 순서를 모사하지 못하기 때문이다. * - * @see .claude/docs/frontend/troubleshooting-state-global.md 사례 5 + * 회귀 배경: 탭 왕복 후 initLocal 동기화가 편집 중이던 입력칸의 값을 되돌려, 먼저 편집한 + * 입력칸에만 옛 값이 남던 결함 (engine-v1.54.7 에서 수정). */ import { test, expect, issueToken, issueScopedToken, authenticatePage } from '../../fixtures/auth'; import type { Page } from '@playwright/test'; diff --git a/tests/scenarios/language-pack-php-whitelist-and-activation-boundary.yaml b/tests/scenarios/language-pack-php-whitelist-and-activation-boundary.yaml index 586e137f..e83ba978 100644 --- a/tests/scenarios/language-pack-php-whitelist-and-activation-boundary.yaml +++ b/tests/scenarios/language-pack-php-whitelist-and-activation-boundary.yaml @@ -79,7 +79,7 @@ effects: # E2E axis 없음: 판정은 전부 서버측(FormRequest / Service)이다. 관리자 화면에서 # auto_activate 를 보내는 곳은 번들 재설치 모달 하나뿐이고, 게이트를 네 경로 전부에 -# 걸기로 하면서(PO 결정 2026-08-04) 이 모달이 보내는 값을 운영자의 활성화 권한 +# 걸기로 하면서(프로젝트 결정 2026-08-04) 이 모달이 보내는 값을 운영자의 활성화 권한 # (`abilities.can_activate`)으로 분기하도록 바꿨다 — 권한이 없으면 auto_activate 를 # 보내지 않아 재설치는 그대로 되고 팩만 installed 로 내려간다. # diff --git a/tests/scenarios/language-pack-provision-and-drift.yaml b/tests/scenarios/language-pack-provision-and-drift.yaml index 6bfb84b3..4439e92c 100644 --- a/tests/scenarios/language-pack-provision-and-drift.yaml +++ b/tests/scenarios/language-pack-provision-and-drift.yaml @@ -11,7 +11,7 @@ description: | 설치 행은 있으나 파일이 사라진 드리프트 팩도 함께 복구한다(수동 복구 경로 겸용). - list()/Resource 는 파생 플래그 files_missing(active 인데 설치본 부재)과 bundled_source_available(번들 소스로 복구 가능)을 부여해 드리프트 표면화 + 복구 가능 여부를 구분한다. - - A2(인스톨러 기본 선택)는 admin_language 가 ko/en 한정이라 no-op → PO 결정으로 제외. + - A2(인스톨러 기본 선택)는 admin_language 가 ko/en 한정이라 no-op → 프로젝트 결정으로 제외. axes: target_locale_source: [supported_locales_default, explicit_locale_option] @@ -40,15 +40,12 @@ effects: - cli_list_surfaces_uninstalled_and_drift - admin_list_shows_drift_badge_and_reinstall - third_party_pack_without_bundle_source_not_offered_for_reinstall - - supported_locale_without_bundle_source_is_statically_flagged - - declared_locale_without_installed_pack_is_statically_flagged test_files: - tests/Feature/LanguagePack/ProvisionLanguagePackCommandTest.php - tests/Feature/LanguagePack/ListDriftDetectionTest.php - tests/Feature/LanguagePack/ListLanguagePackCommandTest.php - templates/_bundled/sirsoft-admin_basic/__tests__/layouts/admin-language-pack-drift.test.tsx - - .claude/scripts/audit/__tests__/rules.test.cjs e2e_files: - tests/Playwright/specs/admin/language-pack-drift-discovery.spec.ts @@ -57,9 +54,15 @@ rules_layer_coverage: - rule: service-direct-data-access coverage: ProvisionLanguagePackCommand 은 LanguagePackService 만 주입 — Model/DB facade 직접 접근 없음 - rule: lang-pack-supported-locale-has-bundle - coverage: config/app.php supported_locales 비-base 로케일 ↔ g7-core-{locale} 번들 소스 정합 정적 검사 + coverage: | + config/app.php supported_locales 비-base 로케일 ↔ g7-core-{locale} 번들 소스 정합 정적 검사. + 효과 supported_locale_without_bundle_source_is_statically_flagged 를 담당한다 — 런타임 + 테스트가 아니라 정적 검사 계층에서만 성립하므로 effects 목록이 아닌 이 항목이 SSoT 다. - rule: lang-pack-installed-version-drift - coverage: 선언 로케일의 설치본 부재(미설치 사각)를 프로비저닝된 환경에 한해 정적 검사 + coverage: | + 선언 로케일의 설치본 부재(미설치 사각)를 프로비저닝된 환경에 한해 정적 검사. + 효과 declared_locale_without_installed_pack_is_statically_flagged 를 담당한다 — 위와 동일한 + 이유로 effects 목록이 아닌 이 항목이 SSoT 다. - rule: frontend-change-requires-e2e coverage: 관리자 언어팩 목록 partial 변경에 동반하는 language-pack-drift-discovery.spec.ts (템플릿 도메인)