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
22 changes: 22 additions & 0 deletions REPORT.md
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
# REPORT

## [2026-09-04] upstream 동기 «정기 축» 판정 — 격차 기반 `behind ≥ 20` (rustjava-upstream-sync-cadence-decision)
- 무엇을: 채택 제안 `2026-09-04-sync-contract-stale-assets-decision#p0` 에 대한 **판정**이다.
★**결론: 동기 회차는 `origin/main..upstream/main` 이 «20 이상»일 때 연다** — 시간(격주·월간) 기반은 기각.
★**신설 0**(검사기·크론·워크플로) · `.rs` **0줄** · ★**S9 미개시**(behind **0**). 바뀐 것은 `docs/upstream-sync-approach.md` **§5-B** 뿐이다.
- 왜: ★★**전제를 «먼저» 재서 «반증»했다.** 회차 커밋 수 ↔ 충돌의 상관계수 ★**부호가 «음»**이다.
★★**[게이트② 정정] 초판 표는 base·(델타/누적) 병기가 없어 기준이 섞여 있었다** ⇒ 정본을 **«누적»**으로 통일해 다시 계산했다:
A 초판(혼재) **r=−0.169 · 합 28** · B S4 만 정정 **r=−0.134 · 합 30** · ★**C 정본 «전부 누적» r=−0.155 · 합 33**.
★**세 열 모두 부호가 음**이고 「많은4 < 적은4」가 유지된다(정본 C: **37커밋 → 14** ↔ **8커밋 → 19**) ⇒ ★**판정 불변**.
★**단 r 은 n=8 비무작위 표본이라 «비례하지 않는다»는 «부호 판정»으로만 쓴다.**
★**누적 충돌도 포화한다**(고정 base: **7커밋 16 → 33커밋 19**) ⇒ ★**충돌을 만든 것은 «양»이 아니라 «무엇이 왔는가»**다.
★**그래도 「아무것도 안 한다」로 가지 않았다** — 반증된 것은 «비용이 격차에 비례한다»는 기전이고,
제안이 지목한 «아무도 챙기지 않는다»는 위험은 그대로 참이라서 **축은 두되 임계를 포화점 뒤**에 놓았다.
- 사용자 영향: 런타임 **무변경**. ★**다음 동기를 «언제» 여는지가 처음으로 정해졌다** — 그 전엔 아무 기준이 없었다.
- 검증: behind **0**(요구값) · `merge-base` `bd42427` = upstream HEAD · S1~S8 회차별 커밋/충돌 전수 ·
게이트② 사이클 전수(`reports/*.review.md` 줄1 — 8회차 중 **7회가 1사이클**) ·
upstream 12개월 **144커밋/51주**(주당 중앙 **1** · ★**0인 주 37%**) · 도달 시간 behind 20 = **중앙 44일**
(★**상수로 인용하지 마라** — 게이트② 재측 **41일** · 차이는 **창 정의**에서 온다 ±3일 · **결론 영향 0**).
- ★**비용**: 회차당 새 충돌 **중앙 2.5**(0~9) · 티켓 **3건** · 연 **6~8회** ⇒ 연 **18~24 티켓**.
- ★**방아쇠**: **기계가 «재고» 사람(총괄)이 «발권»** 한다. 재는 자리 권고 = 이 repo 의 **예약 워크플로**
(선례 `rust-audit.yaml` 이 이미 `schedule: cron` · upstream 은 **read-only fetch** 라 발신 0). ★**구현은 별건.**
- ★**후속 추천**: ⑴behind 를 «재는» 워크플로 1개(발권은 사람 유지) ⑵★**「8회차가 들었다」를 «격차 33 의 비용»으로 인용하지 마라** —
그 덩어리의 상당 부분은 **스쿼시로 계보가 접힌 비용**이고 `merge_strategy: merge` 로 이미 닫혔다.
## [2026-09-04] 형제 repo 파리티 락 필요성 조사 — 둘 다 «조건부 필요», 검사기는 포팅 불가 (rustjava-dod-ci-parity-sibling-repo-survey)
- 무엇을: 채택 제안 `2026-09-04-dod-ci-parity-lock#p1` 에 대한 ★**읽기 전용 조사 + 판정**이다.
`wie`·`qts` 의 **DoD 정본 위치 · CI 검사 집합 · 대칭차**를 각각 실측하고, ★**이력으로 실익까지** 쟀다.
Expand Down
29 changes: 29 additions & 0 deletions STATE.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,35 @@
(25번째 run, 앞선 24건 전부 red). **PR 대기 — 게이트③ 미착지.**

