- [rustjava-upstream-sync-squash-defeats-convergence] ★S1~S4 가 착지하고도 fork 가 upstream 에
한 걸음도 가까워지지 않은 근인을 확정하고 계보를 기록했다. 근인 = 게이트③ 제품 repo
--squash. 증명은 머지커밋 부모 수다 —6bfe97c4·11ef5010·4bb796de·3a597768전건 1개(커밋 7·10·15·21이 각각 1로 접힘). ★반증 시도는 실패했다(= 가설이 맞다): 브랜치34a4235는 부모 2개 (c80638a+3296139)인 진짜 머지 ⇒ 계보는 브랜치에 있었고 스쿼시가 버렸다(cherry-pick 가설 기각). 처방 =origin/main위git merge -s ours 3296139— 트리 오브젝트 SHA 동일(c4f57d10…)로 트리 변경 0. ★git diff --stat빈 출력은-s ours정의상 항상 참이라 근거로 쓰지 않았다(S4 교훈). 효과:merge-base62cf0c6a→3296139c· behind 33 → 18 · 컷 조상 0/4 → 4/4. ★★이 PR 이--squash로 착지하면 위 전부가 무효다 — 반드시gh pr merge --merge. ★회차마다-s ours를 다시 넣는 지금 방식은 러닝머신이다 — S4 의c80638a가 정확히 그 처방이었는데 PR #17 의 스쿼시에 함께 지워졌다(이 리니지에서 네 번 반복). PR 대기 — 게이트③ 미착지. - [rustjava-upstream-sync-s4] upstream 컷
3296139(#184 GlobalRef · CLI classpath · CDC text) 머지 — 충돌 2 해소(java/lang/thread.rs·jvm/src/jvm.rs). ★첫 조치가git merge -s ours --no-ff 822504b— 그것이 ★충돌 20 → 2를 만들었다. PR 대기 — 게이트③ 미착지. ★★계획서의 「S4 새 충돌 0」 예측은 틀렸다 — 실측 2건이고,thread.rs는 S1·S3 에 이어 세 번째다. ★**test_timer_periodic여백을 넓혔다(500→2000ms) — ★«회귀»가 아니라 «만성 경계 테스트»다**(단정 불변). ★컷 양쪽이 같은 비율로 흔들린다(조건 맞춘 교대 실측 · ①절) — 전 판본의 「컷이 들여왔다」는 틀렸다. - [rustjava-coverage-workflow-codecov-token-red]
coverage상시 red 해소 —fail_ci_if_error: false. ★실증: 착지 전 브랜치에서 «이 저장소 최초의 green coverage» (25번째 run, 앞선 24건 전부 red). PR 대기 — 게이트③ 미착지.
- [rustjava-upstream-behind-measure-scheduled-workflow] ★★**
behind를 «재는» 자리 신설 —.github/workflows/upstream-behind.yml.** 채택 제안2026-09-04-upstream-sync-cadence-decision#p0. ★임계는 정해졌는데(behind ≥ 20· PR #29 착지) ★재는 주체가 없었다 (git grep -lI 'rev-list --count' origin/main -- .github/ scripts/→ 0건). ★주기 = 주 1회(cron: "17 6 * * 1") — 선례(rust-audit일간)를 베끼지 않고 임계 도달 속도로 정당화했다: behind 20 도달 중앙 44일 · ★최소 9일 ⇒ ★7 < 9 라 한 주기 넘게 못 놓친다 · 일간은 7배 비용에 판단 가치 0. ★★알림 = ⒝ Job Summary + annotation · «항상 green» — ★취향이 아니라 실측으로 골랐다: ⒜red 는 여기서 안 듣는다(선례rust-audit최근 20 run 중 19 failure 인데 ★대응 티켓 0건) · 예약 red 는 ★main tip check-run 에 붙어(실측8c1238b5에auditfailure 7건) 게이트③의 「착지본 green」 읽기를 흐린다 (★단 PR 은 막지 않는다 — PR head 와 sha 가 다르다) · ⒞이슈는 ★이 fork 가 issues 비활성이라 «불가». ⇒ ★⒝ 가 «남은 것»이고 그 «수동성»을 알고 골랐다 — ★재개 조건이 그 대가를 «잰다» (「behind ≥ 20이 7일 이상인데 회차 미개시」 · 세는 명령·오늘의 값을 §5-B ⒠ 에 박았다). ★한 번 돌려 오늘의 값: ★behind0·merge-basebd42427= upstream HEAD ⇒ 임계 미만. ★upstream 발신 0(remote 추가 + fetch 뿐 ·permissions: contents: read) · ★자동 발권 0 · ★임계 20 무접촉 · ★bin/healthcheck·orchestrator 무접촉 ·scripts/무접촉(파리티 rc=0) ·.rs0줄 · S9 미개시. ★게이트③ 완료: PR #31 — ★★**--merge착지**(★--squash아님 · 등재 repo). 머지커밋 sha 는 회신merged:참조. ★착지 후 «워크플로를 실제로 돌려» 확인했다 — 구현 회차가 「본문 명령만 태웠고 워크플로 자체는 못 돌렸다」고 자인한 그 구멍이다. 결과는 회신 참조. ★게이트② 1회차 approve — 반려 0. - [rustjava-worklog-absence-machine-enforcement-decision] ★★워크로그 «부재»를 기계로 잡을지 «판정» — 결론: 지금은 «넣지 않는다».
채택 제안
2026-09-04-worklog-mandate-and-local-gate#p0. ★**scripts/check-worklog-json.py무접촉**(6축 무회귀 · rc=0) ·.rs0줄 · 과거 backfill 0 · qts 잠금·upstream 리니지·파리티 검사기 무접촉. ★★근거는 «사전 등록된 두 임계»가 «둘 다» 발화하지 않았다는 것 하나다 — 의무화 회차가 데이터를 보기 «전»에AGENTS.md에 등록했고, ★그 문서가 정한 재측 시점(「2026-09-04 이후 열 번째 착지 회차」)에 실제로 도달했다(실측 11). ★⒜ 미작성: 창b3a4cf4..origin/mainfirst-parent 15건 중 1건(6.7%) — 임계 ≥2 미달. ★그 1건은 규약보다 먼저 갈라진 PR #13(createdAt2026-08-23 ↔ 규약 착지 2026-08-26 · ★인용이 아니라 실측) ⇒ ★규약을 «알 수 있었던» 회차만 보면 0 / 14 = 100%. ★⒝ 열린 카드:.json15 · proposals 26 − disposed 13 = ★13(기준선 5) — 임계 <5 미달(★의무가 카드를 늘렸다). ★★약점을 숨기지 않는다: ⒤「100%」는 단일 집행 주체의 습관일 수 있다(리니지는 13개로 갈렸으나 git author 가 하나다) ⒥정본 술어가 느슨하다(「만졌다」는 옛 워크로그 한 줄 추가도 통과 — 엄격 술어로 재도 이번 창은 같은 14) ⒦실패는 여전히 조용하다 ⇒ 「위험이 없다」가 아니라 「임계가 아직 발화하지 않았다」이다. ★재개 조건 + 세는 명령 + 오늘의 값1을AGENTS.md§Round Worklog 에 박았다(2 이상이면 재개 · ★엄격 술어). ★재개하면 만들 것도 미리 적었다: baseline sha 금지 · ★PR diff 로 «조건부» 판정(REPORT 후속 추천을 만졌으면 새 쌍 필수) · 정상 참작은createdAt으로(★제목·라벨 금지) · 기존 6축 보존. ★측정 함정 1건 기록: 「회차 = 부모 2개」로 세면 스쿼시 착지를 놓친다(그 술어로는 12/12 · 정본 술어로 15/1). ★게이트③ 완료: PR #30 — ★★**--merge착지**(★--squash아님 · 등재 repocontracts/upstream-sync-repos.conf:22). 머지커밋 sha 는 회신merged:참조. ★게이트② 1회차 approve — 반려 0. ★착지로 「재개 조건」이AGENTS.md에 살아 있다: 엄격 술어 값이 2 이상이면 다시 연다(오늘 1). - [rustjava-upstream-sync-cadence-decision] ★★upstream 동기 «정기 축» 판정 — 결론: ⒝ 격차 기반
behind ≥ 20. 채택 제안2026-09-04-sync-contract-stale-assets-decision#p0. ★신설 0(검사기·크론·워크플로) ·.rs0줄 · ★S9 미개시(behind 0). ★★제안의 전제(「벌어진 뒤에 받으면 훨씬 비싸다」)를 «먼저 재서» 반증했다: 회차 커밋 수 ↔ 충돌의 상관계수 ★부호가 «음». ★★**[게이트② 정정] 초판 표는 base·(델타/누적) 병기가 없어 기준이 섞여 있었다** ⇒ 정본을 «누적»으로 통일해 재계산: A 초판 r=−0.169·합28 · B S4 정정 r=−0.134·합30 · ★C 정본 r=−0.155·합33(37커밋 → 14 ↔ 8커밋 → 19). ★세 열 모두 부호가 음 ⇒ 판정 불변 · ★r 은 n=8 비무작위 표본이라 «부호 판정»으로만 쓴다. ★누적 충돌도 포화한다: 고정 base 에서 7커밋 16 → 33커밋 19(26커밋 더 벌려도 +3). ⇒ ★충돌을 만든 것은 «몇 개 왔는가»가 아니라 «무엇이 왔는가»(우리 포크 지점 3곳 + 개명 스윕 같은 사건). ★그런데 결론이 「아무것도 안 한다」가 되지는 않았다 — 반증된 것은 «비용이 격차에 비례한다»는 기전이고, 「아무도 챙기지 않는다」는 위험은 그대로 참이다. ⇒ 축은 두되 임계를 포화점 «뒤»에 놓았다. ★시간 기반 기각: upstream 이 37% 의 주에 커밋 0(12개월 144커밋/51주 · 중앙 1/주)이라 시간 축은 ★behind 0 인데 회차를 여는 «빈 회차» 를 만들고, 회차 오버헤드(티켓 3건)가 고정이라 자주 받으면 총비용이 는다. ★사건 기반 기각: S3 충돌 델타 +9(누적 11 · base S2 착지본 · merge-baseaf4f6f8)는 upstream «신규» 파일에서, S8 누적 8 · 델타 +8(base3fb08a8· merge-baseba5797b)은 전 트리 개명에서 왔다 ⇒ 경로 트리거가 대부분을 놓친다. ★임계 20 근거: 아래로는 7커밋 포화점, 위로는 33 이 미측정 구역 입구. ★★**[정정] 초판의 「실제로 아팠던 값」은 «지웠다»** — 그것은 이 판정 자신이 «금지한» 독법(8회차를 격차의 비용으로 읽는 것)이라 자기모순이었다. ★★**「20」은 밴드(733) 안에서 «고른» 수다** — 밴드는 실측이고 그 안 누적이8회** · 회차당 충돌(정본 누적) 중앙 2.5 · 게이트② 사이클 8회차 중 7회가 1. ★방아쇠 = 기계가 «재고» 사람(총괄)이 «발권» — 재는 자리 권고는 이 repo 의 예약 워크플로(선례16→17→17→17→19로 평평하다. 실측 도달 중앙 44일(★상수 인용 금지 — 재측 41일 · 창 정의 ±3일 · 결론 영향 0) ⇒ **연 6rust-audit.yaml), 대안bin/healthcheck는 orchestrator 소관이라 별건. ★구현은 이 회차가 하지 않았다. ★재측정 조건(3회차 뒤 · 충돌 중앙 ≥5 면 임계 내리고 · 도달 간격 ≤14일이면 올린다)을 §5-B 에 오늘의 값과 함께 박았다. ★★**「오래됐다」는 재개 사유가 아니다 — 이 축은 «시간»이 아니라 «격차»로 열린다.** ★게이트③ 완료: PR #29 — ★★**--merge착지**(★--squash아님 · 등재 repocontracts/upstream-sync-repos.conf:22). 머지커밋 sha 는 회신merged:참조. ★게이트② 3회차 만에 approve(초판 → fix → fix2) — ★반려 둘이 모두 «수를 어떻게 적었는가»였다: ⑴base·(델타/누적) 병기 없이 기준을 섞었다 ⑵그 정정이 «표»에만 닿고 «산문·summary»로 전파되지 않았다. ⇒ ★**「표를 고쳤다고 문서가 고쳐진 것이 아니다」가 이 리니지가 남긴 규율이다. ★부모 #27·#28 착지로 두 번CONFLICTING이 됐고 그때마다 머지로 해소했다(마지막은REPORT.md1건) — ★충돌 중에는pull_request검사가 «구조적으로» 못 돈다**(검사 1건 → 10건으로 확증). - [rustjava-dod-ci-parity-sibling-repo-survey] ★★형제 repo(
wie·qts) 파리티 락 필요성 «조사+판정» — 둘 다 «⒞ 조건부 필요». 채택 제안2026-09-04-dod-ci-parity-lock#p1. ★읽기 전용(형제 repogit·PR·파일 수정 0 ·gh api /contents로만 읽었다) · 구현 0. ★★검사기는 «포팅 불가»다 —wie는 DoD 정본이AGENTS.md이고 4번째 게이트(cargo test)가 ★**if:로 갈린 2 step + 블록 스칼라라 우리 파서의 「조건부 = 제외」가 ★거짓 red** 를 만든다 ·qts는 DoD 가make타깃 이름(Makefile 간접층)이고 ★toolchain 매트릭스가 없어 축 B 가 성립하지 않으며gitleaks는 ★action 이라 어떤run:파서도 못 본다. ★★그런데 어긋남은 «둘 다 실재»한다 — 이력으로 쟀다:wierust.yml실패 34건 전수 중 ★beta 셀에서만 실패한 clippy 9건(26%) 인데 four gates 에cargo +beta가 없다(문자열beta규범 문서 0건) ·qtsci.yml최근 실패 60건 전수 중 ★**uv run ruff format --check .«만» 실패 10건(17%)** 인데make lint는 안 친다 (문자열format규범 문서 0건). ⇒ ★먼저 할 일은 락이 아니라 «각 한 줄» — 그 다음이 포팅이다. 다음 티켓 3건(T1·T2·T3)의 축과 합격선만 적었다(발권은 총괄 몫). ★★일반 사실: 세 repo 가 전부 이 어긋남을 갖고 있었고 어긋난 자리가 전부 규범 문서에 없었다 — 「사람이 문서를 최신으로 유지한다」가 세 repo에서 각각 실패했다. ★이 repo 검사기·rust.yml·DoD 블록 무접촉 ·.rs0줄. ★게이트③ 완료: PR #28 — ★★**--merge착지**(★--squash아님 · 등재 repo). 머지커밋 sha 는 회신merged:참조. ★부모 #27 착지로CONFLICTING이 됐고 «해소 회차»가 별도로 돌았다 — 충돌STATE.md1건 · ★판단 필요 hunk 0(두 판본 16줄 중 15줄 바이트 동일 · 차이는 «착지 상태»뿐) · 승인 내용 무접촉 · ★★검사 «1건 → 10건» 전건 성공(충돌 중에는pull_request트리거가 «구조적으로» 못 돈다 — 그 기전이 해소로 확증됐다). ★재검은 총괄이 «건너뛴다»로 판정(원 게이트② 핀5c2ed7bc· 해소 후 head8ab6bb16). - [rustjava-dod-ci-parity-cross-product-decision] ★★파리티 락 «교차곱» 확장 «판정» — 결론: 넓히지 «않는다».
채택 제안
2026-09-04-dod-ci-parity-lock#p0. ★검사기 로직 변경 0 ·.rs0줄 ·rust.yml무접촉 · DoD 블록 무접촉. ★비용을 «먼저» 쟀다(추정 0): 무변경 재실행 19s → 38s = 2.00× ↔ ★소스 1줄 편집 후 89s → 326s = 3.66×. ⇒ ★제안 문면의 「두 배」는 «무변경»에서만 참이고 회차가 겪는 케이스는 3.66배다. 지배항 =cargo +beta test --all215s(같은 편집에서 stable test 66s 의 3.3배) · 콜드 1회 +171s. ★돈이 아닌 비용 둘: ⑴rustfmt가 beta 에 미설치라cargo +beta fmt는 오늘 그대로 rc=1 ⑵★툴체인 교대 축출은 «없다»(beta 3줄 직후 stable clippy 2s · test 25s) — 시간이 아니라 디스크를 쓴다(target46G). ★실익은 «따로» 쟀다: CI 에만 있는 조합 3개(fmt@beta·wasm32 clippy@beta·test@beta)로 비어 있지 않지만, ★★**rust.yml이력 76 run(성공 73 · 실패 3) 전수 분해에서 그 3개가 «새로» 잡았을 사건은 «0건»** 이다 — 이 저장소의 beta 전용 실패는 전건cargo clippy --all이고 그 줄은 DoD 가 이미+beta로 덮는다 (나머지 1건은 fmt 인데 6셀 전건 실패라 stable 이 잡는다). ⇒ ★**+237s/회차를 내고 얻는 것이 0.** ★부분 확장(fmt@beta만 · +3s)도 기각 — 이력 0건 · beta rustfmt 미설치가 기본 · 부분 교차곱은 모델 변경 요구. ★재개 조건 + 세는 명령 + 오늘의 값0을docs/upstream-sync-approach.md§4 에 박았다 (「cargo clippy --all«이외» step 이 beta 셀에서만 실패한 run 이 1건이라도 생기면 다시 연다」). ★검사기 docstring 에만 결정 포인터 1블록(그 파일이 「Widening … is a decision」이라 적고 결정 결과를 몰랐다). ★게이트③ 완료: PR #27 — ★★**--merge착지**(★--squash아님). ★이번엔 «두 겹»으로 강제됐다: ⑴등재 repo(contracts/upstream-sync-repos.conf:22) ⑵★자식 PR #28 이 이 브랜치 «위에» 얹혀 있다 (git merge-base --is-ancestor 204f98be <#28 브랜치>= YES) ⇒ 스쿼시하면 그 커밋들이 재작성돼 #28 이 깨진다. ★단 #28 의 base 는main이라 브랜치 소멸로 닫히지는 않는다(ripple형 사고와 다른 형상). 머지커밋 sha 는 회신merged:참조. ★착지 후 반사실:origin/main..upstream/main= 0 유지. - [rustjava-local-dod-vs-ci-matrix-mechanical-check] ★★로컬 DoD ↔
rust.yml«기계 대조» 신설 —scripts/check-dod-ci-parity.py+ CI jobdod_parity. ★5회차 리니지의 상수를 «사람 손»에서 뺐다. ★★설계 제약을 먼저 지켰다 — «낡은 문자열 스캐너»를 만들지 «않았다». 게이트② 검수자가 실측으로 「F1 은 «수»가 아니라 «말»이라 문자열 검사기로도 안 잡힌다」를 세웠기 때문이다. ⇒ 문서의 «문장»이 아니라 ★문서가 틀리는 «원인»(두 집합이 갈린 것)을 잡는다 —CLAUDE.mdDoD 코드블록과rust.yml을 각각 파싱해 대칭차를 낸다(★정본 위치는 문서가 아니라 스크립트 안에 박혀 있다 · 계약 3). ★축은 둘: A=명령 집합 · B=toolchain 집합(strategy.matrix.rust↔cargo +<tc>접두). ★오늘 대칭차 0 ⇒ 계약 2 대로 경고가 아니라 rc=1(막는다) 로 배선했다. ★검사기가 자기 줄을 «양쪽에» 넣는다 — CI job 과 DoD 블록 둘 다python3 scripts/check-dod-ci-parity.py라 ★자기 존재를 자기가 강제한다. ⇒ DoD 는 6줄 → 7줄. ★★개악 5건 전건 red · 무개악 green(DoD 줄 제거 · CI- run:추가 · 매트릭스 nightly 추가 · DoD+beta제거 ·rust-toolchain.toml신설) — ★공허하지 않다. ★침묵하지 않는다: 성공에도 「명령 N개 · toolchain N개로 «둘 다 일치»」를 찍고, ★못 보는 것(조건부 step = OS 축 · 두 축을 «교차곱»으로 보지 않는 것)도 그 자리에서 함께 찍는다. ★교차곱 미적용은 결함이 아니라 2026-09-04 결정이 «고른 값»이다(cargo +beta test= 두 번째 toolchain 전면 재빌드 · lint 를 지는 축은 clippy 뿐) — 넓히는 것은 «새 결정»이다. ★**§4 의 셸 두 토막을 «지웠다»** — 같은 술어가 두 벌이면 다음 사람이 한쪽만 고친다(정본 = 스크립트). ★C7⒜(「그 축을 돌리는 것이 사람이다」)가 닫혔다 · ⒝(OS 축)는 그대로 열려 있다. ★.rs변경 0 ·allow9곳 무접촉 · upstream 무접촉. ★게이트③ 완료: PR #26 — ★★**--merge착지**(★--squash아님 · 등재 repo). 머지커밋 sha 는 회신merged:참조. ★착지 후 반사실 확인:origin/main..upstream/main= 0 유지(스쿼시였으면 계보가 접혀 다시 벌어진다) · ★**origin/main에서 신설 jobdod_paritysuccess** 확인. - [rustjava-sync-contract-standing-clause-for-our-assets-going-stale] ★**「우리 자산이 낡는다」 상시 조항
«판정» — 결론: ★★넣지 «않는다». 대신 «구멍 하나»(로컬 DoD 가 CI 매트릭스를 재현하지 않던 것)를 막았다.**
★코드(
.rs) 변경 0 · 규범 문서 2 + 기록 문서 4. ★먼저 셌다(목록 문서화로 시작하지 않았다): 자산 8건을 돌연변이로 깨뜨려 무엇이 잡는지 쟀다 — 경로 문자열·setProperty서술자·charset 라우팅·ClassFormatError단정은cargo testRED · 수동 span 은 clippy RED ·double_must_useallow 는 깨져도 무해 · 워크로그 스크립트는 로컬+CI 둘 다. ⇒ ★★**[게이트② 정정] 「아무것도 없음」은 «1개»가 아니라 «2개»(② CI--exclude· ⑦double_must_useallow) — 초판이 ⑦을 «비하중» 자리(중복 crate-level attribute 1곳)에서 재 「무해」로 적었고, ★9곳 전건 삭제로 재측정하면 stable 0 · ★beta RED**(rc=101 · 진단 6건)이라 ⑦의 그물도 CI 만이다. ⇒ 「1개면 그 하나를 고쳐라」 규칙은 적용되지 않는다. ★결론은 그대로 「넣지 않는다」이나 논거를 다시 세웠다: ②와 ⑦은 «한 근인의 두 얼굴»이다 — ★로컬 DoD 가 CI «매트릭스»를 재현하지 않는다(② = 빠진- run:줄 = target 축 · ⑦ = 빠진 toolchain 축). ⇒ 근인 하나를 고치니 둘 다 그물을 얻었다(DoD 에cargo +beta clippy추가 ⇒ ⑦이 로컬에서 RED(rc=101 · 진단 6건)로 잡힌다). ★★근인은 「자산 목록이 없다」가 아니었다 — ★로컬 DoD 가 CI 검사 5종 중 «wasm32 clippy» 한 줄을 빠뜨렸고 그 줄이 그 자산이 사는 유일한 자리다. ⇒CLAUDE.mdDoD 가 이제 ★CI 명령 5줄 + toolchain 축 1줄 = «6줄»을 축약 없이 싣는다(★[게이트② 정정] 「5줄」은 계수 «1» 시절 수다 — 빠진 것은 «줄 하나»가 아니라 «두 축»이었다). ★★**[후속 정정] 그 «6줄»도 낡았다 — 파리티 검사기가 더해져 «7줄»이다.** ⇒ ★이제 줄 수를 문장에 적지 않는다:scripts/check-dod-ci-parity.py(CI jobdod_parity)가 DoD 코드블록과rust.yml을 각각 파싱해 대칭차를 낸다. ★그리고 ②는 «조용히» 실패하지도 않는다(excluded package(s) not found+ 빌드 실패) ⇒ 문제는 침묵이 아니라 늦음이다. ★재개 조건은 «축 둘»이다(정정): 축①- run:줄 · ★축② toolchain 매트릭스 — 세는 명령 둘 다 §4 에 박았다. ★오늘의 값 = 축① 0 · 축② 0(착수 시 축① 5 · 축② 1). ★세 돌연변이(beta 제거·nightly 추가·- run:추가)로 ★각 축이 «자기 자리»에서만 반응함을 실측했다. ★C7 고지: DoD 블록 «개악»과 OS 축 3종은 이 대조가 못 잡는다. ⇒ ★★**[게이트② 2차 정정 · fix2] 「고쳤다고 «신고»한 것이 산출물에 남아 있었다」 — 두 건.** ⑴「다섯 → 여섯」 통일이 ★4자리 중 1자리만 됐다 ⑵워크로그.jsonverification이 ★diff 에 한 줄도 없이 철회된 라벨(「beta 도 ok — 깨져도 무해」)을 «검증 기록» 필드에 그대로 싣고 있었다. ★전문 검색으로 반려 밖에서 «더» 찾았다: 「CI 명령 5줄」 파생 수 6자리 · 워크로그 재개 조건 블록이 «축① 만» 실은 것 · 워크로그 검증 표에+beta행이 없던 것. ⇒ ★전건 동기 + 마감 절차 3줄을 §4 에 규율로 박았다. ⇒ ★★**[게이트② 3차 정정 · fix3] ⑴수 라벨 「beta error 7」이 «거짓»이었다 — 착지본 «18자리» 전건 정정.** 실측(9곳 삭제 →cargo fmt --all→ beta clippy): ★rc=101 ·double_must_use진단 «6»건 (전건jvm/src/jvm.rs:140·404·438·779·791·1016) · cargo 요약 줄이 「due to 6 previous errors」라 말한다. ★**「7」은grep -c '^error'(진단 6 + 요약 줄 1)의 값이고 그 필드가 내건 정의가 아니었다 ⇒ ★화해 문장 철회.** ★**「6」은 «하한»이다** —jvm-bytecode가jvm에 의존해 jvm 이 깨지면 그 크레이트는 린트되지 않는다. ⑵잔존 4건(워크로그 「문서 2파일」 2자리 · jsontitle· 「채택 제안 둘」 3자리) + ★PR 제목까지 동기. ⑶★**«5건째»를 스스로 찾았다**(changes[0]) — ★필터 걸린 sweep 이 «거짓 0»을 냈기 때문이고(zsh 단어분할), 그 교훈을 §4 마감 절차 4번으로 박았다. ★게이트③ 완료: PR #25 — ★★**--merge착지**(★--squash아님 · 등재 repocontracts/upstream-sync-repos.conf:22). 머지커밋 sha 는 회신merged:참조. ★게이트② 5회차 만에 approve(초판 → fix → fix2 → fix3) — ★★반려 넷이 전부 «내용»이 아니라 «신고한 것 ↔ 산출물»의 어긋남이었다(계수 · 수 라벨 · 잔존 자리). ⇒ 그 대가로docs/upstream-sync-approach.md§4 에 ★마감 절차 4줄이 남았다(착지본 전문 검색 · 분모 = 파일 × 필드 · 파생 수 · ★필터 걸린 검색의 «거짓 0»). ★남은 minor 하나(F1 · 워크로그.md:54의 「CI 검사 «한 줄»」)는 이 회차가 «고치지 않았다» — 다음에 그 파일을 만지는 회차가 §4(:90)와 «같은 표지»를 달면 닫힌다. - [rustjava-upstream-sync-s8-rename-sweep-decision] ★★upstream 컷
bd42427(개명 스윕 · 12커밋) 머지 — ★★★merge-baseba5797b→bd42427· behind ★12 → 0** · 부모 2개 ⇒ ★★upstream 을 «완전히» 따라잡았다. 착수 재측정(신 서식): 누적 8 · 델타 +8(base3fb08a8· merge-baseba5797b) — 「재서 8 이었다」. ★개명 대응표(upstream 이력 실측 · A/D 0 · 전건 R):java_runtime→**rustjava-runtime(2홉 · 379건 R079) ·test_data→test-data(243 R083) ·jvm_rust→jvm-bytecode·java_class_proto→jvm-class-proto·java_constants→jvm-types·test_utils→test-utils. ★★modify/delete = «0건»** — 두려워한 형태가 안 나왔다. git 이CONFLICT (file location)+AU로 우리 고유 6건을 새 경로로 이미 옮겨 두고 이동 확인만 요구했다 ⇒ 처분 「간다」 전건 · ★**origin/main블롭 대조로 6건 «바이트 동일» 확인** · ★픽스처 5 → 5. ★★개명이 «우리 자산 2건»을 낡게 만들었다(5회째 · 대상은 처음 — CI·경로):rust.yml의--exclude test_utils(옛 크레이트명 ⇒ wasm32 셀 red · 실측 rc=101↔0) →test-utils·tests/test_class_format.rs의"test_data/"4곳 →test-data/. ★둘 다 «우리 파일»이라 충돌이 날 수 없다. ★**Cargo.lock하강 차단**:--theirs+build 가tracing0.1.44 → 0.1.41(=PR #4 언프리즈 되돌림) ·tracing-subscriber·syn도 내렸다 ⇒ S5 처방(main lock 에서 재생성)으로 내려간 것 0. green: stable 4종 + beta 2종 rc=0 · 554/0/1(baseline 554 · 증감 0 이고 맞다 — upstream 도 547→547). ★게이트③ 완료: PR #24 — ★★**--merge착지**(★--squash아님 · 등재 repo). 머지커밋 sha 는 회신merged:참조. ★★★이 착지가 «캠페인 종료»다 — 2026-08-16 착수 시 behind 33 → 오늘 «0». S1~S8 컷 조상 8/8. ★다음 동기는 «계획된 컷»이 아니라 «upstream 이 움직일 때»다 — 정기 축 여부는 별건 판정(워크로그proposals[1]). - [rustjava-upstream-sync-s7-and-fix-the-conflict-count-format] ★upstream 컷
ba5797b(가상 디스패치 해석 · 1커밋 · 319파일) 머지 — 충돌 1 해소 + ★**§5 「충돌 수」 정본 서식에 «델타/누적» 축을 넣었다.** ★**merge-base95ebc5c→ba5797b· behind 13 → 12 · 부모 2개** ⇒ ★★계획 7회차(S1~S7) 완주. 착수 재측정(신 서식): 컷ba5797b= 누적 1 · 델타 +1(base3e02f8c· merge-base95ebc5c). ★string.rs는 집합에서 빠졌다(S6 해소 뒤 upstream 무접촉) ⇒ ★누적은 줄어들 수도 있다. ★★**thread.rs는 «직교»였다** — upstream(+23/−10)은invoke_virtual에 «선언 클래스» 인자를 더하고 우리(+50/−42, 의미 3줄 + 들여쓰기)는 그 호출들을 감싸는 수동 span(PR #4)이다 ⇒ 우열 판정 대상이 아니다. 우리 구조를 뼈대로 upstream 새 인자 3곳을 얹었다(S1·S3·S4 와 같은 전략 · 4회째). ★★**「충돌 0으로 들어온」 파손 4회째 · ★축은 «처음»: upstream 이 «공용 API 시그니처»를 바꿔 ★우리 고유 테스트 5곳이 구식 4인자로 남아 컴파일 실패(E0061×5). 우리 줄이라 충돌이 «날 수가 없다» ⇒ ★앞 세 번(신규 파일)과 «반대 방향»이고, 잡은 것은 «컴파일»이다.** upstream 관용구를 그대로 채택(&x.class_definition().name()·"java/lang/String") · 단언 무접촉. green: stable 4종 + beta 2종 rc=0 · 554 / 0 / 1(baseline 554 → ★증감 0 이고 그것이 맞다 — upstream 테스트 함수도 547 → 547 = 스윕이지 추가가 아니다) ·#[ignore]1 → 1 · 단언 삭제 0. ★게이트③ 완료: PR #23 — ★★**--merge착지**(★--squash아님 · 등재 repo). 머지커밋 sha 는 회신merged:참조. ★★S1~S7 컷 조상 7/7 ⇒ S4 의 「전건 NO(스쿼시 3회가 족보를 원점으로)」 반대편을 코드 회차 3연속으로 지켰다. ★남은behind 12는 «개명 스윕» 구간이고 S8 몫(총괄 보류분 — 이 회차는 집행하지 않았다). - [rustjava-upstream-sync-s6-cut-95ebc5c] ★upstream 컷
95ebc5c(regex·Formatter·Locale · 11커밋) 머지 — 충돌 1 해소. ★**merge-basec4665b0→95ebc5c· behind 24 → 13 · 머지커밋 부모 2개**(계보 보존).cargo test --all554 passed / 0 failed / 1 ignored(S5 427 → +127) · stable 4종 + ★beta 2종 rc=0. ★★**「S6 새 충돌 0」 예측은 «델타»였다 — 「풀 것이 없다」가 아니다.** 그 0 은 옛 base8c1238b에서 잰 «새로 나타난 파일 수»(누적 3 → 3)이고, 착수 재측정은 새 basea0b5d3c(merge-basec4665b0)에서 ★누적 1이다.string.rs는 S5 의 설계 판단으로 우리 분기(+8/−28)가 남아 upstream 이 만질 때마다(+402/−121) 계속 열린다. ⇒ ★**§5 에 한 줄 보탰다: base 와 «함께» «델타인가 누적인가»도 밝혀라.** 해소 = import 블록 합집합(우리charset::Charset+ upstreamFormatter·Locale·regex) ·Charset라우팅 4곳 생존 ·decode_str/encode_str재유입 0. ★★계약4⒝ 정독이 «충돌 0으로 들어온» 파손 1건을 «테스트 전에» 잡았다 — 이 형태 «세 번째»: upstream 신규 파일java/util/regex/test_pattern_syntax_exception.rs가System.setProperty를)Ljava/lang/Object;로 3곳 부른다 ⇒ 서술자만String으로(S5 의 확립된 처분과 동일). ★전례 S3 3건 → S5 5곳 → S6 3곳 — 매 회차 «새 파일»로 재유입된다. ★게이트③ 완료: PR #22 — ★★**--merge착지**(★--squash아님 · 등재 repo). 머지커밋 sha 는 회신merged:참조. ★착지로 base 가 또 바뀌었다 ⇒ §5 의 「S7 새 충돌 1(thread.rs)」은 «다시 재야 한다»(base·델타/누적 병기). ★남은 구멍(검수자 지적): §5 «상시 규칙» 절의 정본 서식(:268)은 아직<수>(base · merge-base)뿐이고, «델타/누적» 축은 S6 착지 기록(:444) 안에만 있다 — ★다음 §5 갱신 회차가 정본 서식에 한 줄 올려야 한다. - [rustjava-upstream-sync-s5-with-remeasured-conflicts] ★upstream 컷
c4665b0(#190 Java 1.2 API 확장) 머지 — 충돌 3 해소. ★**merge-base3296139c→c4665b0· behind 30 → 24 · 머지커밋 부모 2개**(계보 보존).cargo test --all427 passed / 0 failed / 1 ignored(S4 261 → +166) · green 4종 rc=0. ★착수 시 재측정(§5 상시 규칙 · base 당시 main1983d9f· merge-base3296139c)이 재측정 표와 일치. ★★예측 3건 중 2건 적중 · 1건 반증: ⑴Cargo.lock재생성 ⑵string.rs설계 판단이 맞았으나 «형태»가 달랐다 — upstream 이copyValueOf2종을 신설하며decode_str/encode_str표를 «되살렸는데» 4개 호출부는 자동병합으로 우리Charset라우팅을 유지했다 ⇒ 신규 API 는 취하고 표는 버렸다(안 그러면 dead code — S3 완료조건 위반). ⑶test_timer.rs★**「되얹기」 예측이 반증됐다** — upstream 이 벽시계 테스트 2건을 manual clock + monitor notification 기반 결정성 스위트 12건으로 대체했다 ⇒upstream 채택. ★★S4 가 남긴 「우리 테스트의 시간 의존」 별 축은 소멸했다 — 발권하지 마라(2000ms 근거는 §5 착지 기록에 보존). ★★충돌 «목록에 없던» 파손 1건 — §4 가 경고한 형태가 실제로 났다: upstream 신규 io 테스트 3파일 5곳이System.setProperty를)Ljava/lang/Object;로 부르는데 우리는 PR #5 에서 JDK 규격대로)Ljava/lang/String;이라 ★충돌 마커 0줄인데NoSuchMethodError3건. 서술자만 맞췄다(★test_boolean·test_integer·test_long이 앞 회차에 이미 같은 처분을 받았다 ·Properties.setProperty의 Object 반환은 JDK 규격상 옳아 무접촉). ★게이트③ 완료: PR #21 — ★★**--merge착지**(★--squash아님 · 등재 repo). 머지커밋 sha 는 회신merged:참조. ★착지로 base 가 바뀌었다 ⇒ §5 의 「S6 새 충돌 0 · S7 새 충돌 1」은 «다시 재야 한다» (§5 상시 규칙: 충돌 수를 적을 때는 base 를 반드시 병기하라). - [rustjava-upstream-sync-remeasure-s5-s7-and-lock-restore-basis] ★**PR #18 착지 «뒤» 기준으로 S5~S7 재측정
- 「충돌 수에 base 병기」를 §5 상시 규칙으로 채택.** ★코드 변경 0 · 문서 전용.
세 base 병기: 같은 컷
ba5797b가 19(계획03438b0) · 112(복원 전3a59776) · 4(복원 후8c1238b) — ★28배 차이. base 없는 충돌 수는 검증 불가다. ★새 충돌(복원 후): S5 +3 · S6 +0 · S7 +1. ★S5 는 「충돌 0 물량」이 아니다 — 그 3건은Cargo.lock(재생성) ·string.rs(★설계 판단) ·test_timer.rs(S4 가 넣은 2000ms 여백)이고 ★★전부 upstream 이 아니라 «우리가 앞 회차에 남긴 로컬 분기»가 만든다. ★**「예측은 하한」이 S7 에서 처음 깨졌다**(예측 +3 ↔ ⓐ+2 · ⓒ+1) —Cargo.lock이중 계상 ·class_format_error.rs경로 오기 · ★그 파일과throwable.rs둘 다 «우리 쪽»이3296139와 바이트 동일이라 upstream 변경(+4/−3 · +81/−29)이 깨끗이 적용된다(S3 가 수렴시켰다). ★★**[2026-09-04 정정] 초판이class_format_error.rs를 「upstream 변경 0」으로 적은 것은 «거짓»이고 «0 인 쪽이 반대»였다** —diff 3296139 ba5797b= +4/−3 ·diff 3296139 origin/main= 0줄(블롭0dbd369a). ⇒ ★**「upstream 이 안 건드린다」가 아니라 «우리가 손대는 순간 충돌한다»** 이다. ★부수 발견 — S8 이 필요하고 남은 것 중 제일 크다:ba5797b..upstream/main12커밋 · ⓒ 누적 11(+7) ·java_runtime/→rustjava-runtime/·test_data/→test-data/개명 스윕이라 우리 픽스처에 꽂힌다. ★게이트③ 완료: PR #19 — ★★**--merge착지**(★--squash아님 · 등재 repo). ★착지 «전»REPORT.md·STATE.md위치 충돌 2건을 합집합으로 해소했다(PR #20 이 먼저 착지 · 코드 충돌 0). 머지커밋 sha 는 회신merged:참조.
- 「충돌 수에 base 병기」를 §5 상시 규칙으로 채택.** ★코드 변경 0 · 문서 전용.
세 base 병기: 같은 컷
- [rustjava-worklog-mandate-decision-and-local-gate] ★워크로그 작성을 DoD «의무»로 결정 + 형식 잠금을
로컬 DoD 4번째 명령으로 편입. ★코드 변경 0 · 새 도구 0 · CI 워크플로 무접촉.
★먼저 쟀다: 규약 착지(
b3a4cf4· 2026-08-26) 이후 착지 4회차 중 3건(75%) 작성 · 유일한 미작성(PR #13)은 부모가 정확히b3a4cf4라 규약을 알 수 없었다(알 수 있었던 회차만 3/3). ★★관측이 높은데도 의무화한 이유 = 실패가 «조용하고 잠글 수 없다» — 잠금은 존재하는.json만 검사하므로(비소급 설계) 아예 안 쓴 회차는 red 0 · 카드만 0 이다. 표본 3건 · 전건 같은 리니지. ★되돌릴 수(AGENTS.md§Round Worklog · 측정 명령 동봉): 10회차 착지 시점 재측정 — ⒜미작성 ≥ 2 ⇒ 문안을 빼거나 기계 강제로 ⒝열린 카드 < 5 ⇒ 의무 재검토. ★**cargo test안으로 안 넣었다**:serde_json이Cargo.lock에 부재(새 의존성 + 6셀 빌드) ·python3shell-out 은 python 없는 머신에서 오탐 red ⇒ 「오탐 0」 절대 조건 위반. 대가 = +0.10s(3명령 warm 합계 60.2s 대비 +0.17% · 완전 캐시 회차 9.36s 대비 +1.1%). ★게이트③ 완료: PR #20 — ★★**--merge착지**(★--squash아님.rustjava는upstream-sync-repos.conf등재 repo 라 스쿼시가 계보를 지운다 — #11·#13·#16·#17 이 그 형태였다). 머지커밋 sha 는 회신merged:참조. - [rustjava-upstream-sync-s3] upstream 컷
822504b(#180 오류 분류) 머지 — 충돌 11 해소. ★S2(PR #13) 브랜치 «위에» 쌓았다 — 당시main에 S2 가 없어 base 를main으로 잡으면 S2 의 충돌 5건을 다시 만나기 때문이다. ★게이트③ 완료: PR #16 스쿼시 머지 → main4bb796d(2026-08-26). ★★착수 시 「upstream 조상 무손상이라-s ours불필요」로 적었는데, «축을 하나 놓쳤다» — #13 이 스쿼시로 착지하자 upstream 조상(822504b)은 그대로인데origin/main과의 조상이 끊겼다 (merge-base=b3a4cf4·11ef501이 조상 아님) ⇒ main 과 6충돌(원장 1 + 코드 5, 내용은 전부 동일). ⇒ 게이트③이git merge -s ours --no-ff 11ef501(트리 무변경 실측)로 복원해 충돌 0으로 만들었다. ★교훈: 조상은 «upstream 축»과 «origin/main 축» 둘이다. 스쿼시가 끊는 것은 후자다. - [rustjava-upstream-sync-s2] upstream 컷
af4f6f8(#177 CLDC 1.1) 머지 — 충돌 5 해소. ★PR #11 이 스쿼시 머지돼 upstream 조상이 끊겨 있었다 —-s ours로1f356ae를 부모로 기록해 복원한 뒤 머지했다(트리 무변경). 복원 전 충돌 15 → 복원 후 5. ★게이트③ 완료: PR #13 스쿼시 머지 → main11ef501(2026-08-26). ★착지 전 base 를main으로 당겨 #14(beta clippy)를 들여와 CI red 를 풀었다(핀eaa5668rc=1 CI_RED →df3b04arc=0 CI_GREEN). - [rustjava-worklog-json-proposals-convention] 회차 워크로그
docs/worklog/.md+.json한 쌍 규약 이식. ★게이트③ 완료: PR #15 스쿼시 머지 → mainb3a4cf4. - [rustjava-ci-beta-clippy-double-must-use-red] beta clippy
double_must_use13건 red 해소. ★게이트③ 완료: PR #14 스쿼시 머지 → maindde85ce. - [rustjava-claude-md-prune]
CLAUDE.md프룬(autonomous-sop 삭제 + Goal/Constraints/DoD 신설). ★게이트③ 완료: PR #8 스쿼시 머지 → main00bddf3(2026-08-18). ※구판 「좌초 중」 기재는 폐기. - [rustjava-upstream-sync-s1-tracing-cut-1f356ae] upstream 컷
1f356ae머지(충돌 2 해소 · tracing 축 ·System.setProperty서술자 파손 1건 추가 처리). ★게이트③ 완료: PR #11 스쿼시 머지 → main6bfe97c(2026-08-17). ※원격 브랜치는 repo 설정deleteBranchOnMerge=true로 자동 삭제됨. - [rustjava-runtime-time-todo-impl] RuntimeImpl 시간 API
todo!()3건 제거(now/sleep/yield) + test_utilsr#yield구현 + tokiotime피처 추가 + 회귀 잠금 픽스처(test_data/TimeApi). ★게이트③ 완료: PR #2 스쿼시 머지 → main13ab950(2026-07-23), 브랜치 정리 완료. - [rustjava-classfile-parse-error-propagation] 클래스파일 파싱 실패를 패닉 대신
java.lang.ClassFormatError로 전파(절단/매직 불일치/미지원 상수풀 태그 구분). ★게이트③ 완료: PR #3 스쿼시 머지 → main549b9eb(2026-07-23), 브랜치 정리 완료. - [rustjava-tracing-attributes-pin-removal]
#[tracing::instrument]1건을 수동 span 으로 대체,tracing-attributes상한 핀 제거(tracing 0.1.41→0.1.44 언프리즈), wasm32 clippy CI 커버리지 교정. ★게이트③ 완료: PR #4 approve 핀0a19f38확인 → main 충돌 해소(docs-only) 후 스쿼시 머지(2026-07-23), 브랜치 정리 완료. - [rustjava-unsupported-charset-exception] 미지원 charset
unimplemented!()패닉 3지점을java.io.UnsupportedEncodingException(신설) throw 로 전환, String↔InputStreamReader 지원 charset 을 공용charset::Charset으로 일치(ISO-8859-1/US-ASCII 가 Reader 에서도 동작). 부수:System.setProperty반환 시그니처 JDK 규격화(Object→String, jvm 부트스트랩 포함),Throwable.getMessage()신설, 픽스처test_data/UnsupportedCharset. ★게이트③ 완료: PR #5 approve 핀dd9fcdf확인(이후 이동분은 문서화된 main 동기화 머지 3건뿐, diff-of-diffs 로 코드 동일성 검증) → 스쿼시 머지(2026-07-23), 브랜치 정리 완료. - [2026-07-25-rustjava-branch-hygiene] 원격 잔존 브랜치 2건 판정. ①
dependabot/cargo/tracing-attributes-0.1.31→ PR #4 로tracing-attributes의존 자체가 소멸(Cargo.toml/lock 전무)해 패치 대상 라인 부재 → origin 에서 삭제 완료. ②wie-ktf-hardening→ 12커밋 중 8건이 upstream/main 에 스쿼시 반영/대체(#174~#182), 4건 유효 잔존 → 혼재 판정으로 보존, 커밋별 판정표를 총괄에 제출(코드 변경 0).
★★**[2026-09-03 갱신] 구판 「S4 착지 대기」는 낡았다** — PR #17(S4)·#18(계보 기록)이 전건 머지됐고
★**#18 은 --merge 로 착지해** merge-base origin/main upstream/main = 3296139c · behind 30 ·
열린 PR 0. ⇒ ★**「앞 회차가 착지하면 뒤 회차의 기준선이 바뀐다」가 이제 처음으로 참이다.**
★다음은 S5(c4665b0 · Java 1.2 API 확장). 단 「충돌 0 물량」이 «아니다» — 2026-09-03 재측정(base = 현 main8c1238b · merge-base 3296139c)으로 새 충돌 3건: Cargo.lock(재생성) ·
java_runtime/src/classes/java/lang/string.rs(★설계 판단 · upstream 3296139→c4665b0+285/−31 ↔
우리 3296139→origin/main+8/−28) ·
java_runtime/tests/classes/java/util/test_timer.rs(S4 가 넣은 500→2000ms 여백을 다시 얹는 기계 작업).
S6 새 충돌 0 · S7 새 충돌 1(thread.rs). ★상세·근거·세 base 대조표 = docs/upstream-sync-approach.md §5 「[2026-09-03 재측정]」.
★★충돌 수를 적을 때는 base 를 반드시 병기하라 — §5 상시 규칙이다.
S4 실측(2026-08-27): 착수 시 merge-base origin/main upstream/main = ★**62cf0c6(최초 공통조상) ·
1f356ae·af4f6f8·822504b 가 origin/main 의 조상 전건 NO — ★스쿼시 3회가 족보를 원점으로 되돌렸다.**
⇒ 첫 조치 git merge -s ours --no-ff 822504b → merge-base822504b 복원.
★무해성의 근거는 «git diff --stat origin/main HEAD 빈 출력»이 «아니다» — -s ours 는 정의상 우리 트리를
유지하므로 그 출력은 항상 참이고 아무것도 증명하지 않는다. 근거는 ★**--diff-filter=D 0 + 양방향 전문 대조다.
★충돌 20 → 2**(java/lang/thread.rs · jvm/src/jvm.rs).
green 전건 rc=0 · cargo test --all261 passed / 0 failed / 1 ignored(S3 216 → +45).
★★타이머 테스트 여백 1건 — ★«회귀»가 아니다. 전 판본의 「upstream 회귀를 들여왔다」 서술은 «틀렸다».test_timer_periodic 은 ★컷 이전부터 500ms 창에서 기대 10회 대비 3~4회만 도는 만성 경계 테스트다.
★★측정 조건을 «섞지 마라» — 전 판본이 틀린 이유가 그것이다(단독 결과와 병렬 결과를 나란히 놓았다).
조건을 맞춘 교대 실행 실측:
| 조건 | 4bb796d(컷 전) | 3296139(컷 후) |
|---|---|---|
| 단독 실행 · 교대 10회 | 3 3 3 3 4 4 4 4 3 4 · mean 3.5 | 4 3 4 3 4 3 4 3 4 3 · mean 3.5 |
| 전 스위트 병렬 · 교대 8회 | 4 4 4 4 3 4 3 4 | 4 3 3 6 4 4 4 4 |
⇒ ★두 조건 어디서도 차이가 없다. 「1회전 110150ms」는 컷이 만든 값이 아니라 양쪽 공통의 기존 값이다.
★사료가 그 자체로 반증이다: upstream 이 같은 자리를 넓힌 895d67d(2025-08-20)·ad8b477(2025-10-04)는
★둘 다 이미 origin/main 의 조상이고, 근인으로 지목했던 e557673(GlobalRef)은 2026-07-18 이다
⇒ ★지목된 커밋보다 «11개월 앞서» 이미 만성 flaky 였다.
처분은 그대로다(sleep 500 → 2000ms · run_count > 2불변 · #[ignore] 0 · 삭제 0) — 성격만 정정한다:
★**「가리는 여백」이 아니라 «만성 경계 테스트에 정상 여백을 준 것»이다.**
★대가: 감도가 내려간다 — red 문턱 1회전 ~167ms → ~667ms(약 4배 둔화). 「5.6배 저하」는 여전히 red,
「2.4배 저하」는 이제 통과한다. 그 상한을 테스트 주석에 박았다.
★~~**「예측은 하한」이 이제 3회 연속 실측됐다**~~ → ★★**[2026-09-03 정정] 하한은 «절대적이지 않다» — S7 에서 처음 깨졌다**
(예측 +3 ↔ 실측 계획기준 +2 · 복원 후 +1). 초과는 «우리 로컬 분기»가 만들고(S5 0↔+3),
미달은 «앞 회차가 수렴시켜서» 난다(S3 가 upstream 오류 분류를 채택해 throwable.rs 충돌이 사라졌다).
⇒ ★티켓 size/timeout 은 여전히 하한 쪽으로 잡되, 「하한이다」를 근거로 쓰지 마라.
★**thread.rs 는 S1·S3·S4 «세 회차 연속» 충돌한다 — upstream 이 ThreadStartProxy::call 을 반복 재작성하기 때문이다.
★★[2026-09-03 정정] 「S5~S7 도 기본값으로 잡아라」는 «절반» 맞았다** — 실측상 S5·S6 은 충돌하지 않고 S7 에서만 다시 열린다.
해소 전략은 불변이다:
upstream 본문을 뼈대로 취하고 #[tracing::instrument] 한 줄만 PR #4 의 수동 span 으로 치환한다.
★선행 확인 종결: upstream agent/runtime-api-gaps(6309d47)는 미머지가 아니다 —
PR #190 로 2026-07-25 04:59Z 스쿼시 머지(머지커밋 c4665b0, +33,109/−1,040)됐고
그래서 브랜치가 upstream 에서 삭제됐다. 즉 「삼키는지」는 이제 upstream/main 에 직접 묻는다.
항목별 판정(전부 upstream/main 트리 실측):
| 항목 | upstream/main 현재 | 판정 |
|---|---|---|
Timer.schedule(TimerTask;J)V 1회성 | timer.rsschedule_once 존재 | 삼킴 → 무효 |
StringBuffer.insert(ILjava/lang/String;) | insert_string 존재 | 삼킴 → 무효 |
StringBuffer.append([CII) null→NPE | null 가드 + 범위 가드까지 존재 | 삼킴 → 무효 |
ByteArrayInputStream.<init>([B) null 가드 | is_null() 가드 존재(be77dc6) | 삼킴 → 무효 |
Class.forName null/not-found 가드 | 둘 다 존재 | 삼킴 → 무효 |
Integer.byteValue()/shortValue() | java/lang/Number 가 구현 제공, Integer 가 상속(#176) | 삼킴 → 무효 |
System.arraycopy null 가드 | 부재 | ★유효 잔존 |
String.<init>([B) / ([C) null 가드 | 부재 | ★유효 잔존 |
★유효 잔존 2건의 파괴력 근거(추정 아님): ClassInstanceRef::deref 가
self.instance.as_ref().unwrap() 이라 null 참조를 넘기면 Rust 패닉 = 호스트 프로세스 abort다
(jvm/src/class_instance.rs). System::arraycopy 는 jvm.load_array(&src, …),
String::init_with_byte_array/init_with_char_array 는 jvm.array_length(&value) 로 곧장 deref 한다.
★★형제 호출부 «전수»(2026-08-16 재실측 · java/lang/String 의 <init> 오버로드 10건 전건 대조).
가드가 없어서 null 을 넘기면 호스트 abort 인 것이 7건이다:
<init> 서술자 | 구현 | null 이 닿는 자리 | 가드 |
|---|---|---|---|
([B)V | init_with_byte_array | jvm.array_length(&value) | 없음 |
([C)V | init_with_char_array | jvm.array_length(&value) | 없음 |
([BII)V | init_with_partial_byte_array | jvm.load_array(&value, …) | 없음 |
([BLjava/lang/String;)V | init_with_byte_array_charset | jvm.array_length(&value) | 없음 |
([BIILjava/lang/String;)V | init_with_partial_byte_array_charset | jvm.load_array(&value, …) | charset_name 만 검사 · value없음 |
(Ljava/lang/String;)V | init_with_string | value_range → jvm.get_field(this, …) | 없음 |
(Ljava/lang/StringBuffer;)V | init_with_string_buffer | jvm.invoke_virtual(&value, "toString", …) | 없음 |
([CII)V | init_with_partial_char_array | — | ★있음 |
(II[C)V | init_with_shared_char_array | — | ★있음 |
()V | init_empty | 인자 없음 | 해당 없음 |
★**get_field/invoke_virtual 도 &Box<dyn ClassInstance> 를 받는다** — 배열 인자만의 문제가 아니다.
⇒ ★가드가 «짝이 안 맞는» 것이 핵심이다: ([CII)·(II[C) 만 막혀 있고 [B 계열은 전부 뚫려 있다.
※전역 수리는 불가 — Deref 는 Result 를 못 돌려준다. upstream 방식(진입부 is_null() 가드)이 정답이다.
★★0번 항목(rustjava-pr8-claude-md-prune-disposition)은 «해소됨» — 2026-08-27 S3 회차가 닫았다.
구판은 「reports/rustjava-claude-md-prune.review.md 가 없다 ⇒ 게이트②가 아예 돌지 않고 좌초」를
근거로 이 항목을 최우선에 뒀는데, 그 근거가 둘 다 사실이 아니게 됐다(실측):
Jun025/RustJava#8= ★**MERGED**(mergedAt2026-08-18T19:26:08Z · 머지커밋00bddf3). headfeat/rustjava-claude-md-prune는 머지와 함께 삭제됐다(git ls-remote --heads origin잔존 0).reports/rustjava-claude-md-prune.review.md실재(2026-08-19 03:42) · 승계-fix리니지의.done.md/.review.md도 둘 다 실재 ⇒ ★게이트②는 돌았고 3게이트를 완주했다.- 「현
main의CLAUDE.md에 그 변경이 없다」도 해소 —origin/main의CLAUDE.md에## Goal절이 실재한다(= 프룬 판본이 정본). ★교훈: 이 절이 «이미 끝난 일»을 최우선으로 가리키면 레인이 조용해진다 — 실제로 발권이 멈춘 채 18시간(LANE_IDLE rustjava)이 지났다. 「다음」 절 항목은 닫히는 즉시 닫아라.
⇒ 재부여된 순서(위 0번이 빠지고 1→3 이 한 칸씩 올라온다):
- ★**
rustjava-upstream-sync-s5…-s7(S1~S4 완료 · 구판-32-commits폐기) — ①의 머지를docs/upstream-sync-approach.md§5 의 7회차로 쪼갠다. 한 티켓 = 한 컷이고, ★순서대로다 — 다음은 S5(c4665b0). ★착수 첫 조치는git merge -s ours --no-ff 3296139** (S4 착지가 또 스쿼시라 족보가 다시 끊긴다 — S2·S3·S4 가 전부 같은 형태였다). 각 회차 완료 정의 = 그 컷의 충돌 해소 + CIrust.yml4종 green- 문서 §5 의 회차별 추가 조건(S1 tracing 0건 / S2 charset 잠금 / S3
test_class_format.rs/ S4~S7 해소분 0 증명). ★착수 시 충돌을 재측정하라 — 앞 회차 착지로 기준선이 바뀐다.
- 문서 §5 의 회차별 추가 조건(S1 tracing 0건 / S2 charset 잠금 / S3
rustjava-null-guard-string-init-and-arraycopy(P2·S·low) — ②의 유효 잔존 2건 + 형제 전수. ★①의 뒤여야 한다 — ★근거 정정(2026-08-16): 선행 이유는string.rs가 충돌 목록에 있기 때문이다. ★**system.rs는 충돌 목록에 «없다»**(merge-tree출력에서Auto-merging만 있고CONFLICT줄이 없다) — 구판이 두 파일 다 충돌이라고 적은 것은 오류이니 충돌 해소 대상으로 잡지 마라.- 범위:
System.arraycopy+ ②의 표에서 가드 없음 7건 전부 (([B)·([C)·([BII)·([BLjava/lang/String;)·([BIILjava/lang/String;)·(Ljava/lang/String;)·(Ljava/lang/StringBuffer;)). - 재현:
System.arraycopy(null,0,dst,0,0)·new String((byte[])null)·new String((char[])null)·new String((byte[])null,0,0)·new String((byte[])null,"UTF-8")·new String((byte[])null,0,0,"UTF-8")·new String((String)null)·new String((StringBuffer)null)→ 전부 현재 패닉, 기대NullPointerException. - 완료 정의: 8케이스 픽스처 잠금 + 3종 green. ★가드 스타일은 upstream 기존 방식(진입부
is_null())에 맞춘다.
- 범위:
rustjava-invokedynamic-cp-tags-15-18-support(P2·M·med) — 아래 ④ 참조. ★**「한 티켓으로 묶는 이유」가 2026-08-16 로 바뀌었다.** 구판 논거(「파서만 고치면 인터프리터가todo!()로 죽는다」)는 ★①머지 뒤 성립하지 않는다 — upstream 이jvm_rust/src/verifier.rs로 패닉 축을 이미 제거했기 때문이다(④ 참조). 그리고 ③은 ① 뒤에 도는 티켓이다. ⇒ ★새 논거: ①머지 뒤 남는 것은 「깔끔한 거부」에서 「실제 지원」으로 올리는 일이고, 그것은 파서(태그 15~18 수용) 없이는 시작조차 못 하고, 부트스트랩 실행(verifier·인터프리터) 없이는 끝나지 않는다 — ★두 끝이 «같은 기능 하나»의 앞뒤라서 한 티켓이다(구판처럼 「어느 쪽만 고치면 반대쪽에서 죽는다」가 아니다).- ★착수 전 필수: ①머지 뒤
jvm_rust/src/{verifier,error}.rs와classfile/src/constant_pool.rs의 실제 착지 상태를 다시 재라.jvm_rust/src/class_definition.rs는 충돌 17파일에 이미 들어 있다 — 즉 ①이 반드시 손대는 자리다. - ★범위 축소 권고 불변: 크면 「파서 태그 수용 + 명확한 미지원 예외」까지로 자른다.
- ★착수 전 필수: ①머지 뒤
- ★
jvm_rust/src/interpreter.rsOpcode::Invokedynamic(_) => todo!()는 origin/main·upstream/main 양쪽에 그대로 살아 있다 — ★문자열로는 참이지만 «도달 가능성»이 다르다 (2026-08-16 정정. 구판은 여기서 멈춰 «양쪽 동일»로 읽었는데 틀렸다). ★★upstream 에는jvm_rust/src/verifier.rs가 새로 있고(origin 에는 없다), 거기서Opcode::Invokedynamic(_)를 만나면ClassDefinitionError::UnsupportedFeature("invokedynamic")로 거부한다. 이verify는jvm_rust/src/class_definition.rs가 클래스 정의 시점에 부르므로, upstream 에서는 ★인터프리터의todo!()에 닿기 전에 깔끔한 오류로 끊긴다. 방증: 같은 테스트가 origin 은test_invokedynamic_consumes_reserved_bytes, upstream 은 ★test_invokedynamic_is_rejected로 이름부터 바뀌어 있다(classfile/src/opcode.rs). ⇒ ★★①머지가 끝나면 «패닉 축»은 소멸한다. 남는 것은 «거부» → «실제 지원» 이다. ※rustjava-classfile-parse-error-propagation이 이 축을 처리했다는 통설은 여전히 거짓이다 — 그 티켓은 클래스파일 파싱 경로만 고쳤고 인터프리터·verifier 와 무관하다. - ★javac 21 익명 내부 클래스 "Malformed class file": 미해결. 원인 후보가 좁혀졌다 —
classfile/src/constant_pool.rs의 태그 분기가 origin·upstream 모두 1~12 까지뿐이고 15(MethodHandle)·16(MethodType)·17(Dynamic)·18(InvokeDynamic) 분기가 없다. javac 9+ 는 문자열+연결조차 invokedynamic 으로 낸다. ⇒ STATE 구판의 「태그 1518 아님」은 근거 없이 배제한 것으로 보인다. ★이 절반은 ①머지 뒤에도 그대로 남는다 — verifier 는 파싱이 끝난 뒤에 도는데, 태그 1518 은 파싱 단계에서 먼저 막힌다. 위 invokedynamic 축과 한 티켓(브리프 ③)으로 묶는 근거가 이것이다. - ★InputStreamReader 디코더: origin/main 에서 미해결(read 마다
Charset::resolve(...).new_stream_decoder()로 새로 만든다).rustjava-unsupported-charset-exception이 고친 것은 미지원 charset 패닉이지 경계 유실이 아니다 — 별개 결함이다. ※단 upstream 은 완화책을 갖고 있다(endOfInput필드 + UTF-8 lead-byte 역주사 · EUC-KR>=0x81홀드백). ⇒ ①의 머지로 함께 들어온다. 별건 발권 전에 ① 이후 상태를 다시 재라.
★열린 PR = 1건(gh pr list -R Jun025/RustJava --state open):
| PR | 브랜치 | 상태 | 원장 |
|---|---|---|---|
#16[rustjava-upstream-sync-s3] | feat/rustjava-upstream-sync-s3 | OPEN · ★게이트② approve(핀 3cf944d) · 게이트③ 집행 중 | .done.md·.review.md 둘 다 有 |
[rustjava-upstream-sync-s2] | — | ★MERGED(2026-08-26T21:51:38Z → main 11ef501) | 3게이트 완주 |
| — | MERGED(→ 00bddf3 · dde85ce · b3a4cf4) | 완주 |
★★스택 PR 을 다룰 때 반드시 기억할 것(2026-08-27 실사고급 근접): #16 의 base 가
feat/rustjava-upstream-sync-s2 였고 이 저장소는 deleteBranchOnMerge=true 다 ⇒ ★**#13 을 그냥 머지했으면
#16 이 base 소멸로 자동 CLOSED 될 자리였다(reopen 불가). S2 게이트③이 머지 «전»에
gh pr edit 16 --base main 으로 선제 재타깃해 막았다. ⇒ ★스택 PR 은 부모 머지 «전»에 자식 base 를 옮겨라.**
★원격 브랜치(git ls-remote --heads origin · 2026-08-27 실측) = 3건:
main · feat/rustjava-upstream-sync-s3(PR #16 의 head) · wie-ktf-hardening.
| 브랜치 | 성격 | 처분 |
|---|---|---|
feat/rustjava-upstream-sync-s3 | PR #16 의 head — 게이트③ 집행 중 | 머지와 함께 자동 삭제(deleteBranchOnMerge) |
wie-ktf-hardening | 보존 판정(2026-07-25) | 위 ②로 잔존 가치가 2건까지 줄었다 — 브리프 ③-2 가 그 2건을 새 브랜치로 옮겨 심으면 ★보존 근거가 소멸한다 |
⇒ ★다음은 S4( → ★★**[2026-09-03 갱신] 다음은 S5(3296139) — 남은 upstream 커밋 26c4665b0)** —
남은 upstream 커밋 30(ba5797b 뒤로 12 가 더 붙었다 · 헤드 bd42427). 열린 PR 0 · 원격 브랜치 = main · wie-ktf-hardening.
★**「7회차」로는 헤드에 닿지 않는다 — S8 발권이 필요하고, 그것이 남은 회차 중 제일 크다**
(ⓒ 누적 충돌 11 · java_runtime/→rustjava-runtime/ · test_data/→test-data/개명 스윕이 우리 픽스처에 꽂힌다).
- ★PR 발권 시
--repo Jun025/RustJava명시(2026-07-22 upstream 오발행 사고 재발 방지). - ★upstream 발신(PR·이슈·코멘트·push)은 티켓이 명시 허가할 때만. 기본은 조회뿐.