Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions REPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,29 @@
**4종 전건 KILLED** 로 만들었다(`MakeConcatWrongDescriptor` · `MakeConcatWithArgument`).
- ★**픽스처가 «출력»한다**(`ab`) — ★레시피를 틀린 길이로 합성해도 **링크되고 실행된다**. 값을 버리면 그 오류가 안 보인다(M2 가 그 증거).
- 검증: `cargo test --all` **573 → 574 / 0 failed** · 픽스처 재생성 **멱등**(기존 4개 바이트 동일) · DoD 7명령 rc=0.
## [2026-09-17] 「어느 javac 이 만들었나」를 «기록»이 아니라 «검증»으로 바꿨다 (rustjava-adopt-indy-fixture-jdk-pin-and-slot-accounting-p1)
- 무엇을: 기록된 도구로 **다시 빌드해 바이트를 비교**하는 검사를 만들었다. ★**제품 코드 무접촉**(Rust 변경은 doc 주석 1곳).
- 왜: 채택 제안 `2026-09-16-indy-fixture-jdk-pin-and-slot-accounting#p1`.
- 사용자 영향: 없다(시험 위생). ★바뀐 것은 ★**「javac 26.0.1 로 만들었다」가 «주장»에서 «검증된 사실»이 된 것**이다.
- ★★**제안의 결론 «둘»이 실측으로 반증됐다**:
⑴「**Nothing offline can verify** a recorded compiler version … buys **provenance, not enforcement**」 →
★**거짓**. javac 은 같은 소스·플래그·컴파일러에 **결정적**이라 ★**`test-data/indy` 6개가 바이트 단위로 재현된다**.
⑵「강제 가능한 축은 `constant_pool.rs` 의 상수 개수뿐이고 **한 픽스처만** 덮는다」 → ★**거짓**.
★**javac 산출 indy 픽스처 3/3 이 형상 단언을 갖는다** — `ConstantKinds`(태그별 정확한 개수) ·
`StringConcat`(신원 4축 + 인자가 «가리키는 값» + ★**바이트 창** `[15,6,0,35]`) · `Lambda`(`args[0]==args[2]!=args[1]`).
★제안이 든 위험(「현대 javac 이 enum switch 를 condy 로 낸다」)은 ★**`ConstantKinds` 의 Dynamic 개수 3 이 이미 잠근다.**
- ★**만든 것**: `test-data/src/verify-javac-fixtures.sh` — ★`--release` 를 **픽스처 자신의 major − 44** 로 읽어
**외부 표에 의존하지 않고**, ★명시한 `JAVAC` 가 안 되면 **조용히 대체하지 않고 rc=2** 로 멈추며,
★**「못 만들었다」와 「만들었는데 다르다」를 «가른다»**(합치면 발견을 과장한다).
★**CI 에 배선하지 «않았다»** — 워크플로에도 PATH 에도 JDK 가 없어 **어디서나 실패하거나 어디서나 건너뛴다**.
- ★**실패담 둘(밟은 대로 적는다)**: ⑴`command -v javac` 이 macOS **스텁**을 고른다 ⇒ **실행해서** 판별 ⑵★`-sourcepath` 를 넣었다가
**더 나빠졌다** — `test-data/src/Exception.java` 가 `java.lang.Exception` 을 가려 멀쩡하던 재현이 타입 오류로 무너졌다 ⇒ **되돌리고 그 대가를 따로 보고**.
- ★**개악 대조**: 커밋본 **1바이트 반전** → ★**✗ 감지** · 복원 → 6/6 재현 · 명시 `JAVAC` 부재 → ★**rc=2(통과 아님)**.
- ★**일반화 — 값만 적고 고치지 않았다**: 루트에 돌리니 **109 rebuilt · 104 재현 · 5 상이 · 3 재빌드 불가**.
상이 5건(`MonitorSemantics`×3 · `NativeMethod` @8 · `OddEven` @21)의 ★**원인은 단정하지 않는다**(다른 컴파일러 ↔ 빌드 후 소스 수정이 둘 다 맞는다).
★그래도 적는 이유: ★**제안이 걱정한 드리프트가 «실재»한다는 첫 직접 증거**다.
- 검증: `cargo test --all` **572 / 0 failed / 1 ignored**(doc 주석만 바꿔 **불변**) · DoD 7명령 rc=0.
- 후속 추천: 루트 5건이 **왜** 재현되지 않는지 규명(M) — 상세 = `docs/worklog/2026-09-17-javac-fixture-provenance-verified.md`.
## [2026-09-17] 신원 4축을 «각각» 관측 가능하게 했다 — 감사의 「고칠 것이 없다」를 정정한다 (rustjava-adopt-cp-tag-passthrough-detectable-p0-fix)
- 무엇을: `string_concat.rs` 의 부트스트랩 신원 **4축**(kind·class·name·descriptor) 중 ★**3축이 «관측되지 않고» 있었다** —
근접 실패 픽스처가 **class 축 하나**뿐이었기 때문이다. 나머지 3축의 픽스처를 만들었다. ★**제품 코드 무접촉.**
Expand Down
38 changes: 38 additions & 0 deletions STATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,44 @@
열린 PR **#57**(ci-pending)이 「`.class` 미등재는 핀이 **실패**시킨다」(`test-data/class-file-versions.txt`)를 세우므로,
★**이 PR 이 먼저 착지하면 #57 의 표에 이 셋이 «없어»** 그 회차가 red 가 된다(해소 = `record-class-file-versions.py` 재생성).
★**텍스트 충돌 0 이라 `mergeable` 로는 보이지 않는다** — 같은 고지가 #60 회신에도 있다(그쪽은 다른 3개).
- [rustjava-adopt-indy-fixture-jdk-pin-and-slot-accounting-p1] ★★**「어느 javac 이 만들었나」를 «기록»에서 «검증»으로 바꿨다.**
채택 제안 `2026-09-16-indy-fixture-jdk-pin-and-slot-accounting#p1`(worklog json `adoptedProposals` 기록). ★**제품 코드 무접촉.**
★★**제안의 결론 «둘»이 실측으로 반증됐다 — 그래서 제안이 «불가능»하다고 적은 쪽을 만들었다**:
⑴「**Nothing offline can verify** a recorded compiler version … buys **provenance, not enforcement**」 → ★**거짓**:
javac 은 같은 소스·플래그·컴파일러에 **결정적**이라, 기록된 도구(`javac 26.0.1 --release 21`)로 재빌드하니
★**`test-data/indy` 의 6개가 «바이트 단위로 동일»**했다. ⇒ ★**기록이 «재현»으로 검증된다.**
⑵「강제 가능한 축은 `constant_pool.rs` 의 상수 개수뿐이고 **한 픽스처만** 덮는다」 → ★**거짓**:
★**javac 산출 indy 픽스처 «3/3»이 형상 단언 보유** — `ConstantKinds`(MethodType 1·Dynamic 3·MethodHandle 7·InvokeDynamic 3) ·
`StringConcat`(부트스트랩 **4축** + 인자가 «가리키는 값» `"a\u{1}"` + ★**바이트 창** `[15,6,0,35]` · 「layout changed」로 실패) ·
`Lambda`(`LambdaMetafactory.metafactory` · 인자 3 · ★`args[0]==args[2]!=args[1]`).
★**제안이 든 위험(「현대 javac 은 enum switch 를 condy 로 낸다」)은 `ConstantKinds` 의 Dynamic **3** 이 이미 잠그고 있다.**
★**만든 것**: `test-data/src/verify-javac-fixtures.sh` — ⑴★`--release` 를 **픽스처 자신의 major − 44** 에서 읽어
★**외부 표(형제 PR #57 의 버전 표)에 의존하지 않는다**(동기화할 것이 없다 · 미착지 의존도 없다)
⑵★명시한 `JAVAC` 가 안 되면 **조용히 다른 컴파일러로 대체하지 않고 rc=2** — 「무엇이 검증했나」가 흐려지면 안 된다
⑶★**「못 만들었다」와 「만들었는데 다르다」를 «가른다»** — 합치면 발견을 과장한다.
★**CI 에 배선하지 «않았다»**: `.github/workflows/rust.yml` 에 JDK 가 없고 PATH 에도 없다 ⇒
JDK 를 요구하는 테스트는 ★**어디서나 실패하거나 어디서나 건너뛴다.** 이건 «재생성했을 때 사람이 돌리는» 검사다(doc 주석에 명시).
★★**실패담 둘을 남긴다 — 이 회차가 실제로 밟았다**: ⑴`command -v javac` 이 macOS **스텁**(실행되는데 「JDK 없음」)을 고른다
⇒ 경로가 아니라 **실행해서** 판별한다 ⑵★**`-sourcepath` 를 넣었다가 «더 나빠졌다»** — `test-data/src` 에 **`Exception.java`**·
`Array.java`·`Method.java` 가 있어 javac 이 `Exception` 을 ★**`java.lang.Exception` 이 아니라 그 픽스처로** 해석했다
(멀쩡히 재현되던 파일들이 `incompatible types` 로 무너졌다) ⇒ **되돌리고 그 대가**(형제 참조 소스는 홀로 재빌드 불가)를 **따로 보고**한다.
★**개악 대조**: 커밋본 **마지막 1바이트 반전** → ★**✗ 감지** · 복원 → **6 reproduced** · 명시 `JAVAC` 부재 → ★**rc=2 「nothing was verified」**(통과 아님).
★★**일반화 — 시켜 보고 «나온 값»만 적었다(고치지 않았다)**: 루트 `sh … test-data` →
**109 rebuilt · 104 재현 · ★5 상이 · 3 재빌드 불가**. 상이 5건 = `MonitorSemantics`(+내부 2) · `NativeMethod`(`--release 8`) · `OddEven`(`--release 21`).
★**원인은 단정하지 않는다** — 「다른 컴파일러」와 「빌드 뒤 소스 수정」이 **둘 다 이 관측과 맞는다**. ★범위 밖이라 후속(M)으로 넘겼다.
★**그래도 적는 이유**: ★**제안이 걱정한 드리프트가 «실재»한다는 첫 «직접» 증거**다(그전까지는 버전 분포에서의 추론이었다).
★**직전 회차가 «커밋하지 않기로» 한 개악 하네스와 다른 종류다** — 그건 **제품 소스를 치환**해 죽으면 트리를 오염시켰고,
이건 **읽고 비교만** 한다(실패해도 트리 무변) ⇒ 그래서 **남겼다.**
★`cargo test --all` **572 / 0 failed / 1 ignored**(doc 주석만 바꿔 **불변**) · DoD **7줄 전건 rc=0**.
★★**게이트③ 착지 — PR #58 · `--merge`**(등재 repo · `merge_strategy: merge` 선언분). 게이트② **approve** ·
핀 `38c02a2d` **불이동**(착수 실측 2026-09-17T00:27:39Z · 핀에서 `ci-presence` **rc=0 CI_GREEN**).
★**충돌은 원장 2파일뿐**(`REPORT.md`·`STATE.md`) — 형제 **#55** 착지분과 겹쳤고 코드 파일 충돌 **0**.
해소는 전건 보존·합집합·**시간순**: 이 회차(`38c02a2d` 05:22)가 main 쪽 최신 항목(`30a31bda` 04:04)보다 **뒤**라 위에 얹었다.
★줄 소실 **0**(양방향) · 합집합 밖 신규줄 **0** · ★계약 12 착지 diff numstat **해소 전후 동일**(6파일 · 해소면 밖 변경 0).
★배포 **0** — 이 저장소에 배포 워크플로가 **없다**(CI 2종 + 스케줄 2종 + PR 댓글 1종) · 자식 PR **0건** · 주기 자동 커밋 **0건**.
★★**게이트③ 2회차 — 형제 #59 가 그 사이 착지(`66bc49e8`)해 base 를 다시 당겼다.** 충돌은 또 **원장 2파일뿐**(코드 충돌 0).
★**이번엔 시간순이 «뒤집혔다»** — main 쪽 항목(`3b04712e` 06:52)이 이 회차(`38c02a2d` 05:22)보다 **뒤**라 **위**에 얹었다.
★두 번의 base 당김을 거쳐도 이 PR 의 기여 numstat 은 **불변**(`94/0` 검증 스크립트 · `14/2` 핀 테스트 · worklog 2건).
- [rustjava-adopt-cp-tag-passthrough-detectable-p0-fix] ★★**신원 4축을 «각각» 관측 가능하게 했다 — 감사의 「고칠 것이 없다」를 정정한다.**
게이트② **request-changes** 승계(PR #55 · 핀 `ab13a3c7`). ★**제품 코드 무접촉** — 없던 것은 **픽스처**다.
★★**무엇이 틀렸나**: 직전 감사의 **M7**(「신원 4축 검사 제거」)은 네 비교를 ★**한꺼번에** 지운다 ⇒ 그 red 가 증명하는 것은
Expand Down
39 changes: 39 additions & 0 deletions docs/worklog/2026-09-17-javac-fixture-provenance-verified.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"schema": "worklog/v1",
"date": "2026-09-17",
"taskId": "rustjava-adopt-indy-fixture-jdk-pin-and-slot-accounting-p1",
"summary": "Turned the recorded compiler from an assertion into a check: rebuilding test-data/indy with the recorded javac reproduces all six class files byte for byte. Both of the proposal's blocking claims — that nothing offline can verify a compiler record, and that shape assertions cover only one fixture — are false, measured.",
"changes": [
"test-data/src/verify-javac-fixtures.sh: new. Rebuilds javac-compiled fixtures and compares bytes, reading the --release from each fixture's own major version so nothing has to be kept in sync",
"tests/test_fixture_pins.rs: the pin's doc comment now records that the compiler was verified by rebuilding, with the command and the date, instead of only naming it"
],
"verification": [
"test-data/indy: 6 rebuilt, 6 reproduced byte-for-byte, 0 differed, under javac 26.0.1 --release 21 — the toolchain the comment records",
"the proposal's claim that shape assertions cover one fixture is false: ConstantKinds has exact tag counts in classfile/src/constant_pool.rs, StringConcat has the four identity axes plus what its static argument points at plus a byte-window check in classfile/tests/test.rs, and Lambda has its bootstrap identity plus the args[0] == args[2] != args[1] relation",
"controlled mutation: flipping the last byte of the committed StringConcat.class is detected as differed; restoring returns 6 reproduced",
"an explicitly set JAVAC that does not work exits 2 with 'nothing was verified' rather than silently falling back to another compiler",
"generalization probe over test-data root: 109 rebuilt, 104 reproduced, 5 differed (MonitorSemantics and two inner classes, NativeMethod at --release 8, OddEven at --release 21), 3 could not be rebuilt alone",
"-sourcepath was tried and reverted: test-data/src contains Exception.java, so putting it on the source path makes javac resolve Exception to the fixture instead of java.lang.Exception and turns clean rebuilds into type errors",
"cargo test --all: 572 passed / 0 failed / 1 ignored, unchanged — the only Rust change is a doc comment",
"DoD 7 commands all rc=0"
],
"issues": [
"The check cannot run in CI: there is no JDK in the workflow and none on PATH here. It is a manual check, so it is only as good as the habit of running it after regenerating a fixture.",
"Five root fixtures do not reproduce. Whether that is a different compiler or a source edited after the fixture was built was not determined — both fit the observation, and chasing it is outside this ticket's target of test-data/src/indy.",
"Three root fixtures cannot be rebuilt in isolation because their sources reference sibling classes, and -sourcepath is not usable here for the reason above."
],
"adoptedProposals": [
"2026-09-16-indy-fixture-jdk-pin-and-slot-accounting#p1"
],
"proposals": [
{
"title": "Find out why five root fixtures do not rebuild to their committed bytes",
"plainSummary": "Rebuilding the main test-data fixtures reproduces 104 of them exactly. Five come out different, and we do not know why.",
"userBenefit": "Either the fixtures get back in step with their sources, or we learn that a test has been asserting against bytecode nobody can regenerate — both are better than not knowing.",
"why": "Measured by the script this round added: MonitorSemantics and its two inner classes and NativeMethod differ at --release 8, OddEven differs at --release 21. A different compiler and a source edited after the fixture was built both explain it, and the difference matters: the first is harmless provenance drift, the second means the fixture and its source have diverged.",
"tradeoff": "The likely fix for the second case is recompiling, which changes bytes — and several tests compare fixture output against committed .txt files, so a recompile can turn into a behaviour change. Also three more fixtures cannot be rebuilt alone at all, so the survey cannot be completed without deciding how to compile sources that reference siblings, in a directory where Exception.java shadows java.lang.Exception.",
"effort": "M",
"target": "test-data/, test-data/src/"
}
]
}
Loading