## 완료
- [rustjava-upstream-sync-cadence-decision] ★★**upstream 동기 «정기 축» 판정 — 결론: ⒝ 격차 기반 `behind ≥ 20`.**
채택 제안 `2026-09-04-sync-contract-stale-assets-decision#p0`. ★**신설 0**(검사기·크론·워크플로) · `.rs` **0줄** · ★**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-base `af4f6f8`)는 upstream **«신규» 파일**에서,
S8 **누적 8 · 델타 +8**(base `3fb08a8` · merge-base `ba5797b`)은 **전 트리 개명**에서 왔다 ⇒ 경로 트리거가 대부분을 놓친다.
★**임계 20 근거**: 아래로는 **7커밋 포화점**, 위로는 **33 이 미측정 구역 입구**.
★★**[정정] 초판의 「실제로 아팠던 값」은 «지웠다»** — 그것은 이 판정 자신이 «금지한» 독법(8회차를 격차의 비용으로 읽는 것)이라 자기모순이었다.
★★**「20」은 밴드(7~33) 안에서 «고른» 수다** — 밴드는 실측이고 그 안 누적이 `16→17→17→17→19` 로 **평평**하다.
실측 도달 **중앙 44일**(★상수 인용 금지 — 재측 **41일** · 창 정의 ±3일 · 결론 영향 0) ⇒ **연 6~8회** ·
회차당 충돌(정본 누적) **중앙 2.5** · 게이트② 사이클 **8회차 중 7회가 1**.
★**방아쇠 = 기계가 «재고» 사람(총괄)이 «발권»** — 재는 자리 권고는 **이 repo 의 예약 워크플로**(선례 `rust-audit.yaml`),
대안 `bin/healthcheck` 는 **orchestrator 소관이라 별건**. ★**구현은 이 회차가 하지 않았다.**
★**재측정 조건**(3회차 뒤 · 충돌 중앙 ≥5 면 임계 내리고 · 도달 간격 ≤14일이면 올린다)을 §5-B 에 오늘의 값과 함께 박았다.
★★**「오래됐다」는 재개 사유가 아니다 — 이 축은 «시간»이 아니라 «격차»로 열린다.**
★게이트③ 완료: PR #29 — ★★**`--merge` 착지**(★`--squash` 아님 · 등재 repo `contracts/upstream-sync-repos.conf:22`).
머지커밋 sha 는 회신 `merged:` 참조. ★**게이트② 3회차 만에 approve**(초판 → fix → fix2) —
★**반려 둘이 모두 «수를 어떻게 적었는가»였다**: ⑴base·(델타/누적) 병기 없이 기준을 섞었다 ⑵그 정정이 «표»에만 닿고
«산문·`summary`»로 전파되지 않았다. ⇒ ★**「표를 고쳤다고 문서가 고쳐진 것이 아니다」**가 이 리니지가 남긴 규율이다.
★**부모 #27·#28 착지로 두 번 `CONFLICTING` 이 됐고 그때마다 머지로 해소**했다(마지막은 `REPORT.md` 1건) —
★**충돌 중에는 `pull_request` 검사가 «구조적으로» 못 돈다**(검사 1건 → 10건으로 확증).
- [rustjava-dod-ci-parity-sibling-repo-survey] ★★**형제 repo(`wie`·`qts`) 파리티 락 필요성 «조사+판정» — 둘 다 «⒞ 조건부 필요».**
채택 제안 `2026-09-04-dod-ci-parity-lock#p1`. ★**읽기 전용**(형제 repo `git`·PR·파일 수정 **0** · `gh api /contents` 로만 읽었다) · 구현 **0**.
★★**검사기는 «포팅 불가»다** — `wie` 는 DoD 정본이 **`AGENTS.md`** 이고 4번째 게이트(`cargo test`)가
Expand Down
118 changes: 118 additions & 0 deletions docs/upstream-sync-approach.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -899,6 +899,124 @@ behind ★**12 → 0** · 머지커밋 **부모 2개**(`3fb08a8` + `bd42427`).

---

