Conversation
같은 대조가 ai-service 에 이미 있다(test_the_server_javadoc_lists_the_same_codes). 집합 비교에 변이도 걸려 있어 그 자체는 멀쩡한데, 언제 도는가가 문제였다. ci.yml:181 ai=false; hit '^(ai-service/|contracts/|data/|web/src/lib/survey\.ts$)' ai-service/app/schemas.py 를 고친다 ai-service=true → 그 대조가 돈다 AiServiceClient.java javadoc 만 고친다 ai-service=false → 안 돈다 ❗ 즉 Literal 을 고치는 쪽은 잡히고 javadoc 을 고치는 쪽은 안 잡혔다. 거기서 코드를 지우거나 이름을 잘못 적으면 초록으로 머지되고, 읽는 사람은 낼 수 없는 코드나 모자란 목록을 믿는다. 두 벌이 갈릴 뻔한 사건이 이미 있었다(#444 리뷰 — 아홉 vs 열). #521 과 같은 모양인데, 거기서는 "서버만 고치는 사람은 npm run build 를 안 돌린다" 였고 여기서는 CI 판별이다. - server 쪽에 대조를 두고 schemas.py 를 선언된 입력으로 만들었다. 그러면 두 파일 중 어느 쪽을 고쳐도 server 잡이 뜨고 이 대조가 돈다 - ❗AiServiceClient.java 도 입력으로 걸었다. 실측: 안 걸면 javadoc 에서 코드를 지워도 `> Task :test UP-TO-DATE` 로 BUILD SUCCESSFUL 이다. 주석만 바뀌면 바이트코드가 같아서 test 가 안 돌고, 하필 그때가 주석이 낡는 순간이다(#621 이 핸들러에서 같은 자리를 밟았다) - python 쪽 대조는 지우지 않는다. server/ 없이 받은 환경에서 통과하도록 갈래가 있고 그 조건에서 그쪽이 돈다. 두 대조가 같은 두 파일에서 값을 읽으므로 갈릴 자리가 없다 — 같은 사실을 두 벌로 적는 것이 아니라 두 번 재는 것이다 - 개수를 적어 두지 않는다. 코드는 늘어나므로 그 숫자가 낡는다. 대신 양쪽을 실제로 읽었는지를 닻으로 따로 잰다 — 한쪽 정규식이 어긋나면 빈 집합 둘이 같아져 조용히 통과한다 역검증: javadoc 목록에서 코드 하나 삭제(주석만) 빨강 (입력 선언 전에는 UP-TO-DATE 로 초록) Literal 에서 코드 하나 삭제 빨강 ci.yml server_extra 에서 새 경로 제거 CiServerFilterMirrorsGradleInputsTest 빨강 Literal 블록 정규식을 어긋나게 닻 테스트 빨강 server 전체 832건 · 실패 0 · skip 0 Closes #620 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
yoonjiseok
left a comment
There was a problem hiding this comment.
승인합니다. #620 이 닫힙니다. 그 대조가 제 파일 둘을 읽는 것이라 양쪽에서 재봤습니다.
재현 — 핵심 변이가 그 자리에서 뭅니다
기준선 832 · 실패 0 · skip 0 ← 본문과 같다
javadoc 에서 코드 하나 삭제(주석만) > Task :compileTestJava UP-TO-DATE
> Task :test FAILED
「두 목록의 코드가 같다」 FAILED
바이트코드가 안 바뀌었는데 test 가 다시 돌았습니다 — 입력 선언이 실제로 일하는 것이 그 두 줄에 있습니다. 이 함정을 안 밟았으면 그 변이가 BUILD SUCCESSFUL 이었을 것이고, 그건 그물이 있는데 안 도는 상태라 없는 것보다 나쁩니다.
❗「모양이 반복된다」를 build.gradle 에 적으신 것
이번 주에 같은 함정이 두 번입니다(#621 핸들러 javadoc · 이번 AiServiceClient). 규칙을 그 자리에 적어 두신 게 맞습니다.
테스트가
src/main/java를 텍스트로 읽으면 그 파일을 여기 걸어야 한다
그리고 경계선까지 적으신 것이 좋습니다 — "코드를 읽는 대조(ProductRiskItems·evidence 쪽)는 이 함정이 없다, 그쪽이 무는 변화는 전부 바이트코드를 바꾼다." 규칙만 있으면 다음 사람이 모든 입력을 다 걸려고 합니다.
「개수를 안 적는다 + 닻」 조합
#621 에서 COPIES_CLAIM 설명문의 예시 수를 지운 것과 같은 판단인데, 여기는 한 걸음 더 갔습니다. 개수를 안 적으면 빈 집합 둘이 같아져서 조용히 통과하는 갈래가 생기는데 그것을 닻으로 따로 잡았습니다. 「낡을 숫자를 없앤다」와 「0건 방지」를 같이 세운 모양입니다.
python 쪽을 남기는 것 — 동의합니다
"같은 사실을 두 벌로 적는 것이 아니라 두 번 재는 것" 이 정확한 구별입니다. 두 대조가 같은 두 파일에서 값을 읽으므로 갈릴 자리가 없고, 갈리면 둘 다 빨개집니다(한쪽이 조용해지는 모양이 아닙니다).
제가 하기로 한 것 — 서로 가리키게 하는 줄
#620 에서 "두 대조가 서로를 가리키게 해 달라, 새 테스트가 올라오면 제가 그 줄을 제 파일에 넣겠다" 고 했습니다. 이 PR 이 머지되면 tests/test_manual_source_propagates.py 의 독스트링에 넣겠습니다.
그물이 둘이다 — 이쪽은 ai-service 스위트에서, server 쪽은
ExtractionWarningCodesMirrorTest 가 같은 두 파일을 잰다(#620).
정규식이 갈리는 날 둘 다 고친다.
지금 제 독스트링은 #444·#316 만 가리켜서 server 쪽 대조가 생긴 것을 모릅니다. #613 이 그 파일을 이미 건드리고 있으니 거기 얹거나, 안 되면 별건으로 냅니다.
#613 과 안 부딪힙니다
"집합 비교라 숫자가 안 박혀 있어 어느 쪽이 먼저 들어가도 된다" — 맞습니다. 제 #613 이 10 → 12 로 늘리는데 양쪽을 같이 고치므로 두 대조 다 도는 방향입니다.
Closes #620 맞습니다.
junseo2323
left a comment
There was a problem hiding this comment.
승인합니다. 이 PR 의 급소는 새 테스트가 아니라 build.gradle 두 줄이라고 봤고, 그게 하중을 받는지를 「선언을 빼고 같은 변이를 내는」 방식으로 직접 쟀습니다. 빼면 초록입니다.
❗① 입력 선언이 실제로 하중을 받습니다
ⓐ javadoc 목록에서 QUOTE_NARROWED 삭제 (주석만 바뀐다)
→ > Task :test (UP-TO-DATE 아님) theJavadocListsExactlyTheLiteralCodes FAILED ✅
ⓑ 같은 변이 + build.gradle 의 AiServiceClient.java 입력 선언만 제거
→ > Task :testClasses UP-TO-DATE
> Task :test UP-TO-DATE
BUILD SUCCESSFUL ❗초록
본문이 "실측: 목록에서 코드 하나를 지우고 돌리면 UP-TO-DATE 로 BUILD SUCCESSFUL 이다" 라고 적은 그대로입니다. 테스트만 있고 선언이 없으면 이 대조는 존재하지 않는 것과 같습니다 — 그물이 있는데 안 도는 것이 이 PR 이 고치는 문제 자체라, 같은 함정이 이 PR 안에 한 번 더 있었던 셈이고 그걸 잡아 두신 것이 맞습니다.
build.gradle 주석에 **「반복되는 모양」**으로 적은 것도 맞는 선택이라고 봅니다 — "테스트가 src/main/java 를 텍스트로 읽으면 그 파일을 입력으로 건다" 가 규칙이고, #621 이 핸들러에서 밟은 것까지 세면 벌써 두 번째입니다.
② 나머지 변이 셋
| 변이 | 결과 |
|---|---|
Literal 에서 코드 삭제 |
등식 빨강 |
ci.yml server_extra 에서 schemas.py 제거 |
CiServerFilterMirrorsGradleInputsTest 빨강 |
LITERAL_BLOCK 정규식 어긋내기 |
닻 빨강 (+ 등식도 같이 빨강) |
넷째가 중요한 자리인데, 양쪽 정규식이 같이 깨지면 빈 집합 둘이 같아져 등식만으로는 조용히 통과합니다. 닻을 따로 세운 이유가 그것이고 실제로 그 갈래를 뭅니다.
기준선 server 전체 BUILD SUCCESSFUL · ExtractionWarningCodesMirrorTest tests="2"
③ #613 과의 「합친 결과」를 직접 쟀습니다
"어느 쪽이 먼저 들어가도 된다" 는 주장은 읽는 것으로는 못 믿을 자리라(#559), 둘을 실제로 합쳐서 돌렸습니다.
이 브랜치 + origin/fix/F-EXT-002-evidence-covers-required-456 merge
→ ExtractionWarningCodesMirrorTest BUILD SUCCESSFUL
#613 이 Literal 과 javadoc 둘 다 고치기 때문입니다(EVIDENCE_WIDENED·EVIDENCE_PIECE_MISSING 두 벌 모두). 집합 비교라 숫자가 안 박힌 것도 그대로 확인했습니다 — 순서 제약 없습니다.
④ 곁 — 지금은 문제 없는 두 가지
JAVADOC_LIST는 첫 매치만 씁니다. 그 파일에{@code ExtractionWarning}(가 1 곳뿐이라 지금은 같습니다. 두 번째 목록이 생기면 조용히 한쪽만 보게 되는데, 목록을 두 벌로 적는 것 자체가 이 테스트가 막는 일이라 실질적으로 안 생길 것 같습니다.code: Literal[은schemas.py에 2 곳인데, 패턴이class ExtractionWarning으로 앵커돼 있어 맞는 블록을 집습니다(닻의ITEM_NOT_FOUND가 그것도 같이 봅니다).
python 쪽 대조를 남긴 판단에도 동의합니다 — "같은 사실을 두 벌로 적는 것이 아니라 두 번 재는 것" 이고, 둘이 같은 두 파일을 읽으므로 갈릴 자리가 없습니다.
Closes #620 확인했습니다.
#620입니다. 제가#613리뷰에서 "그물이 없다" 고 잘못 적었던 그 자리이고, 그물은 있는데 한 방향으로만 돌았습니다.무엇이 비어 있었나
Literal을 고치는 쪽은 잡히고 javadoc 을 고치는 쪽은 안 잡혔습니다. 거기서 코드를 지우거나 이름을 잘못 적으면 초록으로 머지되고, 읽는 사람은 낼 수 없는 코드나 모자란 목록을 믿습니다. 두 벌이 갈릴 뻔한 사건이 이미 있었습니다(#444리뷰 — 아홉 vs 열).#521과 같은 모양인데, 거기서는 "서버만 고치는 사람은npm run build를 안 돌린다" 였고 여기서는 CI 판별이 같은 일을 합니다.❗UP-TO-DATE 함정을 또 밟았습니다
대조를 server 쪽에 두고
schemas.py를 입력으로 걸었는데, 그것만으로는 안 돌았습니다.AiServiceClient.java는 main 소스라 주석만 바뀌면 바이트코드가 같고,test태스크는 클래스에만 걸려 있습니다.#621이 핸들러에서 밟은 자리와 같아서build.gradle주석에 반복되는 모양으로 적어 뒀습니다 — 테스트가src/main/java를 텍스트로 읽으면 그 파일을 입력으로 걸어야 합니다.이쪽은 양방향으로 돕니다
AiServiceClient.java는 모듈 안 경로라ci.yml에는 안 더합니다 —^server/가 이미 잡고, 미러 테스트의 모집단은'../'경로입니다.python 쪽 대조를 지우지 않습니다
그쪽은
server/없이 받은 환경에서 조용히 통과하도록 갈래가 있고, 그 조건에서 그쪽이 돕니다. 두 대조가 같은 두 파일에서 값을 읽으므로 갈릴 자리가 없습니다 — 같은 사실을 두 벌로 적는 것이 아니라 두 번 재는 것입니다.개수를 적지 않습니다
코드는 늘어나므로 그 숫자가 낡습니다(
#621이COPIES_CLAIM설명문에서 지운 것과 같은 판단). 대신 양쪽을 실제로 읽었는지를 닻으로 따로 잽니다 — 한쪽 정규식이 어긋나면 빈 집합 둘이 같아져서 조용히 통과합니다.역검증
Literal에서 코드 하나 삭제ci.ymlserver_extra에서 새 경로 제거CiServerFilterMirrorsGradleInputsTest빨강Literal블록 정규식을 어긋나게검증
#613이 이 목록을 10 → 12 로 늘리는데 집합 비교라 숫자가 안 박혀 있어 그 PR 과 충돌하지 않습니다. 어느 쪽이 먼저 들어가도 됩니다.Closes #620