## 5-B. ★★★[2026-09-04 판정] 다음 동기는 «언제» — **격차 기반 `behind ≥ 20`**

채택 제안 `2026-09-04-sync-contract-stale-assets-decision#p0` 에 대한 **결정**이다.
★**S1~S8 이 behind 33 → 0 으로 캠페인을 닫았고, 「다음에 언제 받을지」가 비어 있었다.**

> ★**동기 회차는 `git rev-list --count origin/main..upstream/main` 이 «20 이상»일 때 연다.**
> ★**시간(격주·월간)으로 열지 않는다.** ★**그 아래에서는 열지 않는다** — 아래 실측이 그 이유다.

### ⒜ ★★「벌어진 뒤에 받으면 훨씬 비싸다」는 이 저장소 데이터가 «반증»한다

★★**[2026-09-04 정정 · 게이트②] 초판 표는 «맨 수» 8행이었다 — 이 파일의 상시 규칙(`§5` 「충돌 수를 적을 때는
base 를 반드시 병기한다」)을 «이 표가» 어겼고, 실제로 기준이 섞여 있었다**(S3·S6 은 델타 · S4 는 ★**계획서 «예측»** · S8 은 누적).
⇒ ★**정본 열을 «누적»으로 통일하고 base·기준을 병기한다.**

★**정본 = «누적»**(그 회차의 base 에서 «실제로 열린」 파일 수 = 「이번 회차가 푼 것」) —
★**착지 커밋 제목이 그 값의 1차 사료**다(`git log --first-parent`) — ★**단 «S1~S7» 에 한한다.**
★★**[2026-09-04 정정 · 게이트②] `S8` 은 예외다** — 착지 커밋 `a76b305` 의 제목·본문에 ★**충돌 수가 «0건»** 이다.
그 칸의 값 **8** 의 출처는 ★**직접 재측정**이고(`git merge-tree --write-tree --name-only 3fb08a8 bd42427` —
`Cargo.lock` 1 + 개명 유발 file-location 6 + `thread.rs` 1), ★**값은 옳다. 좁힌 것은 «사료 출처의 범위»뿐이다.**

| 회차 | 커밋 | ★**누적**(정본) | 델타(§5 제안표) | base · merge-base | 성격 |
|---|---|---|---|---|---|
| S1 | 5 | **2** | 2 | `03438b0` · `62cf0c6a` | 설계(tracing) |
| S2 | 1 | **5** | +5 | S1 착지본 · `1f356ae` | 설계(charset) |
| S3 | 1 | ★**11** | +9 | S2 착지본 · `af4f6f8` | 설계(오류 분류) |
| S4 | 8 | ★**2** | ~~0(★**계획서 «예측»**)~~ | `3a59776`(복원 후) · `822504b` | 물량 |
| S5 | 6 | **3** | +3 | `8c1238b` · `3296139c` | 물량 |
| S6 | ★**11** | ★**1** | +0 | `a0b5d3c` · `c4665b0` | 물량 |
| S7 | 1 | **1** | +1 | `3e02f8c` · `95ebc5c` | 물량+ |
| S8 | ★**12** | **8** | +8 | `3fb08a8` · `ba5797b` | 개명 스윕 |

★★**정정 셋을 «숨기지 않는다»**:
- ★**S4 = `0` 은 «실측이 아니라 계획서 예측»이었다**(`reports/…-s4.done.md`: 예측 **0** / 복원 «전» 실측 **20** / 복원 «후» 실측 **2**).
§5 제안표의 그 칸만 **한 번도 정정되지 않았고**, ★**같은 파일의 정정 블록은 이미 `S4 20 → 2` 를 적어 두고 있었다.**
★**하필 그 칸이 논증의 «최강 데이터»(「8커밋인데 충돌 0」)였다** ⇒ **실측 `2` 로 고친다.**
- ★**S6 = `0` 은 «델타»다 — 누적은 `1`**(`string.rs`). ★**§5 가 그 오독을 «실사고»로 이름 붙인 바로 그 자리다.**
- ★**S3 = `+9` 는 델타 · 누적은 `11`**(착지 커밋 제목 「충돌 11」).

★★**세 열을 «다 계산해» 싣는다 — 부호가 안 흔들린다는 것이 요지다**(내가 다시 계산했다):

| 열 | 값(S1…S8) | r | 합 | 중앙 | 많은4(37커밋) | 적은4(8커밋) |
|---|---|---|---|---|---|---|
| A 초판(기준 혼재) | 2·5·9·0·3·0·1·8 | **−0.169** | 28 | 2.5 | 11 | 17 |
| B S4 만 정정 | 2·5·9·2·3·0·1·8 | **−0.134** | 30 | 2.5 | 13 | 17 |
| ★**C 정본 «전부 누적»** | **2·5·11·2·3·1·1·8** | ★**−0.155** | **33** | **2.5** | ★**14** | ★**19** |

★★**세 열 모두 r 의 부호가 «음»이고 「많은4 < 적은4」가 유지된다** ⇒ ★**판정은 흔들리지 않는다.**
★★**단 r 을 «정밀 추정치»로 읽지 마라 — n=8 이고 회차 경계가 «컷 분할»로 정해진 비무작위 표본이다.**
★**이 수는 «비례하지 않는다»는 «부호 판정»으로만 쓴다**(초판이 그 열로 「우상향」을 읽은 것과 **같은 방법**이라
방향만 반대다 — 그래서 강하게 읽지 않는다).

★**정본 기준(C)으로도**: 커밋 많은 4회차(**37커밋**)가 충돌 **14** · 적은 4회차(**8커밋**)가 충돌 **19**.
⇒ ★★**충돌을 만든 것은 «몇 개 왔는가»가 아니라 «무엇이 왔는가»다** — 우리 포크 지점
(tracing span · charset 라우팅 · 오류 분류)을 upstream 이 건드릴 때, 그리고 개명 스윕 같은 **사건**이 올 때.

★**누적 충돌도 «포화»한다**(§5 첫 표): 7커밋 **16** → 10커밋 17 → 21커밋 17 → 32커밋 17 → 33커밋 **19**.
⇒ ★**7커밋 뒤로 26커밋을 더 벌려도 충돌이 «+3»** 이다. 「격차가 크면 비용이 는다」의 흔한 기전이 **여기엔 없다**.

### ⒝ ⇒ 그래서 «작게 자주»가 총비용을 낮추지 «않는다»

★**회차 오버헤드는 «고정»이다** — 회차당 티켓 **3건**(구현 · 게이트② · 게이트③).
게이트② 사이클 실측: **8회차 중 7회가 1사이클**(S4 만 3).
⇒ ★**충돌 총량이 포화하는데 회차 수만 늘면 «총비용이 는다».** 시간 기반(⒜)을 기각한 이유가 이것이다.
★**그리고 upstream 이 느리고 버스티하다**(아래 ⒞) — 시간 축은 ★**behind 0 인데 회차를 여는 «빈 회차»** 를 만든다.

★**「8회차가 들었다」를 «격차 33 의 비용»으로 읽지 마라** — 회차 경계는 §5 의 **컷 분할**이 정했고,
추가 비용의 큰 덩어리는 ★**스쿼시로 계보가 접힌 것**이었다(별 리니지 `…-squash-defeats-convergence`).
그것은 격차가 아니라 **머지 방식**의 비용이고, `merge_strategy: merge` 로 이미 닫혔다.

### ⒞ upstream 속도 실측(12개월 · `upstream/main`)

**144 커밋 / 51주** — 주당 **평균 2.81 · 중앙 1.0 · p90 7** · ★**커밋이 «0»인 주가 19주(37%)**.
누적 도달 시간(연속 창 실측): behind **5** 중앙 **8일** · **10** 중앙 **21일** · **20** 중앙 ★**44일** · **33** 중앙 83일.
⇒ ★**`behind ≥ 20` 은 실질 «약 6주 · 연 6~8회»** 다.
★★**「44일」을 «상수»로 인용하지 마라** — 게이트② 재측은 **41일**이었고 차이는 **창 정의**(어느 12개월을 쓰나)에서 온다(±3일).
★**결론 영향은 0**(어느 값이든 「약 6주」다) — 그러나 인용할 때는 **그 창을 함께 적어라**.

### ⒟ 왜 «20» 인가 — 위아래를 둘 다 적는다

- **아래로 내리지 않는 이유**: 충돌이 **7커밋에서 포화**하므로 그보다 자주 받아도 충돌 총량이 안 준다.
더 자주 받으면 회차 수(= 티켓 3건씩)만 는다.
- **위로 올리지 않는 이유**: ★**포화는 «7~33 구간»에서만 측정됐다 — 33 너머는 «미측정»** 이다
(§5 첫 표의 상한이 33 이다). ★**미측정 구역으로 걸어 들어가지 않는다.**
★★**[2026-09-04 정정 · 게이트②] 초판은 여기에 「33 은 실제로 아팠던 값이다」를 함께 적었다 — «지웠다».**
★**그것은 바로 위 ⒝ 가 «금지한» 독법이다**(「8회차가 들었다」를 격차의 비용으로 읽는 것) ⇒ **같은 절 안의 자기모순**이었다.
★**「미측정」 논거는 혼자 선다** — 아픔을 끌어올 필요가 없다.
- ★**그리고 «늦게 알수록» 우리 자산 낡음이 오래 방치된다** — S8 개명 스윕이 `rust.yml` 의 크레이트 이름과
경로 4곳을 낡게 만들었고, 그 여파가 **문서 정정 5회차**로 이어졌다(§4 리니지).

★★**[2026-09-04 명시 · 게이트②] 「20」은 «밴드 안에서 «고른» 수»다 — 데이터가 그 한 점을 지목하지 않는다.**
★**지어낸 수가 «아니다»**: **밴드**가 실측이다(하한 = 포화 시작 **7** · 상한 = 측정 상한 **33**).
★**그리고 그 밴드 안 누적이 `16 → 17 → 17 → 17 → 19` 로 «평평»해 어디를 골라도 데이터는 같은 말을 한다.**
⇒ ★**「20 을 골랐다」** — 근거는 «도달 중앙 ≈6주가 회차 오버헤드(티켓 3건)와 균형」이라는 ★**판단**이고,
★**⒡ 가 3회차 뒤 재측정을 걸어 그 판단을 검증한다.** ★**밝히는 것이 논증을 약화시키지 않는다** — ⒡ 가 그 전제 위의 장치다.

### ⒠ ★누가 방아쇠를 당기는가 — **기계가 «재고», 사람(총괄)이 «발권한다»**

```sh
git fetch -q upstream && git rev-list --count origin/main..upstream/main # ★오늘의 값 = 0
```
- ★**재는 자리(권고) = 이 repo 의 «예약 워크플로»** — 선례가 있다(`rust-audit.yaml` 이 이미 `schedule: cron`).
upstream 을 **read-only fetch** 해 그 수를 찍고 임계 초과 시 **눈에 보이게** 알린다. ★**upstream 발신 0**(fetch 는 읽기다).
- ★**대안 = 총괄 레인의 `bin/healthcheck` 축**(그 레인에 이미 체크아웃이 있다).
★**그것은 `orchestrator` repo 소관이라 이 저장소가 정할 수 없다** ⇒ **별건 판정**으로 넘긴다.
- ★★**발권은 «사람(총괄)»이 한다** — 기계가 자동으로 동기 회차를 열지 않는다.
이유: 회차마다 **설계 판단**(우리 포크 지점 유지 여부)이 들어가고, 그것은 S1·S2·S3 에서 실제로 필요했다.
- ★**구현은 «별건»이다 — 이 판정 회차에서 만들지 않았다**(검사기·크론·워크플로 신설 **0**).

### ⒡ ★재개(재측정) 조건 — 세는 법과 오늘의 값

> ★**새 축으로 «3회차»를 돈 뒤 다시 재라.** 임계 20 은 «시작값»이지 상수가 아니다.

재잴 것 셋: ⑴임계 도달 간격(실제 일수) ⑵회차당 새 충돌 ⑶게이트② 사이클 수.
★**⑵의 중앙이 «5 이상»으로 오르면 임계를 내려라**(포화 가정이 깨진 것) ·
★**⑴이 «14일 이하»로 짧아지면 임계를 올려라**(upstream 이 빨라진 것 — 지금은 중앙 44일).
★**오늘의 값**: behind **0** · upstream HEAD `bd42427`(2026-08-31) · 마지막 착지 `61d5bf3f`.
★★**「오래됐다」는 재개 사유가 «아니다»** — 이 축은 **시간이 아니라 격차**로 열린다.

## 6. 이 접근안이 **하지 않는** 것

- upstream(`dlunch/RustJava`) 발신 0. `classfile::ClassFileError` 에 진단 변형을 되돌려 넣는 안은
Expand Down
Loading