From 5618f824425cbbf76d5462c86970f16131f63a6e Mon Sep 17 00:00:00 2001 From: jun0 Date: Fri, 4 Sep 2026 13:14:17 +0900 Subject: [PATCH 1/5] =?UTF-8?q?docs:=20=E3=80=8C=EC=9A=B0=EB=A6=AC=20?= =?UTF-8?q?=EC=9E=90=EC=82=B0=EC=9D=B4=20=EB=82=A1=EB=8A=94=EB=8B=A4?= =?UTF-8?q?=E3=80=8D=20=EC=A1=B0=ED=95=AD=20=ED=8C=90=EC=A0=95=20=E2=80=94?= =?UTF-8?q?=20=EB=84=A3=EC=A7=80=20=EC=95=8A=EA=B3=A0=20DoD=20=EC=9D=98=20?= =?UTF-8?q?CI=20=EA=B2=80=EC=82=AC=20=EB=88=84=EB=9D=BD=EC=9D=84=20?= =?UTF-8?q?=EB=A7=89=EC=95=98=EB=8B=A4=20[rustjava-sync-contract-standing-?= =?UTF-8?q?clause-for-our-assets-going-stale]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ★먼저 셌다(목록 문서화로 시작하지 않았다): 자산 8건을 돌연변이로 깨뜨려 무엇이 잡는지 실측 — 경로 문자열·setProperty 서술자·charset 라우팅·ClassFormatError 단정은 cargo test RED · 수동 span 은 clippy RED · double_must_use allow 는 깨져도 무해 · 워크로그 스크립트는 로컬+CI 둘 다. ⇒ 「아무것도 없음」은 1개(CI 워크플로의 --exclude 크레이트 이름) ⇒ 계약대로 조항이 아니라 그 하나를 고쳤다. ★그 1개도 조용히 실패하지 않는다(excluded package(s) not found + 빌드 실패) ⇒ 문제는 침묵이 아니라 늦음이고, 근인은 「자산 목록이 없다」가 아니라 「로컬 DoD 가 CI 5종 중 wasm32 clippy 한 줄을 빠뜨렸다」였다 — 그 줄이 그 자산이 사는 유일한 자리다. ⇒ CLAUDE.md DoD 가 CI 5줄을 축약 없이 그대로 싣는다. ★사료: S3·S5·S6=신규/판본 교체(테스트) · S7=공용 API(컴파일) · S8=개명(CI만/테스트) ⇒ 셋은 같은 형태가 아니고 잡는 그물이 다르다 ⇒ 조항 하나로 덮으면 이미 그물이 있는 다섯 자리에 사람 확인을 얹게 된다. ★재개 조건: 「CI 검사 ∖ 로컬 DoD」가 1건이라도 생기면 다시 연다 · 세는 명령을 §4 에 박았다 · 오늘의 값 0(착수 시 5). CI 5줄 문면 그대로 전건 rc=0 · 554/0/1(새 red 0) · 코드 변경 0. --- CLAUDE.md | 15 +- REPORT.md | 28 ++++ STATE.md | 11 ++ docs/upstream-sync-approach.md | 59 ++++++++ ...4-sync-contract-stale-assets-decision.json | 46 ++++++ ...-04-sync-contract-stale-assets-decision.md | 132 ++++++++++++++++++ 6 files changed, 289 insertions(+), 2 deletions(-) create mode 100644 docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json create mode 100644 docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md diff --git a/CLAUDE.md b/CLAUDE.md index d4737488..f9517b60 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -22,8 +22,19 @@ **검증기로 막을 수 없다.** ⇒ 이 조항은 **1차 방어**이며 **최종 방어는 diff 검토**다. ## Definition of Done -- `cargo fmt --check` · `cargo clippy` · `cargo test` · `python3 scripts/check-worklog-json.py` - 전부 green(명령 상세 = `AGENTS.md`). +- ★**`.github/workflows/rust.yml` 이 «치는 그대로» 전부 green** — 축약하지 말고 이 다섯 줄을 그대로 쳐라: + ``` + cargo fmt --all -- --check + cargo clippy --all -- -D warnings + cargo clippy --workspace --exclude test-utils --target wasm32-unknown-unknown -- -D warnings + cargo test --all + python3 scripts/check-worklog-json.py + ``` + ★★**축약본을 쓰지 마라 — 그것이 2026-09-04 에 실제로 구멍을 만들었다.** 종전 문안은 + `cargo fmt --check`·`cargo clippy`·`cargo test` 로 줄여 적어 ★**wasm32 줄이 통째로 빠져 있었고**, + 그 줄이 ★**`--exclude <크레이트 이름>` 이 사는 «유일한» 자리**다. ⇒ upstream 이 `test_utils` 를 + `test-utils` 로 개명(S8)했을 때 **로컬에서는 어떤 명령으로도 드러나지 않고 CI 에서만** 빨개졌다. + ⇒ ★**CI 가 검사를 늘리거나 인자를 바꾸면 이 블록도 «같이» 고쳐라**(아래 재개 조건이 그것을 센다). - 착수·완료마다 STATE.md 의 "진행중/완료/다음" 을 갱신하고, 완료 시 REPORT.md 상단에 `[YYYY-MM-DD]` 요약 3줄(무엇을·왜·사용자 영향) + 후속 추천을 append 한다. - ★**후속 추천을 적었으면 `docs/worklog/YYYY-MM-DD-.{md,json}` 한 쌍도 남긴다** — diff --git a/REPORT.md b/REPORT.md index 1d348746..0a58d8cd 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,5 +1,33 @@ # REPORT +## [2026-09-04] 「우리 자산이 낡는다」 상시 조항 판정 — 넣지 않고 «구멍 하나»를 막았다 (rustjava-sync-contract-standing-clause-for-our-assets-going-stale) +- 무엇을: 운영자 채택 제안 둘(`2026-09-04-upstream-sync-s6#p1`·`…-s7#p1`)에 대한 **결정**이다. + ★**결론: 상시 조항을 «넣지 않는다».** 대신 ★**로컬 DoD 가 CI 검사 5종 중 «wasm32 clippy» 한 줄을 + 빠뜨리고 있던 것**을 고쳤다 — `CLAUDE.md` DoD 가 이제 **CI 명령 5줄을 축약 없이 그대로** 싣는다. + ★**코드 변경 0 · 문서 2파일**(`CLAUDE.md` · `docs/upstream-sync-approach.md`). +- 왜: ★**목록 문서화로 시작하지 않고 «먼저 셌다»**(티켓이 그렇게 요구했다). 우리 자산 **8건**을 + ★**돌연변이로 깨뜨려** 무엇이 잡는지 실측했다 — 경로 문자열·`setProperty` 서술자·charset 라우팅· + `ClassFormatError` 종류 단정은 **`cargo test` RED**, 수동 span 은 **clippy RED**, + `double_must_use` allow 는 **깨져도 무해**, 워크로그 스크립트는 **로컬 DoD 와 CI 둘 다** 잡는다. + ⇒ ★**「아무것도 없음」 칸이 «1개»**(CI 워크플로의 `--exclude <크레이트 이름>`)이고, + 계약이 정한 대로 ★**1개면 조항이 아니라 «그 하나를 고치는 것»이 처방**이다. + ★★**게다가 그 1개도 «조용히» 실패하지 않는다** — cargo 가 `warning: excluded package(s) … not found` + 를 찍고 빌드가 깨진다 ⇒ ★**문제는 «침묵»이 아니라 «늦음»**(push 후 CI 에서만)이고, + ★**근인은 「자산 목록이 없다」가 아니라 «로컬 DoD 가 CI 한 줄을 빠뜨렸다»** 였다. +- 사용자 영향: 런타임 동작 **무변경**. 회차가 로컬에서 CI 와 **같은 5줄**을 돌리게 되어 + ★**「로컬 green 인데 CI red」 부류가 이 축에서 사라진다**(S5·S7·S8 이 실제로 그 부류였다). +- 검증: CI 5줄을 **워크플로 문면 그대로** 실행 — 전건 **rc=0** · `cargo test --all` **554 / 0 / 1**(baseline 동수 · 새 red 0). + ★**돌연변이는 전부 복구**했고 워킹트리는 문서 2파일만 바뀌었다. +- ★★**사료 — 「세 번」·「두 방향」을 확정하되 결론은 «한 조항으로 못 덮는다»**: + S3(문구 단정 3건 · 테스트) · S5(io 5곳 · 테스트) · S6(regex 3곳 · 정독) = **⑴신규/판본 교체** · + S7(우리 테스트 5곳 · **컴파일**) = **⑵공용 API 변경** · S8(`rust.yml`·경로 4곳 · **CI만/테스트**) = **⑶개명**. + ⇒ ★**잡는 그물이 각각 다르므로**, 조항 하나로 덮으면 **이미 그물이 있는 다섯 자리에까지 사람 확인을 얹게 된다**. +- ★★**재개 조건**(결정에 재개 조건이 없으면 «영구 종결»로 읽힌다): + 「**CI 가 치는 검사 중 로컬 DoD 에 없는 것이 1건이라도 생기면 다시 연다**」 · + ★**세는 명령을 `docs/upstream-sync-approach.md` §4 에 박았다** · ★**오늘의 값 = 0**(착수 시 **5**). +- 후속 추천: ⑴**게이트③은 `--merge`**(등재 repo). ⑵★**upstream 동기 «정기 축» 판정은 아직 열려 있다** + (S8 워크로그 `proposals[1]` · behind 0 인 지금이 적기다) — 이 회차는 그것을 «건드리지 않았다». + ## [2026-09-04] upstream 동기 S8 — 컷 `bd42427` 개명 스윕 · ★**behind 0** (rustjava-upstream-sync-s8-rename-sweep-decision) - 무엇을: upstream `bd42427` 까지 **12커밋**(crates.io 공개 준비 개명 스윕)을 `--merge` 로 흡수하고 충돌 **8건**을 해소했다. ★★**`merge-base` `ba5797b` → `bd42427` · behind `12` → ★`0`** · 부모 **2개** diff --git a/STATE.md b/STATE.md index bd17a9b2..84138fec 100644 --- a/STATE.md +++ b/STATE.md @@ -1,6 +1,17 @@ # STATE ## 진행중 +- [rustjava-sync-contract-standing-clause-for-our-assets-going-stale] ★**「우리 자산이 낡는다」 상시 조항 + «판정» — 결론: ★★넣지 «않는다». 대신 «그물이 없던 자리 하나»를 막았다.** ★코드 변경 0 · 문서 2파일. + ★**먼저 셌다(목록 문서화로 시작하지 않았다)**: 자산 8건을 **돌연변이로 깨뜨려** 무엇이 잡는지 쟀다 — + 경로 문자열·`setProperty` 서술자·charset 라우팅·`ClassFormatError` 단정은 **`cargo test` RED** · + 수동 span 은 **clippy RED** · `double_must_use` allow 는 **깨져도 무해** · 워크로그 스크립트는 **로컬+CI 둘 다**. + ⇒ ★**「아무것도 없음」은 «1개»**(CI 워크플로의 `--exclude <크레이트 이름>`) ⇒ 계약대로 **조항이 아니라 그 하나를 고쳤다**. + ★★**근인은 「자산 목록이 없다」가 아니었다** — ★**로컬 DoD 가 CI 검사 5종 중 «wasm32 clippy» 한 줄을 빠뜨렸고** + 그 줄이 그 자산이 사는 **유일한 자리**다. ⇒ `CLAUDE.md` DoD 가 이제 **CI 명령 5줄을 축약 없이 그대로** 싣는다. + ★그리고 ②는 «조용히» 실패하지도 않는다(`excluded package(s) not found` + 빌드 실패) ⇒ 문제는 침묵이 아니라 **늦음**이다. + ★**재개 조건**: 「CI 검사 ∖ 로컬 DoD」가 **1건이라도** 생기면 다시 연다 · **세는 명령을 §4 에 박았다** · + ★**오늘의 값 = 0**(착수 시 **5**). **PR 대기 — 게이트③ 미착지.** - [rustjava-upstream-sync-squash-defeats-convergence] ★**S1~S4 가 착지하고도 fork 가 upstream 에 한 걸음도 가까워지지 않은 근인을 확정하고 계보를 기록했다.** 근인 = 게이트③ 제품 repo **`--squash`**. 증명은 **머지커밋 부모 수**다 — `6bfe97c4`·`11ef5010`·`4bb796de`·`3a597768` **전건 1개**(커밋 7·10·15·21이 diff --git a/docs/upstream-sync-approach.md b/docs/upstream-sync-approach.md index 12694a2f..83b309e7 100644 --- a/docs/upstream-sync-approach.md +++ b/docs/upstream-sync-approach.md @@ -185,6 +185,65 @@ upstream 은 여기서만 `UTF-8`/`EUC-KR` 하드코딩을 유지한다 ⇒ 그 --- +### ★★★[2026-09-04 결정] 「우리 자산이 낡는다」 — ★**상시 조항을 «넣지 않는다». 대신 구멍 하나를 막았다** + +★**채택 제안 둘**(`2026-09-04-upstream-sync-s6#p1` · `2026-09-04-upstream-sync-s7#p1`)에 대한 **결정**이다. + +**결정문**: +> ★**동기 회차 계약에 「우리 자산 서술자 목록을 문서화하고 머지 후 재확인한다」 상시 조항을 «넣지 않는다».** +> ★**대신 «그물이 없던 자리 «하나»»를 막는다 — 로컬 DoD 가 CI 검사 5종 중 «wasm32 clippy» 한 줄을 빠뜨리고 있었다.** +> ⇒ `CLAUDE.md` §Definition of Done 이 이제 **CI 명령 5줄을 «축약 없이 그대로»** 싣는다. + +★**왜 조항이 아닌가 — «세고» 정했다**(먼저 목록을 만들지 않았다). 자산 8건을 **돌연변이로 깨뜨려** 무엇이 잡는지 쟀다: + +| # | 우리 자산 | 돌연변이 | 무엇이 잡나 | +|---|---|---|---| +| ① | 픽스처 경로 문자열 | `test-data/` → `test_data/` | ★`cargo test` **RED** | +| ② | ★**CI 워크플로의 크레이트 이름**(`--exclude test-utils`) | `test-utils` → `test_utils` | ★★**로컬 4종 «어느 것도» 안 잡는다 — CI 만** | +| ③ | `System.setProperty` 서술자 | `String` → `Object` | ★`cargo test` **RED** | +| ④ | charset 라우팅(PR #5) | `Charset::resolve` → 폴백 우회 | ★`cargo test` **RED** | +| ⑤ | 수동 span(PR #4) | `.instrument(span)` 삭제 | ★`clippy` **RED**(미사용 import) | +| ⑥ | `ClassFormatError` 종류 단정(PR #3) | `ClassFormatError` → `Throwable` | ★`cargo test` **RED** | +| ⑦ | `double_must_use` allow(PR #14) | allow 삭제 | stable·beta 둘 다 **ok** ⇒ ★**깨져도 무해**(낡음 위험 없음) | +| ⑧ | 워크로그 잠금 스크립트 경로 | 스크립트 이동 | 로컬 DoD **와** CI 둘 다 잡는다(rc=2) | + +⇒ ★**「아무것도 없음」 칸은 «1개»**(②)이고, 계약이 정한 대로 **1개면 조항이 아니라 «그 하나를 고치는 것»이 처방**이다. + +★★**그리고 ② 는 «조용히» 실패하지도 않았다 — 그 정정이 처방을 더 좁혔다.** +낡은 이름으로 치면 cargo 가 ★**`warning: excluded package(s) 'test_utils' not found in workspace`** 를 찍고 **빌드가 깨진다**(rc≠0). +⇒ 문제는 «침묵»이 아니라 ★**«늦음»**이다(push 후 CI 에서만 난다). +⇒ ★**근인은 「자산 목록이 없다」가 아니라 ★«로컬 DoD 가 CI 검사 한 줄을 빠뜨렸다»**이다 — 그것을 고쳤다. + +★**사료 — 「세 번」·「두 방향」은 확정하되, ★«한 조항으로 못 덮는다»가 결론이다**: + +| 회차 | 낡은 것 | 방향 | 잡은 것 | +|---|---|---|---| +| S3 | `test_class_format.rs` 문구 단정 3건 | ⑴upstream **신규/판본 교체** | 테스트 | +| S5 | io 테스트 **5곳** `setProperty` 서술자 | ⑴ | 테스트 | +| S6 | regex 테스트 **3곳** 〃 | ⑴ | 정독(테스트 «전») | +| S7 | 우리 고유 테스트 **5곳** `invoke_virtual` | ⑵**공용 API 시그니처 변경** | 컴파일 | +| S8 | `rust.yml` 크레이트명 · `test_class_format.rs` 경로 4곳 | ⑶**개명** | ★CI 만 / 테스트 | + +⇒ ★★**셋은 «같은 형태»가 아니다** — 잡는 그물이 각각 다르다(테스트·컴파일·CI). +★**그래서 조항 하나로 덮으려 하면 «이미 그물이 있는 다섯 자리»에까지 사람 확인을 얹게 된다** — 그것이 비용이다. + +### ★★재개 조건 — «세는 법»과 «오늘의 값» + +> ★**CI 가 치는 검사 중 로컬 DoD 에 없는 것이 «1건이라도» 생기면 이 결정을 다시 연다.** + +```sh +# CI 검사 ∖ 로컬 DoD (0 이어야 한다) +cd "$(git rev-parse --show-toplevel)" +DOD=$(sed -n '/## Definition of Done/,/^- 착수·완료마다/p' CLAUDE.md) +LC_ALL=C /usr/bin/grep -E '^[[:space:]]+- run: ' .github/workflows/rust.yml | sed 's/^[[:space:]]*- run: //' | while IFS= read -r c; do printf '%s' "$DOD" | LC_ALL=C /usr/bin/grep -qF -- "$c" || echo "MISSING: $c"; done | /usr/bin/grep -c . +``` + +★**오늘의 값 = 0**(2026-09-04 · 이 회차가 5 → 0 으로 만들었다). +★**이 수가 «1 이상»이 되면**: 그 빠진 검사가 다시 「로컬에서 안 잡히는 자산」을 만들 수 있으므로 +**⑴그 줄을 DoD 에 넣거나 ⑵넣을 수 없는 이유를 적고 이 결정을 재검토**하라. +★**「조항이 필요하다」로 바로 가지 마라 — 그때도 «먼저 세라»**(위 돌연변이 표를 다시 만들면 된다). + + ## 5. 단계 분할 — ★**커밋 수로 자르지 마라. 충돌은 앞쪽 7커밋에 몰려 있다** 각 컷 지점에서 `git merge-tree --write-tree --name-only origin/main ` 을 돌린 실측: diff --git a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json new file mode 100644 index 00000000..6462f2d9 --- /dev/null +++ b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json @@ -0,0 +1,46 @@ +{ + "schema": 1, + "date": "2026-09-04", + "title": "「우리 자산이 낡는다」 상시 조항 판정 — 넣지 않고 로컬 DoD 의 CI 검사 누락 1건을 막았다", + "services": [ + "RustJava" + ], + "taskId": "rustjava-sync-contract-standing-clause-for-our-assets-going-stale", + "summary": "운영자 채택 제안 둘(2026-09-04-upstream-sync-s6#p1 · …-s7#p1)에 대한 결정이다. 결론: 동기 회차 계약에 「우리 자산 서술자 목록을 문서화하고 머지 후 재확인한다」 상시 조항을 넣지 않는다. 대신 그물이 없던 자리 하나를 막았다 — CLAUDE.md §Definition of Done 이 이제 CI 명령 5줄을 축약 없이 그대로 싣는다. 목록 문서화로 시작하지 않고 먼저 셌다: 우리 자산 8건을 돌연변이로 깨뜨려 무엇이 잡는지 실측했고(경로 문자열·setProperty 서술자·charset 라우팅·ClassFormatError 종류 단정은 cargo test RED · 수동 span 은 clippy RED · double_must_use allow 는 stable·beta 둘 다 ok 라 깨져도 무해 · 워크로그 스크립트는 로컬 DoD 와 CI 둘 다), 「아무것도 없음」 칸이 1개(CI 워크플로의 --exclude 크레이트 이름)였다. 계약이 정한 대로 1개면 조항이 아니라 그 하나를 고치는 것이 처방이다. 그리고 그 1개도 조용히 실패하지 않는다 — cargo 가 warning: excluded package(s) not found 를 찍고 빌드가 깨진다 ⇒ 문제는 침묵이 아니라 늦음이고, 근인은 「자산 목록이 없다」가 아니라 「로컬 DoD 가 CI 검사 5종 중 wasm32 clippy 한 줄을 빠뜨렸다」였다. 그 줄이 --exclude 크레이트 이름이 사는 유일한 자리다.", + "changes": [ + "CLAUDE.md §Definition of Done — CI(rust.yml)가 치는 5줄을 축약 없이 그대로 싣도록 교체 + 「축약본을 쓰지 마라」와 그 이유(2026-09-04 S8 실사고: wasm32 줄이 빠져 있어 test_utils→test-utils 개명이 로컬에서 안 드러나고 CI 에서만 red 였다) + 「CI 가 검사를 늘리거나 인자를 바꾸면 이 블록도 같이 고쳐라」.", + "docs/upstream-sync-approach.md §4 뒤 — 「[2026-09-04 결정] 「우리 자산이 낡는다」」 절 신설: 결정문 · 돌연변이 표 8건(무엇이 잡는가) · 「아무것도 없음 1개」 · 「조용히가 아니라 늦음」 정정 · 사료 표(S3·S5·S6=⑴ / S7=⑵ / S8=⑶ · 셋은 같은 형태가 아니다) · 재개 조건과 세는 명령과 오늘의 값.", + "STATE.md · REPORT.md · docs/worklog/2026-09-04-sync-contract-stale-assets-decision.{md,json} 갱신·신설.", + "★.github/workflows/rust.yml 은 무접촉 — 크레이트 이름 1건은 S8 회차가 이미 고쳐 착지시켰다." + ], + "deploy": { + "sha": "", + "urls": [] + }, + "verification": "착수 실측: origin/main a76b305 · behind 0 · 열린 PR 0. 계약1⒝ 돌연변이(각각 깨뜨린 뒤 build/clippy/test 를 돌리고 원상 복구): ① tests/test_class_format.rs 의 test-data/ → test_data/ ⇒ build ok · clippy ok · test RED. ③ system.rs 의 setProperty 서술자 String → Object ⇒ test RED. ④ string.rs 의 Charset::resolve → from_name().unwrap() 우회 ⇒ test RED. ⑤ thread.rs 의 .instrument(span) 삭제 ⇒ clippy RED(미사용 import). ⑥ test_class_format.rs 의 ClassFormatError → Throwable ⇒ test RED. ⑦ jvm-bytecode/src/interpreter.rs 의 #[allow(clippy::double_must_use)] 삭제 ⇒ stable clippy ok · beta clippy 도 ok(깨져도 무해). ② cargo clippy --workspace --exclude test_utils --target wasm32-unknown-unknown ⇒ rc=101 이고 문면은 warning: excluded package(s) `test_utils` not found in workspace + tokio wasm 컴파일 실패(조용한 통과가 아니다) · 로컬 4종 중 어느 것도 그 인자를 쓰지 않는다. ⑧ scripts/check-worklog-json.py 이동 ⇒ rc=2(로컬 DoD 와 CI 둘 다 그 경로를 친다). 근인 대조: rust.yml 의 - run: 줄 5개 ↔ CLAUDE.md DoD 4개 ⇒ 차집합이 정확히 wasm32 clippy 한 줄. 재개 조건 세는 명령(회신·§4 동일)의 값: 착수 시 5 → 착지본 0. 계약6: CI 5줄을 워크플로 문면 그대로 실행해 전건 rc=0 · cargo test --all = 554 passed / 0 failed / 1 ignored(baseline 554/0/1 동수 · 새 red 0). 돌연변이 전부 복구 확인(git status 가 문서 2파일만). 계약5: .github/workflows/rust.yml:55 이 이미 --exclude test-utils 이므로 이 회차는 무접촉.", + "issues": [ + "★★결정은 「조항을 넣지 않는다」이고, 그 근거는 «수»다 — 「아무것도 없음」이 1개였다. 그 1개가 2개 이상이 되면 결론이 달라질 수 있으므로 재개 조건과 세는 명령을 §4 에 박았다(오늘의 값 0).", + "★이 결정이 «막는» 것은 「우리 자산이 낡는 것」 자체가 아니라 「그것이 로컬에서 안 드러나고 CI 에서만 드러나는 것」이다. 낡음 자체는 여전히 일어나고, 다만 여섯 자리는 기계가(테스트·컴파일·clippy) 이미 잡는다.", + "★잡는 그물이 축마다 다르다(테스트/컴파일/CI)는 것이 「조항 하나로 못 덮는다」의 근거다 — 조항으로 덮으면 이미 그물이 있는 다섯 자리에까지 사람 확인을 얹게 된다.", + "★double_must_use allow(PR #14)는 이제 지워도 stable·beta 둘 다 통과한다 — upstream 변경으로 불필요해졌을 수 있다. 이 회차는 포크 정책을 바꾸지 않으므로 «건드리지 않았다»(별건 판정 대상).", + "★S8 이 고친 CI 크레이트 이름 1건과 이 회차의 산출은 «다른 층»이다: 전자는 증상 1건, 후자는 그 증상이 늦게 드러난 경로. 티켓이 「고쳤다고 조항 결정을 건너뛰지 마라」고 못박은 자리다.", + "머지하지 않았다 — 게이트②·③은 별 세션이다. ★게이트③은 등재 repo 라 merge_strategy: merge 필수(bin/queue-lint 검사22). upstream 동기 회차를 새로 열지 않았다(behind 0 · S9 없음)." + ], + "proposals": [ + { + "title": "upstream 동기를 «정기 축»으로 둘지 판정하라 — behind 0 인 지금이 적기이고 아직 열려 있다", + "plainSummary": "원본 저장소를 완전히 따라잡았지만 다음에 언제 다시 받아올지가 정해져 있지 않다. 아무도 챙기지 않으면 격차가 다시 벌어지고, 벌어진 뒤에 받으면 훨씬 비싸다.", + "userBenefit": "격차가 작을 때 받아오면 충돌이 작고 우리 고유 기능이 원본 변경에 삼켜질 위험도 작다. 이번 캠페인이 behind 33 에서 시작해 여덟 회차가 걸린 것이 그 반대 사례다.", + "why": "S8 착지로 behind 가 0 이 됐고 계획서 §5 의 7회차 + S8 이 모두 끝났다. 계획서는 「어느 컷을 언제」를 정했지만 「따라잡은 뒤」를 정하지 않았다. 이 캠페인 비용의 대부분이 「격차가 커진 뒤 한꺼번에 받은 것」에서 나왔다 — S5 는 설계 판단 1건, S8 은 개명 스윕 판정이 필요했고 둘 다 격차가 작았으면 훨씬 쌌다. 이 제안은 S8 워크로그 proposals[1] 과 같은 것이며 아직 미처분이다.", + "tradeoff": "⑴정기 축(예: 월 1회 또는 behind 임계)으로 두면 회차가 작아지지만 발권·검수 비용이 상시로 든다. ⑵필요할 때만 받으면 비용이 0 이지만 격차가 다시 33 이 될 수 있고 그때는 이번처럼 여덟 회차가 든다. ⑶behind 를 재는 것만 자동화하고 발권은 사람이 하면 중간이지만 그 기구가 지금 없다.", + "effort": "XS — 판정. 정기 축을 고르면 그 축의 발권 방식은 별건.", + "target": "docs/upstream-sync-approach.md · 총괄 발권 정책" + } + ], + "resolvedIssues": [], + "adoptedProposals": [ + "2026-09-04-upstream-sync-s6#p1", + "2026-09-04-upstream-sync-s7#p1" + ], + "declinedProposals": [] +} diff --git a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md new file mode 100644 index 00000000..c6b1da5d --- /dev/null +++ b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md @@ -0,0 +1,132 @@ +# [2026-09-04] 「우리 자산이 낡는다」 상시 조항 «판정» — 넣지 않고 «구멍 하나»를 막았다 + +**티켓**: `rustjava-sync-contract-standing-clause-for-our-assets-going-stale` +**채택 제안 2건**: `2026-09-04-upstream-sync-s6#p1` · `2026-09-04-upstream-sync-s7#p1` +**성격**: 결정 회차 · 코드 변경 **0** · 문서 **2파일** + +--- + +## 1. ★먼저 «셌다» — 목록 문서화로 시작하지 않았다 + +티켓이 못박은 순서 그대로: ★**「그물이 없는 자리」의 «수»가 이 결정을 정한다.** +자산 8건을 ★**돌연변이로 깨뜨려**(추론 0) 무엇이 잡는지 쟀다. + +| # | 우리 자산(출처) | 돌연변이 | build | clippy | test | ★그물 | +|---|---|---|---|---|---|---| +| ① | 픽스처 경로 문자열(PR #3) | `test-data/` → `test_data/` | ok | ok | ★**RED** | 있음 | +| ② | ★**CI 워크플로 `--exclude test-utils`**(S8) | `test-utils` → `test_utils` | — | — | — | ★★**없음(CI 만)** | +| ③ | `System.setProperty` 서술자(PR #5) | `String` → `Object` | ok | ok | ★**RED** | 있음 | +| ④ | charset 라우팅(PR #5) | `Charset::resolve` → 폴백 우회 | ok | ok | ★**RED** | 있음 | +| ⑤ | 수동 span(PR #4) | `.instrument(span)` 삭제 | ok | ★**RED** | ok | 있음 | +| ⑥ | `ClassFormatError` 종류 단정(PR #3) | `ClassFormatError` → `Throwable` | ok | ok | ★**RED** | 있음 | +| ⑦ | `double_must_use` allow(PR #14) | allow 삭제 | ok | ok(★beta 도 ok) | ok | ★**해당 없음 — 깨져도 무해** | +| ⑧ | 워크로그 잠금 스크립트 경로(PR #15) | 스크립트 이동 | — | — | — | 있음(로컬 DoD **와** CI 둘 다 · rc=2) | + +★**⑦은 「그물 없음」이 아니라 「위험 없음」이다** — allow 를 지워도 stable·beta 둘 다 통과한다 +(upstream 이 그 자리를 바꿔 allow 가 불필요해졌다). ⇒ 낡아도 아무것도 깨지지 않으므로 이 결정의 대상이 아니다. + +⇒ ★★**「아무것도 없음」 칸은 «1개»(②)다.** + +## 2. ★★그 1개도 «조용히» 실패하지 않는다 — 그 정정이 처방을 더 좁혔다 + +낡은 이름으로 치면 cargo 가 이렇게 말한다: + +``` +warning: excluded package(s) `test_utils` not found in workspace `…/RustJava` +error: Only features sync,macros,io-util,rt,time are supported on wasm. +error: could not compile `tokio` (lib) due to 1 previous error ← rc≠0 +``` + +⇒ ★**문제는 «침묵»이 아니라 «늦음»이다** — push 후 CI 에서만 난다. +⇒ ★★**근인은 「자산 목록이 없다」가 «아니라» — 로컬 DoD 가 CI 검사 한 줄을 빠뜨린 것이다.** + +**대조 실측**: + +| | 검사 | +|---|---| +| CI(`rust.yml`) | `fmt --all -- --check` · `clippy --all` · ★**`clippy --workspace --exclude test-utils --target wasm32`** · `test --all` · `check-worklog-json.py` = **5** | +| 로컬 DoD(종전) | `cargo fmt --check` · `cargo clippy` · `cargo test` · `check-worklog-json.py` = **4** | + +★**빠진 하나가 정확히 wasm32 줄**이고, ★**그 줄이 `--exclude <크레이트 이름>` 이 사는 «유일한» 자리**다. +⇒ S8 의 개명(`test_utils`→`test-utils`)이 **로컬 어디에서도 안 드러난** 이유가 이것이다. + +## 3. 사료 확정 — 「세 번」·「두 방향」 (계약 2) + +| 회차 | 낡은 것 | ⒝ 방향 | 잡은 것 | +|---|---|---|---| +| **S3** | `test_class_format.rs` 문구 단정 3건 | ⑴upstream **신규/판본 교체** | 테스트 | +| **S5** | io 테스트 **5곳** `setProperty` 서술자 | ⑴ | 테스트 | +| **S6** | regex 테스트 **3곳** 〃 | ⑴ | ★정독(테스트 «전») | +| **S7** | 우리 고유 테스트 **5곳** `invoke_virtual` | ⑵**공용 API 시그니처 변경** | ★컴파일 | +| **S8** | `rust.yml` 크레이트명 · `test_class_format.rs` 경로 4곳 | ⑶**개명** | ★CI 만 / 테스트 | + +⒜ **「세 번」 = S3·S5·S6**(제안 `#p1` 이 센 것) · ⒝ **「두 방향」 = ⑴·⑵**(S7 이 가른 것) · +★**S8 이 ⑶을 더해 «셋»이 됐다.** + +⒞ ★★**같은 형태인가 → «아니다».** 잡는 그물이 각각 다르다(테스트 · 컴파일 · CI). +⇒ ★**조항 하나로 못 덮는다** — 덮으려 하면 **이미 그물이 있는 다섯 자리에까지 사람 확인을 얹는다**. 그것이 비용이다. + +## 4. ★★결정문 · 적은 «자리» · 이유 (계약 3) + +> ★**동기 회차 계약에 「우리 자산 서술자 목록을 문서화하고 머지 후 재확인한다」 상시 조항을 «넣지 않는다».** +> ★**대신 «그물이 없던 자리 하나»를 막는다 — `CLAUDE.md` §Definition of Done 이 CI 명령 5줄을 «축약 없이 그대로» 싣는다.** + +**⒜ 왜 이것이 «가장 좁은» 형태인가**: +- 계약 자체가 정했다 — 「**1개면 계약 조항이 아니라 «그 하나를 고치는 것»이 처방**」. +- ★**사람 기억에 맡기지 않는다** — 추가한 것은 «체크리스트 항목»이 아니라 ★**실제로 도는 명령**이다. + 회차가 DoD 를 돌리면 **cargo 가 스스로 낡음을 말한다**(`excluded package(s) … not found`). +- ★**목록을 만들지 않았다** — 목록은 사람이 유지해야 하고, 위 표대로 **여섯 자리는 이미 기계가 지킨다**. + +**⒞ 적은 자리 — 워크로그에만 적지 않았다**: +| 자리 | 무엇을 | 왜 그 자리인가 | +|---|---|---| +| ★`CLAUDE.md` §Definition of Done | **CI 5줄 verbatim** + 「축약하지 마라」와 그 이유(S8 실사고) | ★**모든 회차가 반드시 읽는다**(DoD) | +| ★`docs/upstream-sync-approach.md` §4 뒤 | **결정문 · 돌연변이 표 · 사료 표 · 재개 조건과 세는 명령** | ★**동기 회차가 반드시 읽는 계약 파일** | + +## 5. ★★재개 조건 + 세는 명령 + 오늘의 값 (계약 4) + +> ★**CI 가 치는 검사 중 로컬 DoD 에 없는 것이 «1건이라도» 생기면 이 결정을 다시 연다.** + +```sh +cd "$(git rev-parse --show-toplevel)" +DOD=$(sed -n '/## Definition of Done/,/^- 착수·완료마다/p' CLAUDE.md) +LC_ALL=C /usr/bin/grep -E '^[[:space:]]+- run: ' .github/workflows/rust.yml | sed 's/^[[:space:]]*- run: //' \ +| while IFS= read -r c; do printf '%s' "$DOD" | LC_ALL=C /usr/bin/grep -qF -- "$c" || echo "MISSING: $c"; done \ +| /usr/bin/grep -c . +``` + +| | 값 | +|---|---| +| 착수 시 | ★**5**(DoD 가 축약본이라 CI 5줄 «전건»이 문자열로 안 맞았고, 그중 wasm32 는 **의미로도** 없었다) | +| ★**오늘(착지본)** | ★**0** | + +★**1 이상이 되면**: ⑴그 줄을 DoD 에 넣거나 ⑵넣을 수 없는 이유를 적고 **이 결정을 재검토**하라. +★**「조항이 필요하다」로 바로 가지 마라 — 그때도 «먼저 세라»**(위 §1 돌연변이 표를 다시 만들면 된다). + +## 6. 계약 5 — CI 크레이트 이름 1건은 ★**이미 고쳐져 있었다** + +티켓은 「이 회차에서 고쳐도 된다(XS)」고 열어 뒀으나 ★**S8 회차가 이미 고쳐 착지시켰다** +(`.github/workflows/rust.yml:55` = `--exclude test-utils`). ⇒ **이 회차는 그 파일을 안 건드렸다.** +★**그리고 티켓 경고대로 «고쳤으니 조항 결정을 건너뛴다»로 가지 않았다** — 위 §4 가 그 별도 산출이다. +★**이 회차가 한 것은 «그 사고가 로컬에서 안 잡힌 이유»를 막은 것**이고, 그 둘은 다른 층이다 +(전자는 **증상 1건**, 후자는 **그 증상이 늦게 드러난 경로**). + +## 7. 계약 6 — 기존 스위트 전건 · 새 red 0 + +★**CI 5줄을 «워크플로 문면 그대로»** 실행: + +| 명령 | rc | +|---|---| +| `cargo fmt --all -- --check` | **0** | +| `cargo clippy --all -- -D warnings` | **0** | +| `cargo clippy --workspace --exclude test-utils --target wasm32-unknown-unknown -- -D warnings` | **0** | +| `cargo test --all` | **0** — ★**554 / 0 / 1** | +| `python3 scripts/check-worklog-json.py` | **0** | + +★**새 red 0**(baseline **554/0/1** 동수) · ★**돌연변이는 전부 복구**했고 워킹트리는 **문서 2파일**만 바뀌었다. + +## 8. 경계 준수 + +★**upstream 동기 회차를 «새로 열지» 않았다**(behind **0** · S9 없음) · 포크 정책 무접촉 · +★**「목록 통째 문서화」로 시작하지 않았다**(먼저 셌다) · 머지 **0** · force-push **0** · 리베이스 **0** · +`main` 직접 push **0** · 시크릿 출력 **0** · 코드(`.rs`) 변경 **0** · 맨 `grep` **0**(전건 `/usr/bin/grep`). From 99bcdc3ef531ea86f48327bcf5796410cf6dd19e Mon Sep 17 00:00:00 2001 From: jun0 Date: Fri, 4 Sep 2026 14:37:54 +0900 Subject: [PATCH 2/5] =?UTF-8?q?docs:=20=EA=B3=84=EC=88=98=EA=B0=80=20?= =?UTF-8?q?=C2=AB2=C2=BB=EB=8B=A4=20=E2=80=94=20=E2=91=A6=ED=96=89=20?= =?UTF-8?q?=EB=9D=BC=EB=B2=A8=20=EC=A0=95=EC=A0=95=20+=20toolchain=20?= =?UTF-8?q?=EC=B6=95=20=EC=B6=94=EA=B0=80=20[rustjava-sync-contract-standi?= =?UTF-8?q?ng-clause-for-our-assets-going-stale]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ★게이트② request-changes 승계. 실측 규율(먼저 세고·돌연변이로 재고·재개 조건에 세는 법과 값을 박는다)은 그대로 두고, 검수자가 짚은 두 결함을 고쳤다. C1 — ⑦행 「깨져도 무해」는 거짓이었다. 근인은 돌연변이를 «비하중» 자리에 넣은 것이다: 초판은 interpreter.rs:1(같은 파일 함수별 allow 에 가려진 중복) 한 곳만 지웠고 jvm.rs 에 7곳이 남아 있었다. 세 갈래 재측정(각 회 cargo fmt 정규화): ①interpreter.rs:1 만 → beta 0(초판 재현) ②jvm.rs:2 만 → beta 0 ③★9곳 전건 → stable 0 · ★beta error 7. ⇒ ⑦의 그물은 «CI 만»이고 ②와 같은 칸이다 ⇒ ★계수 = 2. ★후속 추천 3번(「allow 를 지워도 통과한다」)을 철회했다 — 그대로 두면 다음 회차가 beta 3셀을 빨갛게 만든다. C2 — 처방·재개 조건이 «매트릭스 차원»에 안 닿았다. rust: [stable,beta] 를 [stable] 로 줄여도 [stable,beta,nightly] 로 늘려도 종전 명령은 0 이었다(양성대조 - run: 1줄 추가는 1). ⇒ ⒜DoD 에 cargo +beta clippy 추가(5줄 → 6줄 · CI 는 6셀 = toolchain 2 × OS 3 이고 repo 에 rust-toolchain.toml 이 없어 맨 cargo 는 stable 1개다) ⒝재개 조건에 축② «toolchain 매트릭스 대조» 추가. 세 돌연변이 재실측: beta 제거 → 축② 0(★옳다 — 술어가 CI ∖ DoD 라 DoD 가 더 엄격한 건 구멍이 아니다) · nightly 추가 → 축② 1 · - run: 추가 → 축① 1 ⇒ 각 축이 자기 자리에서만 반응한다. ★결론은 그대로 「조항을 넣지 않는다」이나 논거를 다시 세웠다: ②와 ⑦은 다른 자산이 아니라 «한 근인의 두 얼굴»(로컬 DoD 가 CI 매트릭스를 재현하지 않는다)이고, 근인 하나를 고치니 둘 다 그물을 얻었다. 「조항이 여럿이면?」도 기각했다(세 방향 중 둘은 이미 기계가 지키는 자리다). C3 adoptedProposals 세 ref · C4 「제안 2 ↔ 검수 1」 차 해소(2가 맞다) · C5 다섯→여섯 통일 + 세는 명령 · C7 고지(DoD 블록 개악과 OS 축 3종은 이 대조가 못 잡는다). 검증: 새 DoD 6줄 전건 rc=0 · cargo test --all 554/0/1(새 red 0) · allow 9곳 무접촉 · .rs 변경 0. --- CLAUDE.md | 13 ++- REPORT.md | 17 +++- STATE.md | 13 ++- docs/upstream-sync-approach.md | 91 ++++++++++++++++--- ...4-sync-contract-stale-assets-decision.json | 17 ++-- ...-04-sync-contract-stale-assets-decision.md | 35 +++++-- 6 files changed, 149 insertions(+), 37 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index f9517b60..46b76896 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -22,19 +22,26 @@ **검증기로 막을 수 없다.** ⇒ 이 조항은 **1차 방어**이며 **최종 방어는 diff 검토**다. ## Definition of Done -- ★**`.github/workflows/rust.yml` 이 «치는 그대로» 전부 green** — 축약하지 말고 이 다섯 줄을 그대로 쳐라: +- ★**`.github/workflows/rust.yml` 이 «치는 그대로» 전부 green** — 축약하지 말고 이 여섯 줄을 그대로 쳐라: ``` cargo fmt --all -- --check cargo clippy --all -- -D warnings + cargo +beta clippy --all -- -D warnings cargo clippy --workspace --exclude test-utils --target wasm32-unknown-unknown -- -D warnings cargo test --all python3 scripts/check-worklog-json.py ``` - ★★**축약본을 쓰지 마라 — 그것이 2026-09-04 에 실제로 구멍을 만들었다.** 종전 문안은 + ★★**`+beta` 줄을 빼지 마라 — CI 는 이 검사들을 «6셀»(toolchain 2 × OS 3)로 친다.** + `rust.yml` 의 `strategy.matrix.rust = [stable, beta]` 가 그 차원이고, 이 repo 엔 `rust-toolchain.toml` 이 + **없어** 맨 `cargo` 는 **stable 1개**로만 돈다. ⇒ ★**toolchain 축을 안 적으면 「rust.yml 이 치는 그대로」가 «거짓»이 된다.** + ★**실측 근거**(2026-09-04): `#[allow(clippy::double_must_use)]` **9곳을 전건 지우면** + ★**stable clippy 는 0인데 beta clippy 가 error 7** 이다 ⇒ ★**그 자산의 그물은 «beta 축»에만 있다.** + ★★**축약본도 쓰지 마라 — 그것이 2026-09-04 에 실제로 구멍을 만들었다.** 종전 문안은 `cargo fmt --check`·`cargo clippy`·`cargo test` 로 줄여 적어 ★**wasm32 줄이 통째로 빠져 있었고**, 그 줄이 ★**`--exclude <크레이트 이름>` 이 사는 «유일한» 자리**다. ⇒ upstream 이 `test_utils` 를 `test-utils` 로 개명(S8)했을 때 **로컬에서는 어떤 명령으로도 드러나지 않고 CI 에서만** 빨개졌다. - ⇒ ★**CI 가 검사를 늘리거나 인자를 바꾸면 이 블록도 «같이» 고쳐라**(아래 재개 조건이 그것을 센다). + ⇒ ★**CI 가 검사를 늘리거나 «매트릭스 차원»을 바꾸면 이 블록도 «같이» 고쳐라**(아래 재개 조건이 둘 다 센다). + ※OS 축(3종)은 로컬에서 재현할 수 없다 — ★**그 차원만은 CI 가 유일한 그물이고, 그것은 «알고 두는» 값이다.** - 착수·완료마다 STATE.md 의 "진행중/완료/다음" 을 갱신하고, 완료 시 REPORT.md 상단에 `[YYYY-MM-DD]` 요약 3줄(무엇을·왜·사용자 영향) + 후속 추천을 append 한다. - ★**후속 추천을 적었으면 `docs/worklog/YYYY-MM-DD-.{md,json}` 한 쌍도 남긴다** — diff --git a/REPORT.md b/REPORT.md index 0a58d8cd..120453ef 100644 --- a/REPORT.md +++ b/REPORT.md @@ -9,11 +9,15 @@ ★**돌연변이로 깨뜨려** 무엇이 잡는지 실측했다 — 경로 문자열·`setProperty` 서술자·charset 라우팅· `ClassFormatError` 종류 단정은 **`cargo test` RED**, 수동 span 은 **clippy RED**, `double_must_use` allow 는 **깨져도 무해**, 워크로그 스크립트는 **로컬 DoD 와 CI 둘 다** 잡는다. - ⇒ ★**「아무것도 없음」 칸이 «1개»**(CI 워크플로의 `--exclude <크레이트 이름>`)이고, - 계약이 정한 대로 ★**1개면 조항이 아니라 «그 하나를 고치는 것»이 처방**이다. + ⇒ ★★**[게이트② `request-changes` 정정] 「아무것도 없음」은 «2개»다**(② CI `--exclude` · ⑦ `double_must_use` allow). + 초판이 ⑦을 «비하중» 자리에서 재 「무해」로 적었으나, ★**9곳 전건 삭제로 재측정하면 stable 0 · ★beta error 7** + ⇒ ⑦의 그물도 **CI 만**이다. ⇒ ★**「1개면 그 하나를 고쳐라」 규칙은 적용되지 않는다.** ★★**게다가 그 1개도 «조용히» 실패하지 않는다** — cargo 가 `warning: excluded package(s) … not found` 를 찍고 빌드가 깨진다 ⇒ ★**문제는 «침묵»이 아니라 «늦음»**(push 후 CI 에서만)이고, - ★**근인은 「자산 목록이 없다」가 아니라 «로컬 DoD 가 CI 한 줄을 빠뜨렸다»** 였다. + ★**근인은 「자산 목록이 없다」가 아니라 «로컬 DoD 가 CI «매트릭스»를 재현하지 않는다»** 였다 — + ②는 빠진 `- run:` 줄(**target** 축) · ⑦은 빠진 **toolchain** 축(beta) ⇒ ★**한 근인의 두 얼굴**이다. + ⇒ ★**결론은 그대로 「넣지 않는다」이나 논거가 바뀌었다**: 근인 하나를 고치면 둘 다 그물을 얻는다 + (DoD 에 `cargo +beta clippy` 를 넣자 ⑦이 **로컬에서 error 7** 로 잡힌다 · 실측). - 사용자 영향: 런타임 동작 **무변경**. 회차가 로컬에서 CI 와 **같은 5줄**을 돌리게 되어 ★**「로컬 green 인데 CI red」 부류가 이 축에서 사라진다**(S5·S7·S8 이 실제로 그 부류였다). - 검증: CI 5줄을 **워크플로 문면 그대로** 실행 — 전건 **rc=0** · `cargo test --all` **554 / 0 / 1**(baseline 동수 · 새 red 0). @@ -24,9 +28,14 @@ ⇒ ★**잡는 그물이 각각 다르므로**, 조항 하나로 덮으면 **이미 그물이 있는 다섯 자리에까지 사람 확인을 얹게 된다**. - ★★**재개 조건**(결정에 재개 조건이 없으면 «영구 종결»로 읽힌다): 「**CI 가 치는 검사 중 로컬 DoD 에 없는 것이 1건이라도 생기면 다시 연다**」 · - ★**세는 명령을 `docs/upstream-sync-approach.md` §4 에 박았다** · ★**오늘의 값 = 0**(착수 시 **5**). + ★**세는 명령을 `docs/upstream-sync-approach.md` §4 에 박았고, 정정으로 «축이 둘»이 됐다** + (축① `- run:` 줄 · ★축② **toolchain 매트릭스**) · ★**오늘의 값 = 축① 0 · 축② 0**(착수 시 축① 5 · 축② 1). + ★세 돌연변이로 **각 축이 «자기 자리»에서만 반응**함을 실측했다. +- ★★**[정정] 초판 후속 추천 3번을 «철회한다»** — 「`double_must_use` allow 가 이제 지워도 통과한다」는 + **비하중 돌연변이에서 나온 거짓**이다. ★**9곳을 전건 지우면 beta clippy 가 error 7 로 red 다** ⇒ ★**지우지 마라.** - 후속 추천: ⑴**게이트③은 `--merge`**(등재 repo). ⑵★**upstream 동기 «정기 축» 판정은 아직 열려 있다** (S8 워크로그 `proposals[1]` · behind 0 인 지금이 적기다) — 이 회차는 그것을 «건드리지 않았다». + ⑶★**C7 고지**: DoD 블록 «개악»과 **OS 축 3종**은 이 대조가 못 잡는다 — 회차가 두 축을 «실제로 돌렸는지» 적어라. ## [2026-09-04] upstream 동기 S8 — 컷 `bd42427` 개명 스윕 · ★**behind 0** (rustjava-upstream-sync-s8-rename-sweep-decision) - 무엇을: upstream `bd42427` 까지 **12커밋**(crates.io 공개 준비 개명 스윕)을 `--merge` 로 흡수하고 충돌 **8건**을 해소했다. diff --git a/STATE.md b/STATE.md index 84138fec..8b9c2083 100644 --- a/STATE.md +++ b/STATE.md @@ -6,12 +6,19 @@ ★**먼저 셌다(목록 문서화로 시작하지 않았다)**: 자산 8건을 **돌연변이로 깨뜨려** 무엇이 잡는지 쟀다 — 경로 문자열·`setProperty` 서술자·charset 라우팅·`ClassFormatError` 단정은 **`cargo test` RED** · 수동 span 은 **clippy RED** · `double_must_use` allow 는 **깨져도 무해** · 워크로그 스크립트는 **로컬+CI 둘 다**. - ⇒ ★**「아무것도 없음」은 «1개»**(CI 워크플로의 `--exclude <크레이트 이름>`) ⇒ 계약대로 **조항이 아니라 그 하나를 고쳤다**. + ⇒ ★★**[게이트② 정정] 「아무것도 없음」은 «1개»가 아니라 «2개»**(② CI `--exclude` · ⑦ `double_must_use` allow) — + 초판이 ⑦을 «비하중» 자리(중복 crate-level attribute 1곳)에서 재 「무해」로 적었고, ★**9곳 전건 삭제로 재측정하면 + stable 0 · ★beta error 7** 이라 ⑦의 그물도 **CI 만**이다. ⇒ 「1개면 그 하나를 고쳐라」 규칙은 **적용되지 않는다**. + ★**결론은 그대로 「넣지 않는다」이나 논거를 다시 세웠다**: ②와 ⑦은 «한 근인의 두 얼굴»이다 — + ★**로컬 DoD 가 CI «매트릭스»를 재현하지 않는다**(② = 빠진 `- run:` 줄 = target 축 · ⑦ = 빠진 toolchain 축). + ⇒ 근인 하나를 고치니 둘 다 그물을 얻었다(DoD 에 `cargo +beta clippy` 추가 ⇒ ⑦이 **로컬에서 error 7** 로 잡힌다). ★★**근인은 「자산 목록이 없다」가 아니었다** — ★**로컬 DoD 가 CI 검사 5종 중 «wasm32 clippy» 한 줄을 빠뜨렸고** 그 줄이 그 자산이 사는 **유일한 자리**다. ⇒ `CLAUDE.md` DoD 가 이제 **CI 명령 5줄을 축약 없이 그대로** 싣는다. ★그리고 ②는 «조용히» 실패하지도 않는다(`excluded package(s) not found` + 빌드 실패) ⇒ 문제는 침묵이 아니라 **늦음**이다. - ★**재개 조건**: 「CI 검사 ∖ 로컬 DoD」가 **1건이라도** 생기면 다시 연다 · **세는 명령을 §4 에 박았다** · - ★**오늘의 값 = 0**(착수 시 **5**). **PR 대기 — 게이트③ 미착지.** + ★**재개 조건은 «축 둘»이다**(정정): **축① `- run:` 줄** · ★**축② toolchain 매트릭스** — 세는 명령 둘 다 §4 에 박았다. + ★**오늘의 값 = 축① 0 · 축② 0**(착수 시 축① **5** · 축② **1**). ★세 돌연변이(beta 제거·nightly 추가·`- run:` 추가)로 + ★**각 축이 «자기 자리»에서만 반응함을 실측**했다. ★**C7 고지**: DoD 블록 «개악»과 **OS 축 3종**은 이 대조가 못 잡는다. + **PR 대기 — 게이트③ 미착지.** - [rustjava-upstream-sync-squash-defeats-convergence] ★**S1~S4 가 착지하고도 fork 가 upstream 에 한 걸음도 가까워지지 않은 근인을 확정하고 계보를 기록했다.** 근인 = 게이트③ 제품 repo **`--squash`**. 증명은 **머지커밋 부모 수**다 — `6bfe97c4`·`11ef5010`·`4bb796de`·`3a597768` **전건 1개**(커밋 7·10·15·21이 diff --git a/docs/upstream-sync-approach.md b/docs/upstream-sync-approach.md index 83b309e7..e9f669c1 100644 --- a/docs/upstream-sync-approach.md +++ b/docs/upstream-sync-approach.md @@ -204,15 +204,42 @@ upstream 은 여기서만 `UTF-8`/`EUC-KR` 하드코딩을 유지한다 ⇒ 그 | ④ | charset 라우팅(PR #5) | `Charset::resolve` → 폴백 우회 | ★`cargo test` **RED** | | ⑤ | 수동 span(PR #4) | `.instrument(span)` 삭제 | ★`clippy` **RED**(미사용 import) | | ⑥ | `ClassFormatError` 종류 단정(PR #3) | `ClassFormatError` → `Throwable` | ★`cargo test` **RED** | -| ⑦ | `double_must_use` allow(PR #14) | allow 삭제 | stable·beta 둘 다 **ok** ⇒ ★**깨져도 무해**(낡음 위험 없음) | +| ⑦ | `double_must_use` allow(PR #14) | ★**9곳 «전건» 삭제** | ★★**CI 만**(stable clippy **0** ↔ ★**beta clippy error 7**) | | ⑧ | 워크로그 잠금 스크립트 경로 | 스크립트 이동 | 로컬 DoD **와** CI 둘 다 잡는다(rc=2) | -⇒ ★**「아무것도 없음」 칸은 «1개»**(②)이고, 계약이 정한 대로 **1개면 조항이 아니라 «그 하나를 고치는 것»이 처방**이다. +⇒ ★★**「아무것도 없음」 칸은 «2개»(② · ⑦)다.** + +★★**[2026-09-04 정정 — 게이트② `request-changes`] 초판은 ⑦을 「깨져도 무해」로 적었고 그것은 «거짓»이다.** +근인은 ★**돌연변이를 «비하중» 자리에 넣은 것**이다 — 초판은 `jvm-bytecode/src/interpreter.rs:1` **한 곳**만 지웠는데 +그 크레이트 수준 attribute 는 **같은 파일의 함수별 `#[allow]` 에 가려진 «중복»**이고, `jvm/src/jvm.rs` 에 **7곳**이 그대로 남아 있었다. +★**세 갈래 재측정**(각 회 `cargo fmt --all` 로 삭제 artifact 정규화 후 · 2026-09-04): + +| 돌연변이 | stable clippy | ★**beta clippy** | +|---|---|---| +| ⓪ 무돌연변이(기준선) | 0 | **0** | +| ① `interpreter.rs:1` 만 삭제(★초판이 한 것) | 0 | **0** ← 초판 결과 재현됨 | +| ② `jvm.rs:2` 만 삭제(함수별 6 존치) | 0 | **0** | +| ★**③ 9곳 «전건» 삭제** | 0 | ★**error 7** | + +⇒ ★**「지워도 stable·beta 둘 다 통과한다」는 «중복 attribute 하나»에만 참이고 «자산»에는 «거짓»이다.** +★**⑦의 그물은 «beta clippy» 뿐이고, 그것이 로컬 DoD 에 없었으므로 «CI 만» — ② 와 «문자 그대로 같은 칸»이다.** +★★**그래서 「1개면 그 하나를 고쳐라」 규칙은 이 표에 적용되지 않는다 — 계수가 2다.** ★★**그리고 ② 는 «조용히» 실패하지도 않았다 — 그 정정이 처방을 더 좁혔다.** 낡은 이름으로 치면 cargo 가 ★**`warning: excluded package(s) 'test_utils' not found in workspace`** 를 찍고 **빌드가 깨진다**(rc≠0). ⇒ 문제는 «침묵»이 아니라 ★**«늦음»**이다(push 후 CI 에서만 난다). -⇒ ★**근인은 「자산 목록이 없다」가 아니라 ★«로컬 DoD 가 CI 검사 한 줄을 빠뜨렸다»**이다 — 그것을 고쳤다. +⇒ ★**근인은 「자산 목록이 없다」가 아니라 ★«로컬 DoD 가 CI 매트릭스를 재현하지 않는다»**이다. + +★★**[2026-09-04 정정 — 계수 2 위에서 논거를 다시 세운다] 결론은 같지만 «이유»가 다르다.** +초판 논거(「1개니까 그 하나를 고쳐라」)는 ★**계수 정정으로 무효**가 됐다. 새 논거는 이것이다: +- ★★**② 와 ⑦ 은 «다른 자산»이 아니라 «한 근인의 두 얼굴»이다** — ②는 **빠진 `- run:` 줄**(wasm32 **target** 축) · + ⑦은 **빠진 toolchain 축**(beta). ⇒ ★**근인 «하나»(DoD ≠ CI 매트릭스)를 고치면 «둘 다» 그물을 얻는다.** + ★**실측**: DoD 에 `cargo +beta clippy --all -- -D warnings` 를 넣자 ⑦의 9곳 전건 삭제가 + ★**로컬에서 error 7 로 잡힌다**(종전엔 CI 에서만 났다). +- ★**「조항이 «여럿»이면?」도 검토하고 기각한다** — 아래 사료 표대로 세 방향은 잡는 그물이 각각 다르므로 + 방향마다 조항을 두면 **셋**이 되고, 그중 둘(테스트·컴파일 축)은 ★**이미 기계가 지키는 자리에 사람 확인을 얹는 것**이다. +- ⇒ 계약이 준 규칙(「1개면 …」)은 **적용되지 않지만**, 그 «취지»(★**「자산 목록」이 아니라 «구멍»을 고쳐라**)는 + 계수 2 에서도 그대로 성립한다. ⇒ ★**구멍 «하나»(매트릭스 재현)를 고쳤다 — 축 두 개(target · toolchain)로.** ★**사료 — 「세 번」·「두 방향」은 확정하되, ★«한 조항으로 못 덮는다»가 결론이다**: @@ -225,24 +252,66 @@ upstream 은 여기서만 `UTF-8`/`EUC-KR` 하드코딩을 유지한다 ⇒ 그 | S8 | `rust.yml` 크레이트명 · `test_class_format.rs` 경로 4곳 | ⑶**개명** | ★CI 만 / 테스트 | ⇒ ★★**셋은 «같은 형태»가 아니다** — 잡는 그물이 각각 다르다(테스트·컴파일·CI). -★**그래서 조항 하나로 덮으려 하면 «이미 그물이 있는 다섯 자리»에까지 사람 확인을 얹게 된다** — 그것이 비용이다. +★**그래서 조항 하나로 덮으려 하면 «이미 그물이 있는 여섯 자리»에까지 사람 확인을 얹게 된다** — 그것이 비용이다. + +★★**[2026-09-04 정정 — C5] 「다섯」은 오기였다. 판정 시점 기준으로 «여섯»이 맞다.** 세는 법을 병기한다: +> 위 돌연변이 표에서 **★그물 칸이 「CI 만」이 «아닌» 행의 수**. +> **판정 시점(수리 전)**: 8행 − 「CI 만」 **2행**(② · ⑦) = ★**6** · **수리 후**: ★**8**(둘 다 로컬 그물을 얻었다). +```sh +# 표의 그물 칸을 센다(문서 실측 · 「CI 만」이 아닌 행) +sed -n '/^| # | 우리 자산/,/^$/p' docs/upstream-sync-approach.md \ +| /usr/bin/grep -c '^| [①-⑧]' ; \ +sed -n '/^| # | 우리 자산/,/^$/p' docs/upstream-sync-approach.md \ +| /usr/bin/grep -c 'CI 만' +``` -### ★★재개 조건 — «세는 법»과 «오늘의 값» +### ★★재개 조건 — «세는 법»과 «오늘의 값» (★**축이 «둘»이다**) -> ★**CI 가 치는 검사 중 로컬 DoD 에 없는 것이 «1건이라도» 생기면 이 결정을 다시 연다.** +> ★**CI 가 치는 것 중 로컬 DoD 에 없는 것이 «1건이라도» 생기면 이 결정을 다시 연다.** +> ★★**«치는 것»은 «줄»만이 아니라 «매트릭스 차원»도 포함한다** — 그래서 축이 둘이다. ```sh -# CI 검사 ∖ 로컬 DoD (0 이어야 한다) cd "$(git rev-parse --show-toplevel)" DOD=$(sed -n '/## Definition of Done/,/^- 착수·완료마다/p' CLAUDE.md) -LC_ALL=C /usr/bin/grep -E '^[[:space:]]+- run: ' .github/workflows/rust.yml | sed 's/^[[:space:]]*- run: //' | while IFS= read -r c; do printf '%s' "$DOD" | LC_ALL=C /usr/bin/grep -qF -- "$c" || echo "MISSING: $c"; done | /usr/bin/grep -c . + +# ★축① — CI 의 `- run:` 줄 ∖ 로컬 DoD (0 이어야 한다) +LC_ALL=C /usr/bin/grep -E '^[[:space:]]+- run: ' .github/workflows/rust.yml | sed 's/^[[:space:]]*- run: //' \ +| while IFS= read -r c; do printf '%s' "$DOD" | LC_ALL=C /usr/bin/grep -qF -- "$c" || echo "MISSING-RUN: $c"; done \ +| /usr/bin/grep -c . + +# ★축② — CI 의 toolchain 매트릭스 ∖ 로컬 DoD (0 이어야 한다) +LC_ALL=C /usr/bin/grep -E '^[[:space:]]+rust: \[' .github/workflows/rust.yml \ +| sed 's/.*\[//; s/\].*//; s/, */\n/g' \ +| while IFS= read -r tc; do + [ "$tc" = stable ] && { printf '%s' "$DOD" | LC_ALL=C /usr/bin/grep -qE 'cargo (fmt|clippy|test)' || echo "MISSING-TC: $tc"; continue; } + printf '%s' "$DOD" | LC_ALL=C /usr/bin/grep -qF -- "cargo +$tc " || echo "MISSING-TC: $tc" + done | /usr/bin/grep -c . ``` -★**오늘의 값 = 0**(2026-09-04 · 이 회차가 5 → 0 으로 만들었다). -★**이 수가 «1 이상»이 되면**: 그 빠진 검사가 다시 「로컬에서 안 잡히는 자산」을 만들 수 있으므로 -**⑴그 줄을 DoD 에 넣거나 ⑵넣을 수 없는 이유를 적고 이 결정을 재검토**하라. +★**오늘의 값**(2026-09-04 정정 후): **축① `0`** · **축② `0`**. +※착수 시엔 **축① 5 · 축② 1**(beta 가 DoD 에 없었다) — 축①은 원 회차가, 축②는 정정 회차가 0 으로 만들었다. + +★★**축②를 왜 따로 두는가 — 축① 만으로는 «구조적으로» 못 본다.** 실측(정정 회차): + +| 워크플로 돌연변이 | 축① | 축② | ★옳은 값인가 | +|---|---|---|---| +| ⓪ 무돌연변이 | **0** | **0** | ✔ | +| ① `rust: [stable, beta]` → `[stable]`(CI 가 beta 를 **버림**) | 0 | **0** | ✔ ★**0 이 «옳다»** — 술어가 `CI ∖ DoD` 라 **DoD 가 더 엄격한 것은 «구멍»이 아니다**(로컬이 CI 보다 한 축 더 돌 뿐) | +| ② → `[stable, beta, nightly]`(CI 가 **늘림**) | 0 | ★**1** | ✔ **축②만** 반응 | +| ③ `- run: cargo doc --no-deps` 1줄 추가 | ★**1** | 0 | ✔ **축①만** 반응 | + +⇒ ★**①이 0 인 것을 «검사가 안 듣는다»로 읽지 마라** — 그 방향은 애초에 재개 사유가 아니다. +★**②·③ 이 각각 «자기 축»에서만 1 을 내는 것**이 두 축이 «겹치지 않고 덮는다»는 증거다. + +★**1 이상이 되면**: ⑴그 줄/축을 DoD 에 넣거나 ⑵넣을 수 없는 이유를 적고 **이 결정을 재검토**하라. ★**「조항이 필요하다」로 바로 가지 마라 — 그때도 «먼저 세라»**(위 돌연변이 표를 다시 만들면 된다). +★★**[C7 고지 — 이 처방이 «못 잡는» 것]** +⒜**DoD 블록 자체의 개악은 자동으로 안 잡힌다** — 누가 그 블록에서 한 줄을 지우면 축①이 **1** 이 되지만, +★**그 축을 «돌리는 것»이 사람이다.** 기계 강제(DoD ↔ `rust.yml` 대조 CI job)는 이 회차 범위 밖이고, +★**고칠 수 없으면 «고지»가 처방이다.** ⇒ ★**이 절을 읽는 회차는 「축①·축②를 «실제로 돌렸는가»」를 회신에 적어라.** +⒝★**OS 축(macos·ubuntu·windows 3종)은 로컬에서 재현할 수 없다** — 그 차원은 ★**CI 가 «유일한» 그물**이고 +대조 대상이 아니다. **결함이 아니라 «알고 두는» 값이다.** ## 5. 단계 분할 — ★**커밋 수로 자르지 마라. 충돌은 앞쪽 7커밋에 몰려 있다** diff --git a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json index 6462f2d9..7c900624 100644 --- a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json +++ b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json @@ -6,10 +6,10 @@ "RustJava" ], "taskId": "rustjava-sync-contract-standing-clause-for-our-assets-going-stale", - "summary": "운영자 채택 제안 둘(2026-09-04-upstream-sync-s6#p1 · …-s7#p1)에 대한 결정이다. 결론: 동기 회차 계약에 「우리 자산 서술자 목록을 문서화하고 머지 후 재확인한다」 상시 조항을 넣지 않는다. 대신 그물이 없던 자리 하나를 막았다 — CLAUDE.md §Definition of Done 이 이제 CI 명령 5줄을 축약 없이 그대로 싣는다. 목록 문서화로 시작하지 않고 먼저 셌다: 우리 자산 8건을 돌연변이로 깨뜨려 무엇이 잡는지 실측했고(경로 문자열·setProperty 서술자·charset 라우팅·ClassFormatError 종류 단정은 cargo test RED · 수동 span 은 clippy RED · double_must_use allow 는 stable·beta 둘 다 ok 라 깨져도 무해 · 워크로그 스크립트는 로컬 DoD 와 CI 둘 다), 「아무것도 없음」 칸이 1개(CI 워크플로의 --exclude 크레이트 이름)였다. 계약이 정한 대로 1개면 조항이 아니라 그 하나를 고치는 것이 처방이다. 그리고 그 1개도 조용히 실패하지 않는다 — cargo 가 warning: excluded package(s) not found 를 찍고 빌드가 깨진다 ⇒ 문제는 침묵이 아니라 늦음이고, 근인은 「자산 목록이 없다」가 아니라 「로컬 DoD 가 CI 검사 5종 중 wasm32 clippy 한 줄을 빠뜨렸다」였다. 그 줄이 --exclude 크레이트 이름이 사는 유일한 자리다.", + "summary": "운영자 채택 제안 둘(2026-09-04-upstream-sync-s6#p1 · …-s7#p1)에 대한 결정이다. 결론: 동기 회차 계약에 「우리 자산 서술자 목록을 문서화하고 머지 후 재확인한다」 상시 조항을 넣지 않는다. 대신 그물이 없던 자리 하나를 막았다 — CLAUDE.md §Definition of Done 이 이제 CI 명령 5줄을 축약 없이 그대로 싣는다. 목록 문서화로 시작하지 않고 먼저 셌다: 우리 자산 8건을 돌연변이로 깨뜨려 무엇이 잡는지 실측했고(경로 문자열·setProperty 서술자·charset 라우팅·ClassFormatError 종류 단정은 cargo test RED · 수동 span 은 clippy RED · double_must_use allow 는 stable·beta 둘 다 ok 라 깨져도 무해 · 워크로그 스크립트는 로컬 DoD 와 CI 둘 다), ★[게이트② request-changes 정정] 「아무것도 없음」 칸은 1개가 아니라 «2개»다 — ② CI 워크플로의 --exclude 크레이트 이름 · ⑦ double_must_use allow. 초판이 ⑦을 「깨져도 무해」로 적은 것은 돌연변이를 «비하중» 자리(중복 crate-level attribute 한 곳)에 넣었기 때문이고, 9곳 전건 삭제로 재측정하면 stable 0 · beta error 7 이다 ⇒ ⑦의 그물도 «CI 만»이다. 계수가 2 라 「1개면 그 하나를 고쳐라」 규칙은 적용되지 않는다. 그리고 그 1개도 조용히 실패하지 않는다 — cargo 가 warning: excluded package(s) not found 를 찍고 빌드가 깨진다 ⇒ 문제는 침묵이 아니라 늦음이고, 근인은 「자산 목록이 없다」가 아니라 「로컬 DoD 가 CI 검사 5종 중 wasm32 clippy 한 줄을 빠뜨렸다」였다. 그 줄이 --exclude 크레이트 이름이 사는 유일한 자리다. ★결론은 그대로 「조항을 넣지 않는다」이나 논거를 다시 세웠다: ②와 ⑦은 다른 자산이 아니라 «한 근인의 두 얼굴»이다 — ②는 빠진 - run: 줄(target 축) · ⑦은 빠진 toolchain 축(beta) ⇒ 근인 하나(로컬 DoD 가 CI 매트릭스를 재현하지 않는다)를 고치면 둘 다 그물을 얻는다. DoD 에 cargo +beta clippy 를 넣자 ⑦의 9곳 전건 삭제가 로컬에서 error 7 로 잡힌다. 재개 조건도 축을 둘로 늘렸다(줄 문자열 축 + 매트릭스 차원 축) — 종전 명령은 rust: [stable, beta] 를 [stable] 로 줄여도 [stable, beta, nightly] 로 늘려도 0 을 냈다.", "changes": [ - "CLAUDE.md §Definition of Done — CI(rust.yml)가 치는 5줄을 축약 없이 그대로 싣도록 교체 + 「축약본을 쓰지 마라」와 그 이유(2026-09-04 S8 실사고: wasm32 줄이 빠져 있어 test_utils→test-utils 개명이 로컬에서 안 드러나고 CI 에서만 red 였다) + 「CI 가 검사를 늘리거나 인자를 바꾸면 이 블록도 같이 고쳐라」.", - "docs/upstream-sync-approach.md §4 뒤 — 「[2026-09-04 결정] 「우리 자산이 낡는다」」 절 신설: 결정문 · 돌연변이 표 8건(무엇이 잡는가) · 「아무것도 없음 1개」 · 「조용히가 아니라 늦음」 정정 · 사료 표(S3·S5·S6=⑴ / S7=⑵ / S8=⑶ · 셋은 같은 형태가 아니다) · 재개 조건과 세는 명령과 오늘의 값.", + "CLAUDE.md §Definition of Done — CI 가 치는 명령을 5줄 → ★6줄로(cargo +beta clippy --all -- -D warnings 추가). CI 는 이 검사를 6셀(toolchain 2 × OS 3)로 치는데 repo 에 rust-toolchain.toml 이 없어 맨 cargo 는 stable 1개로만 돈다 — toolchain 축을 안 적으면 「rust.yml 이 치는 그대로」가 거짓이 된다. 실측 근거(9곳 전건 삭제 시 stable 0 · beta error 7)와 OS 축은 로컬 재현 불가라 CI 가 유일한 그물이라는 고지를 함께 넣었다.", + "docs/upstream-sync-approach.md §4 결정 절 — ⑦행 라벨을 「깨져도 무해」에서 ★「CI 만」으로 정정(세 갈래 재측정 표 첨부) · 계수 1 → ★2 · 결정 논거 재구성(둘은 한 근인의 두 얼굴 · 「조항이 여럿이면?」 기각) · 재개 조건에 ★축② 「매트릭스 차원 대조」 추가 · 비용 논거의 수를 「다섯」 → ★「여섯」으로 통일하고 세는 명령 병기.", "STATE.md · REPORT.md · docs/worklog/2026-09-04-sync-contract-stale-assets-decision.{md,json} 갱신·신설.", "★.github/workflows/rust.yml 은 무접촉 — 크레이트 이름 1건은 S8 회차가 이미 고쳐 착지시켰다." ], @@ -19,12 +19,14 @@ }, "verification": "착수 실측: origin/main a76b305 · behind 0 · 열린 PR 0. 계약1⒝ 돌연변이(각각 깨뜨린 뒤 build/clippy/test 를 돌리고 원상 복구): ① tests/test_class_format.rs 의 test-data/ → test_data/ ⇒ build ok · clippy ok · test RED. ③ system.rs 의 setProperty 서술자 String → Object ⇒ test RED. ④ string.rs 의 Charset::resolve → from_name().unwrap() 우회 ⇒ test RED. ⑤ thread.rs 의 .instrument(span) 삭제 ⇒ clippy RED(미사용 import). ⑥ test_class_format.rs 의 ClassFormatError → Throwable ⇒ test RED. ⑦ jvm-bytecode/src/interpreter.rs 의 #[allow(clippy::double_must_use)] 삭제 ⇒ stable clippy ok · beta clippy 도 ok(깨져도 무해). ② cargo clippy --workspace --exclude test_utils --target wasm32-unknown-unknown ⇒ rc=101 이고 문면은 warning: excluded package(s) `test_utils` not found in workspace + tokio wasm 컴파일 실패(조용한 통과가 아니다) · 로컬 4종 중 어느 것도 그 인자를 쓰지 않는다. ⑧ scripts/check-worklog-json.py 이동 ⇒ rc=2(로컬 DoD 와 CI 둘 다 그 경로를 친다). 근인 대조: rust.yml 의 - run: 줄 5개 ↔ CLAUDE.md DoD 4개 ⇒ 차집합이 정확히 wasm32 clippy 한 줄. 재개 조건 세는 명령(회신·§4 동일)의 값: 착수 시 5 → 착지본 0. 계약6: CI 5줄을 워크플로 문면 그대로 실행해 전건 rc=0 · cargo test --all = 554 passed / 0 failed / 1 ignored(baseline 554/0/1 동수 · 새 red 0). 돌연변이 전부 복구 확인(git status 가 문서 2파일만). 계약5: .github/workflows/rust.yml:55 이 이미 --exclude test-utils 이므로 이 회차는 무접촉.", "issues": [ - "★★결정은 「조항을 넣지 않는다」이고, 그 근거는 «수»다 — 「아무것도 없음」이 1개였다. 그 1개가 2개 이상이 되면 결론이 달라질 수 있으므로 재개 조건과 세는 명령을 §4 에 박았다(오늘의 값 0).", + "★★[게이트② request-changes 정정] 초판의 계수 「1」은 틀렸다 — 「아무것도 없음」은 «2개»(② · ⑦)다. 근인은 돌연변이를 비하중 자리에 넣은 것이고(중복 crate-level attribute 한 곳만 삭제), 9곳 전건 삭제로 재측정하면 beta error 7 이다. ★그리고 그 차를 놓친 «같은 근인»이 하나 더 있었다: 브리프가 「제안 2 ↔ 검수 1」의 차를 해소하라고 요구했는데 초판이 그것을 안 짚었다 — 이제 답이 나왔다: ★«2»가 맞다.", "★이 결정이 «막는» 것은 「우리 자산이 낡는 것」 자체가 아니라 「그것이 로컬에서 안 드러나고 CI 에서만 드러나는 것」이다. 낡음 자체는 여전히 일어나고, 다만 여섯 자리는 기계가(테스트·컴파일·clippy) 이미 잡는다.", "★잡는 그물이 축마다 다르다(테스트/컴파일/CI)는 것이 「조항 하나로 못 덮는다」의 근거다 — 조항으로 덮으면 이미 그물이 있는 다섯 자리에까지 사람 확인을 얹게 된다.", - "★double_must_use allow(PR #14)는 이제 지워도 stable·beta 둘 다 통과한다 — upstream 변경으로 불필요해졌을 수 있다. 이 회차는 포크 정책을 바꾸지 않으므로 «건드리지 않았다»(별건 판정 대상).", "★S8 이 고친 CI 크레이트 이름 1건과 이 회차의 산출은 «다른 층»이다: 전자는 증상 1건, 후자는 그 증상이 늦게 드러난 경로. 티켓이 「고쳤다고 조항 결정을 건너뛰지 마라」고 못박은 자리다.", - "머지하지 않았다 — 게이트②·③은 별 세션이다. ★게이트③은 등재 repo 라 merge_strategy: merge 필수(bin/queue-lint 검사22). upstream 동기 회차를 새로 열지 않았다(behind 0 · S9 없음)." + "머지하지 않았다 — 게이트②·③은 별 세션이다. ★게이트③은 등재 repo 라 merge_strategy: merge 필수(bin/queue-lint 검사22). upstream 동기 회차를 새로 열지 않았다(behind 0 · S9 없음).", + "★★[C1 승계 철회] 초판 후속 추천 3번(「double_must_use allow 가 이제 지워도 통과한다 — 정리할지는 별건」)을 «철회한다». 그 문장은 비하중 돌연변이에서 나온 것이고, 9곳을 전건 지우면 beta clippy 가 error 7 로 red 다. ★그대로 두면 다음 회차가 그 문장을 근거로 allow 를 지우고 beta 3셀을 빨갛게 만든다 ⇒ ★allow 9곳을 지우지 마라.", + "★[C7 고지] ⑸ⓐ 처방(DoD 가 CI 명령을 verbatim 싣는 것)의 «개악»을 자동으로 잡는 것은 없다 — 누군가 DoD 블록에서 한 줄을 지우면 재개 조건 축①이 1 이 되지만, 그 축을 «돌리는 것»이 사람이다. ★기계 강제(예: DoD 블록과 rust.yml 을 대조하는 CI job)는 이 회차 범위 밖이고, 고칠 수 없으면 «고지»가 처방이다 ⇒ 여기 적는다.", + "★[C7 고지 2] OS 축(macos·ubuntu·windows 3종)은 로컬에서 재현할 수 없다 — 그 차원은 CI 가 유일한 그물이고 재개 조건 대조의 대상이 아니다. 이것은 결함이 아니라 «알고 두는» 값이다." ], "proposals": [ { @@ -40,7 +42,8 @@ "resolvedIssues": [], "adoptedProposals": [ "2026-09-04-upstream-sync-s6#p1", - "2026-09-04-upstream-sync-s7#p1" + "2026-09-04-upstream-sync-s7#p1", + "2026-09-04-upstream-sync-s8#p0" ], "declinedProposals": [] } diff --git a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md index c6b1da5d..793d94c2 100644 --- a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md +++ b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md @@ -19,13 +19,24 @@ | ④ | charset 라우팅(PR #5) | `Charset::resolve` → 폴백 우회 | ok | ok | ★**RED** | 있음 | | ⑤ | 수동 span(PR #4) | `.instrument(span)` 삭제 | ok | ★**RED** | ok | 있음 | | ⑥ | `ClassFormatError` 종류 단정(PR #3) | `ClassFormatError` → `Throwable` | ok | ok | ★**RED** | 있음 | -| ⑦ | `double_must_use` allow(PR #14) | allow 삭제 | ok | ok(★beta 도 ok) | ok | ★**해당 없음 — 깨져도 무해** | +| ⑦ | `double_must_use` allow(PR #14) | ★**9곳 «전건» 삭제** | ok | ★**beta RED**(error 7) | ok | ★★**없음 — CI 만**(② 와 같은 칸) | | ⑧ | 워크로그 잠금 스크립트 경로(PR #15) | 스크립트 이동 | — | — | — | 있음(로컬 DoD **와** CI 둘 다 · rc=2) | -★**⑦은 「그물 없음」이 아니라 「위험 없음」이다** — allow 를 지워도 stable·beta 둘 다 통과한다 -(upstream 이 그 자리를 바꿔 allow 가 불필요해졌다). ⇒ 낡아도 아무것도 깨지지 않으므로 이 결정의 대상이 아니다. +★★**[2026-09-04 정정 — 게이트② `request-changes`] 초판의 ⑦행 「깨져도 무해」는 «거짓»이다.** +근인은 ★**돌연변이를 «비하중» 자리에 넣은 것**이다 — 초판은 `interpreter.rs:1` **한 곳**만 지웠는데 +그것은 **같은 파일 함수별 `#[allow]` 에 가려진 «중복»**이고 `jvm/src/jvm.rs` 에 **7곳**이 그대로 남아 있었다. +★**세 갈래 재측정**(각 회 `cargo fmt --all` 정규화 후): -⇒ ★★**「아무것도 없음」 칸은 «1개»(②)다.** +| 돌연변이 | stable | ★beta | +|---|---|---| +| ⓪ 무돌연변이 | 0 | **0** | +| ① `interpreter.rs:1` 만(★초판) | 0 | **0** ← 초판 결과 재현됨 | +| ② `jvm.rs:2` 만(함수별 6 존치) | 0 | **0** | +| ★③ **9곳 전건** | 0 | ★**error 7** | + +⇒ ★**⑦의 그물은 «beta clippy» 뿐이고 그것이 로컬 DoD 에 없었으므로 «CI 만» — ② 와 같은 칸이다.** + +⇒ ★★**「아무것도 없음」 칸은 «2개»(② · ⑦)다.** ## 2. ★★그 1개도 «조용히» 실패하지 않는다 — 그 정정이 처방을 더 좁혔다 @@ -71,8 +82,12 @@ error: could not compile `tokio` (lib) due to 1 previous error ← rc≠0 > ★**동기 회차 계약에 「우리 자산 서술자 목록을 문서화하고 머지 후 재확인한다」 상시 조항을 «넣지 않는다».** > ★**대신 «그물이 없던 자리 하나»를 막는다 — `CLAUDE.md` §Definition of Done 이 CI 명령 5줄을 «축약 없이 그대로» 싣는다.** -**⒜ 왜 이것이 «가장 좁은» 형태인가**: -- 계약 자체가 정했다 — 「**1개면 계약 조항이 아니라 «그 하나를 고치는 것»이 처방**」. +**⒜ ★계수가 «2»인데도 왜 여전히 조항이 아닌가**(★초판 논거 「1개니까」는 계수 정정으로 **무효** — 결론은 같고 이유가 다르다): +- ★★**② 와 ⑦ 은 «다른 자산»이 아니라 «한 근인의 두 얼굴»이다 — «로컬 DoD 가 CI 매트릭스를 재현하지 않는다».** + ②는 빠진 `- run:` 줄(**target** 축) · ⑦은 빠진 **toolchain** 축(beta). + ⇒ ★**근인 하나를 고치면 둘 다 그물을 얻는다**(실측: DoD 에 `+beta` 를 넣자 ⑦이 로컬에서 error 7 로 잡힌다). +- ★**「조항이 «여럿»이면?」도 기각한다** — 세 방향은 잡는 그물이 각각 달라 조항이 셋이 되고, + 그중 둘은 ★**이미 기계가 지키는 자리에 사람 확인을 얹는 것**이다. - ★**사람 기억에 맡기지 않는다** — 추가한 것은 «체크리스트 항목»이 아니라 ★**실제로 도는 명령**이다. 회차가 DoD 를 돌리면 **cargo 가 스스로 낡음을 말한다**(`excluded package(s) … not found`). - ★**목록을 만들지 않았다** — 목록은 사람이 유지해야 하고, 위 표대로 **여섯 자리는 이미 기계가 지킨다**. @@ -97,10 +112,12 @@ LC_ALL=C /usr/bin/grep -E '^[[:space:]]+- run: ' .github/workflows/rust.yml | se | | 값 | |---|---| -| 착수 시 | ★**5**(DoD 가 축약본이라 CI 5줄 «전건»이 문자열로 안 맞았고, 그중 wasm32 는 **의미로도** 없었다) | -| ★**오늘(착지본)** | ★**0** | +| 착수 시 | 축① ★**5** · 축② ★**1**(beta 축이 DoD 에 없었다) | +| ★**오늘(정정 후)** | 축① ★**0** · 축② ★**0** | -★**1 이상이 되면**: ⑴그 줄을 DoD 에 넣거나 ⑵넣을 수 없는 이유를 적고 **이 결정을 재검토**하라. +★**두 축을 «둘 다» 세라 — 하나만 0 이면 나머지 차원이 조용히 빠진다**(그것이 ⑦이 CI 에서만 났던 이유다). +★**1 이상이 되면**: ⑴그 줄/축을 DoD 에 넣거나 ⑵넣을 수 없는 이유를 적고 **이 결정을 재검토**하라. +★**OS 축(3종)은 로컬 재현 불가라 대조 대상이 아니다** — ★그 차원은 **CI 가 유일한 그물**이고 «알고 두는» 값이다. ★**「조항이 필요하다」로 바로 가지 마라 — 그때도 «먼저 세라»**(위 §1 돌연변이 표를 다시 만들면 된다). ## 6. 계약 5 — CI 크레이트 이름 1건은 ★**이미 고쳐져 있었다** From 435b904fd77b283c022756e251e6ad01259832b6 Mon Sep 17 00:00:00 2001 From: jun0 Date: Fri, 4 Sep 2026 15:54:25 +0900 Subject: [PATCH 3/5] =?UTF-8?q?docs:=20=E3=80=8C=EA=B3=A0=EC=B3=A4?= =?UTF-8?q?=EB=8B=A4=EA=B3=A0=20=EC=8B=A0=EA=B3=A0=ED=95=9C=20=EA=B2=83?= =?UTF-8?q?=E3=80=8D=EC=9D=84=20=EC=82=B0=EC=B6=9C=EB=AC=BC=EA=B3=BC=20?= =?UTF-8?q?=EC=A0=84=EC=88=98=20=EB=8F=99=EA=B8=B0=20=E2=80=94=20=E3=80=8C?= =?UTF-8?q?=EB=8B=A4=EC=84=AF=E3=80=8D=203=EC=9E=90=EB=A6=AC=20=C2=B7=20ve?= =?UTF-8?q?rification=20=ED=95=84=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 게이트② request-changes(C1·C2) 승계. 본체(계수 2 · 근인 하나 · 축 둘 · 결론) 무접촉. C1 — 「다섯 → 여섯」이 4자리 중 1자리만 됐다. 나머지 3자리(REPORT.md · 워크로그 .md · .json issues[2])를 여섯으로 통일하고 세는 법(8행 − 「CI 만」 2행 = 6)을 병기. 두 파일 안의 자기모순(.md:78↔:93 · json issues[2]↔issues[1])도 닫았다. C2 — 워크로그 .json verification 이 diff 에 한 줄도 없이 철회된 라벨(「beta 도 ok — 깨져도 무해」)을 실은 채였다. ⑦ 정정 표지(다른 4파일과 같은 형식) · 근인 대조를 축 둘로 · 축② 착수값 1 · cargo +beta clippy 실행 기록을 넣었다. 전문 검색이 반려 밖에서 더 찾은 것: 「CI 명령 5줄」 파생 수 6자리 · 워크로그 재개 조건 코드블록이 축① 만 실은 것 · 워크로그 검증 표에 +beta 행이 없던 것. 전건 동기. 규율: 「고쳤다」를 쓰기 전에 세라 — 마감 절차 3줄을 approach.md §4 에 박았다. 검증: DoD 6줄 전건 rc=0 · cargo test --all 554/0/1(새 red 0) · 축① 0 · 축② 0 · .rs 변경 0 · allow 9곳 무접촉. [rustjava-sync-contract-standing-clause-for-our-assets-going-stale] --- REPORT.md | 19 +++++++----- STATE.md | 11 +++++-- docs/upstream-sync-approach.md | 21 +++++++++++-- ...4-sync-contract-stale-assets-decision.json | 11 +++---- ...-04-sync-contract-stale-assets-decision.md | 30 +++++++++++++++---- 5 files changed, 71 insertions(+), 21 deletions(-) diff --git a/REPORT.md b/REPORT.md index 120453ef..59a527c7 100644 --- a/REPORT.md +++ b/REPORT.md @@ -2,9 +2,12 @@ ## [2026-09-04] 「우리 자산이 낡는다」 상시 조항 판정 — 넣지 않고 «구멍 하나»를 막았다 (rustjava-sync-contract-standing-clause-for-our-assets-going-stale) - 무엇을: 운영자 채택 제안 둘(`2026-09-04-upstream-sync-s6#p1`·`…-s7#p1`)에 대한 **결정**이다. - ★**결론: 상시 조항을 «넣지 않는다».** 대신 ★**로컬 DoD 가 CI 검사 5종 중 «wasm32 clippy» 한 줄을 - 빠뜨리고 있던 것**을 고쳤다 — `CLAUDE.md` DoD 가 이제 **CI 명령 5줄을 축약 없이 그대로** 싣는다. - ★**코드 변경 0 · 문서 2파일**(`CLAUDE.md` · `docs/upstream-sync-approach.md`). + ★**결론: 상시 조항을 «넣지 않는다».** 대신 ★**로컬 DoD 가 CI 의 «매트릭스»를 재현하지 않던 것**을 고쳤다 — + `CLAUDE.md` DoD 가 이제 **CI 명령 5줄 + toolchain 축 1줄 = «6줄»**을 축약 없이 싣는다. + ★**코드(`.rs`) 변경 0** · 규범 문서 **2파일**(`CLAUDE.md` · `docs/upstream-sync-approach.md`) + 기록 문서 4 + (`REPORT.md` · `STATE.md` · 워크로그 `.md`/`.json`). + ★**[게이트② 정정] 초판은 「CI 검사 5종 중 wasm32 clippy 한 줄」이라 적었다** — 계수 «1» 시절 문면이고, + 계수 **2** 정정 후에는 **두 축**(target · toolchain)이라 DoD 도 **6줄**이다. - 왜: ★**목록 문서화로 시작하지 않고 «먼저 셌다»**(티켓이 그렇게 요구했다). 우리 자산 **8건**을 ★**돌연변이로 깨뜨려** 무엇이 잡는지 실측했다 — 경로 문자열·`setProperty` 서술자·charset 라우팅· `ClassFormatError` 종류 단정은 **`cargo test` RED**, 수동 span 은 **clippy RED**, @@ -18,14 +21,16 @@ ②는 빠진 `- run:` 줄(**target** 축) · ⑦은 빠진 **toolchain** 축(beta) ⇒ ★**한 근인의 두 얼굴**이다. ⇒ ★**결론은 그대로 「넣지 않는다」이나 논거가 바뀌었다**: 근인 하나를 고치면 둘 다 그물을 얻는다 (DoD 에 `cargo +beta clippy` 를 넣자 ⑦이 **로컬에서 error 7** 로 잡힌다 · 실측). -- 사용자 영향: 런타임 동작 **무변경**. 회차가 로컬에서 CI 와 **같은 5줄**을 돌리게 되어 +- 사용자 영향: 런타임 동작 **무변경**. 회차가 로컬에서 CI 와 **같은 6줄**(★**toolchain 축 포함**)을 돌리게 되어 ★**「로컬 green 인데 CI red」 부류가 이 축에서 사라진다**(S5·S7·S8 이 실제로 그 부류였다). -- 검증: CI 5줄을 **워크플로 문면 그대로** 실행 — 전건 **rc=0** · `cargo test --all` **554 / 0 / 1**(baseline 동수 · 새 red 0). - ★**돌연변이는 전부 복구**했고 워킹트리는 문서 2파일만 바뀌었다. +- 검증: **DoD 6줄을 문면 그대로** 실행 — 전건 **rc=0**(★`cargo +beta clippy --all -- -D warnings` **rc=0** 포함) · + `cargo test --all` **554 / 0 / 1**(baseline 동수 · 새 red 0). ★**돌연변이는 전부 복구**했고 `.rs` 변경은 **0**이다. - ★★**사료 — 「세 번」·「두 방향」을 확정하되 결론은 «한 조항으로 못 덮는다»**: S3(문구 단정 3건 · 테스트) · S5(io 5곳 · 테스트) · S6(regex 3곳 · 정독) = **⑴신규/판본 교체** · S7(우리 테스트 5곳 · **컴파일**) = **⑵공용 API 변경** · S8(`rust.yml`·경로 4곳 · **CI만/테스트**) = **⑶개명**. - ⇒ ★**잡는 그물이 각각 다르므로**, 조항 하나로 덮으면 **이미 그물이 있는 다섯 자리에까지 사람 확인을 얹게 된다**. + ⇒ ★**잡는 그물이 각각 다르므로**, 조항 하나로 덮으면 **이미 그물이 있는 여섯 자리에까지 사람 확인을 얹게 된다** + (★**세는 법**: 돌연변이 표 **8행** − 그물이 「CI 만」인 **2행**(② · ⑦) = **6** · 명령은 `docs/upstream-sync-approach.md` §4. + ★**[게이트② 정정] 초판의 「다섯」은 계수 «1» 시절의 파생 수였다** — 계수가 2 가 되며 **6**이 맞다). - ★★**재개 조건**(결정에 재개 조건이 없으면 «영구 종결»로 읽힌다): 「**CI 가 치는 검사 중 로컬 DoD 에 없는 것이 1건이라도 생기면 다시 연다**」 · ★**세는 명령을 `docs/upstream-sync-approach.md` §4 에 박았고, 정정으로 «축이 둘»이 됐다** diff --git a/STATE.md b/STATE.md index 8b9c2083..f0b5f65d 100644 --- a/STATE.md +++ b/STATE.md @@ -2,7 +2,8 @@ ## 진행중 - [rustjava-sync-contract-standing-clause-for-our-assets-going-stale] ★**「우리 자산이 낡는다」 상시 조항 - «판정» — 결론: ★★넣지 «않는다». 대신 «그물이 없던 자리 하나»를 막았다.** ★코드 변경 0 · 문서 2파일. + «판정» — 결론: ★★넣지 «않는다». 대신 «구멍 하나»(로컬 DoD 가 CI 매트릭스를 재현하지 않던 것)를 막았다.** + ★코드(`.rs`) 변경 0 · 규범 문서 2 + 기록 문서 4. ★**먼저 셌다(목록 문서화로 시작하지 않았다)**: 자산 8건을 **돌연변이로 깨뜨려** 무엇이 잡는지 쟀다 — 경로 문자열·`setProperty` 서술자·charset 라우팅·`ClassFormatError` 단정은 **`cargo test` RED** · 수동 span 은 **clippy RED** · `double_must_use` allow 는 **깨져도 무해** · 워크로그 스크립트는 **로컬+CI 둘 다**. @@ -13,11 +14,17 @@ ★**로컬 DoD 가 CI «매트릭스»를 재현하지 않는다**(② = 빠진 `- run:` 줄 = target 축 · ⑦ = 빠진 toolchain 축). ⇒ 근인 하나를 고치니 둘 다 그물을 얻었다(DoD 에 `cargo +beta clippy` 추가 ⇒ ⑦이 **로컬에서 error 7** 로 잡힌다). ★★**근인은 「자산 목록이 없다」가 아니었다** — ★**로컬 DoD 가 CI 검사 5종 중 «wasm32 clippy» 한 줄을 빠뜨렸고** - 그 줄이 그 자산이 사는 **유일한 자리**다. ⇒ `CLAUDE.md` DoD 가 이제 **CI 명령 5줄을 축약 없이 그대로** 싣는다. + 그 줄이 그 자산이 사는 **유일한 자리**다. ⇒ `CLAUDE.md` DoD 가 이제 ★**CI 명령 5줄 + toolchain 축 1줄 = «6줄»**을 + 축약 없이 싣는다(★**[게이트② 정정] 「5줄」은 계수 «1» 시절 수다 — 빠진 것은 «줄 하나»가 아니라 «두 축»이었다**). ★그리고 ②는 «조용히» 실패하지도 않는다(`excluded package(s) not found` + 빌드 실패) ⇒ 문제는 침묵이 아니라 **늦음**이다. ★**재개 조건은 «축 둘»이다**(정정): **축① `- run:` 줄** · ★**축② toolchain 매트릭스** — 세는 명령 둘 다 §4 에 박았다. ★**오늘의 값 = 축① 0 · 축② 0**(착수 시 축① **5** · 축② **1**). ★세 돌연변이(beta 제거·nightly 추가·`- run:` 추가)로 ★**각 축이 «자기 자리»에서만 반응함을 실측**했다. ★**C7 고지**: DoD 블록 «개악»과 **OS 축 3종**은 이 대조가 못 잡는다. + ⇒ ★★**[게이트② 2차 정정 · fix2] 「고쳤다고 «신고»한 것이 산출물에 남아 있었다」 — 두 건.** + ⑴「다섯 → 여섯」 통일이 ★**4자리 중 1자리**만 됐다 ⑵워크로그 `.json` `verification` 이 ★**diff 에 한 줄도 없이** + 철회된 라벨(「beta 도 ok — 깨져도 무해」)을 «검증 기록» 필드에 그대로 싣고 있었다. + ★**전문 검색으로 반려 밖에서 «더» 찾았다**: 「CI 명령 5줄」 파생 수 **6자리** · 워크로그 재개 조건 블록이 + «축① 만» 실은 것 · 워크로그 검증 표에 `+beta` 행이 없던 것. ⇒ ★**전건 동기 + 마감 절차 3줄을 §4 에 규율로 박았다.** **PR 대기 — 게이트③ 미착지.** - [rustjava-upstream-sync-squash-defeats-convergence] ★**S1~S4 가 착지하고도 fork 가 upstream 에 한 걸음도 가까워지지 않은 근인을 확정하고 계보를 기록했다.** 근인 = 게이트③ 제품 repo **`--squash`**. diff --git a/docs/upstream-sync-approach.md b/docs/upstream-sync-approach.md index e9f669c1..0b7301ab 100644 --- a/docs/upstream-sync-approach.md +++ b/docs/upstream-sync-approach.md @@ -191,8 +191,13 @@ upstream 은 여기서만 `UTF-8`/`EUC-KR` 하드코딩을 유지한다 ⇒ 그 **결정문**: > ★**동기 회차 계약에 「우리 자산 서술자 목록을 문서화하고 머지 후 재확인한다」 상시 조항을 «넣지 않는다».** -> ★**대신 «그물이 없던 자리 «하나»»를 막는다 — 로컬 DoD 가 CI 검사 5종 중 «wasm32 clippy» 한 줄을 빠뜨리고 있었다.** -> ⇒ `CLAUDE.md` §Definition of Done 이 이제 **CI 명령 5줄을 «축약 없이 그대로»** 싣는다. +> ★**대신 «구멍 하나»를 막는다 — 로컬 DoD 가 CI 의 «매트릭스»를 재현하지 않았다.** +> ⇒ `CLAUDE.md` §Definition of Done 이 이제 **CI 명령 5줄 + toolchain 축 1줄 = «6줄»**을 축약 없이 싣는다. + +★**[2026-09-04 정정 — 게이트② `request-changes`] 위 결정문의 초판은 「그물이 없던 자리 «하나» — CI 검사 5종 중 +wasm32 clippy 한 줄」이었다.** 그것은 ★**계수 «1» 시절의 문면**이고, 계수가 **2**로 정정된 지금은 **낡았다**: +빠진 것은 «줄 하나»가 아니라 ★**«두 축»**(② target 축 = wasm32 `- run:` 줄 · ⑦ toolchain 축 = beta)이고, +둘은 ★**한 근인의 두 얼굴**이다. ⇒ 그래서 DoD 는 **5줄이 아니라 6줄**이다. ★**왜 조항이 아닌가 — «세고» 정했다**(먼저 목록을 만들지 않았다). 자산 8건을 **돌연변이로 깨뜨려** 무엇이 잡는지 쟀다: @@ -313,6 +318,18 @@ LC_ALL=C /usr/bin/grep -E '^[[:space:]]+rust: \[' .github/workflows/rust.yml \ ⒝★**OS 축(macos·ubuntu·windows 3종)은 로컬에서 재현할 수 없다** — 그 차원은 ★**CI 가 «유일한» 그물**이고 대조 대상이 아니다. **결함이 아니라 «알고 두는» 값이다.** +★★★**[2026-09-04 규율 — 게이트② 2회 연속 반려가 만든 것] 「고쳤다」를 쓰기 «전»에 «세라».** +이 리니지는 ★**「해소했다고 신고한 것이 산출물에 그대로 남아 있는」 형태로 두 번 반려됐다.** 실측: +「다섯 → 여섯 통일」은 ★**4자리 중 1자리**만 됐고, 워크로그 `.json` 의 `verification` 은 ★**diff 에 한 줄도 없이** +철회된 라벨(「beta 도 ok — 깨져도 무해」)을 «검증 기록»이라는 더 권위 있는 필드에 계속 싣고 있었다. +⇒ ★**정정 회차의 마감 절차 3줄**(이 절을 읽는 회차는 그대로 하라): +1. ★**`git diff` 로 확인하지 마라 — «착지본 전문 검색»으로 확인하라.** diff 는 «안 바뀐 자리»를 보여주지 않는다. + `LC_ALL=C /usr/bin/grep -rn '<옛 문자열>' --include='*.md' --include='*.json' .` → ★**0건이어야 한다.** +2. ★**분모는 「이 PR 이 만지는 문서 «전부» × 그 안의 필드 «전부»」다**(`git diff --name-only ..HEAD`). + ★**`.json` 의 «필드»가 사각이다** — `summary`·`changes`·`issues` 를 고치고 `verification` 을 빠뜨리기 쉽다. +3. ★**정정한 수는 «파생 수»를 데리고 다닌다.** 계수를 1 → 2 로 고치면 「다섯」·「5줄」·「자리 하나」가 전부 낡는다 — + ★**고친 수 하나마다 그 수에서 유도된 문장을 «검색해서» 세라.** + ## 5. 단계 분할 — ★**커밋 수로 자르지 마라. 충돌은 앞쪽 7커밋에 몰려 있다** 각 컷 지점에서 `git merge-tree --write-tree --name-only origin/main ` 을 돌린 실측: diff --git a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json index 7c900624..c16de279 100644 --- a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json +++ b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json @@ -6,22 +6,23 @@ "RustJava" ], "taskId": "rustjava-sync-contract-standing-clause-for-our-assets-going-stale", - "summary": "운영자 채택 제안 둘(2026-09-04-upstream-sync-s6#p1 · …-s7#p1)에 대한 결정이다. 결론: 동기 회차 계약에 「우리 자산 서술자 목록을 문서화하고 머지 후 재확인한다」 상시 조항을 넣지 않는다. 대신 그물이 없던 자리 하나를 막았다 — CLAUDE.md §Definition of Done 이 이제 CI 명령 5줄을 축약 없이 그대로 싣는다. 목록 문서화로 시작하지 않고 먼저 셌다: 우리 자산 8건을 돌연변이로 깨뜨려 무엇이 잡는지 실측했고(경로 문자열·setProperty 서술자·charset 라우팅·ClassFormatError 종류 단정은 cargo test RED · 수동 span 은 clippy RED · double_must_use allow 는 stable·beta 둘 다 ok 라 깨져도 무해 · 워크로그 스크립트는 로컬 DoD 와 CI 둘 다), ★[게이트② request-changes 정정] 「아무것도 없음」 칸은 1개가 아니라 «2개»다 — ② CI 워크플로의 --exclude 크레이트 이름 · ⑦ double_must_use allow. 초판이 ⑦을 「깨져도 무해」로 적은 것은 돌연변이를 «비하중» 자리(중복 crate-level attribute 한 곳)에 넣었기 때문이고, 9곳 전건 삭제로 재측정하면 stable 0 · beta error 7 이다 ⇒ ⑦의 그물도 «CI 만»이다. 계수가 2 라 「1개면 그 하나를 고쳐라」 규칙은 적용되지 않는다. 그리고 그 1개도 조용히 실패하지 않는다 — cargo 가 warning: excluded package(s) not found 를 찍고 빌드가 깨진다 ⇒ 문제는 침묵이 아니라 늦음이고, 근인은 「자산 목록이 없다」가 아니라 「로컬 DoD 가 CI 검사 5종 중 wasm32 clippy 한 줄을 빠뜨렸다」였다. 그 줄이 --exclude 크레이트 이름이 사는 유일한 자리다. ★결론은 그대로 「조항을 넣지 않는다」이나 논거를 다시 세웠다: ②와 ⑦은 다른 자산이 아니라 «한 근인의 두 얼굴»이다 — ②는 빠진 - run: 줄(target 축) · ⑦은 빠진 toolchain 축(beta) ⇒ 근인 하나(로컬 DoD 가 CI 매트릭스를 재현하지 않는다)를 고치면 둘 다 그물을 얻는다. DoD 에 cargo +beta clippy 를 넣자 ⑦의 9곳 전건 삭제가 로컬에서 error 7 로 잡힌다. 재개 조건도 축을 둘로 늘렸다(줄 문자열 축 + 매트릭스 차원 축) — 종전 명령은 rust: [stable, beta] 를 [stable] 로 줄여도 [stable, beta, nightly] 로 늘려도 0 을 냈다.", + "summary": "운영자 채택 제안 둘(2026-09-04-upstream-sync-s6#p1 · …-s7#p1)에 대한 결정이다. 결론: 동기 회차 계약에 「우리 자산 서술자 목록을 문서화하고 머지 후 재확인한다」 상시 조항을 넣지 않는다. 대신 구멍 하나(로컬 DoD 가 CI 매트릭스를 재현하지 않던 것)를 막았다 — CLAUDE.md §Definition of Done 이 이제 CI 명령 5줄 + toolchain 축 1줄 = «6줄»을 축약 없이 싣는다. 목록 문서화로 시작하지 않고 먼저 셌다: 우리 자산 8건을 돌연변이로 깨뜨려 무엇이 잡는지 실측했고(경로 문자열·setProperty 서술자·charset 라우팅·ClassFormatError 종류 단정은 cargo test RED · 수동 span 은 clippy RED · double_must_use allow 는 stable·beta 둘 다 ok 라 깨져도 무해 · 워크로그 스크립트는 로컬 DoD 와 CI 둘 다), ★[게이트② request-changes 정정] 「아무것도 없음」 칸은 1개가 아니라 «2개»다 — ② CI 워크플로의 --exclude 크레이트 이름 · ⑦ double_must_use allow. 초판이 ⑦을 「깨져도 무해」로 적은 것은 돌연변이를 «비하중» 자리(중복 crate-level attribute 한 곳)에 넣었기 때문이고, 9곳 전건 삭제로 재측정하면 stable 0 · beta error 7 이다 ⇒ ⑦의 그물도 «CI 만»이다. 계수가 2 라 「1개면 그 하나를 고쳐라」 규칙은 적용되지 않는다. 그리고 그 1개도 조용히 실패하지 않는다 — cargo 가 warning: excluded package(s) not found 를 찍고 빌드가 깨진다 ⇒ 문제는 침묵이 아니라 늦음이고, 근인은 「자산 목록이 없다」가 아니라 「로컬 DoD 가 CI 검사 5종 중 wasm32 clippy 한 줄을 빠뜨렸다」였다. 그 줄이 --exclude 크레이트 이름이 사는 유일한 자리다. ★결론은 그대로 「조항을 넣지 않는다」이나 논거를 다시 세웠다: ②와 ⑦은 다른 자산이 아니라 «한 근인의 두 얼굴»이다 — ②는 빠진 - run: 줄(target 축) · ⑦은 빠진 toolchain 축(beta) ⇒ 근인 하나(로컬 DoD 가 CI 매트릭스를 재현하지 않는다)를 고치면 둘 다 그물을 얻는다. DoD 에 cargo +beta clippy 를 넣자 ⑦의 9곳 전건 삭제가 로컬에서 error 7 로 잡힌다. 재개 조건도 축을 둘로 늘렸다(줄 문자열 축 + 매트릭스 차원 축) — 종전 명령은 rust: [stable, beta] 를 [stable] 로 줄여도 [stable, beta, nightly] 로 늘려도 0 을 냈다. ★[게이트② fix2 정정] 초판 문면의 「그물이 없던 자리 하나 = CI 명령 5줄」은 계수 «1» 시절의 파생 수다 — 계수가 2 가 되며 빠진 것은 «줄 하나»가 아니라 «두 축»(② target · ⑦ toolchain)이고, 따라서 DoD 는 5줄이 아니라 «6줄»이다. 그 파생 수가 REPORT.md · STATE.md · 워크로그 .md/.json · approach.md 에 남아 있던 것을 fix2 에서 전수 동기했다.", "changes": [ "CLAUDE.md §Definition of Done — CI 가 치는 명령을 5줄 → ★6줄로(cargo +beta clippy --all -- -D warnings 추가). CI 는 이 검사를 6셀(toolchain 2 × OS 3)로 치는데 repo 에 rust-toolchain.toml 이 없어 맨 cargo 는 stable 1개로만 돈다 — toolchain 축을 안 적으면 「rust.yml 이 치는 그대로」가 거짓이 된다. 실측 근거(9곳 전건 삭제 시 stable 0 · beta error 7)와 OS 축은 로컬 재현 불가라 CI 가 유일한 그물이라는 고지를 함께 넣었다.", - "docs/upstream-sync-approach.md §4 결정 절 — ⑦행 라벨을 「깨져도 무해」에서 ★「CI 만」으로 정정(세 갈래 재측정 표 첨부) · 계수 1 → ★2 · 결정 논거 재구성(둘은 한 근인의 두 얼굴 · 「조항이 여럿이면?」 기각) · 재개 조건에 ★축② 「매트릭스 차원 대조」 추가 · 비용 논거의 수를 「다섯」 → ★「여섯」으로 통일하고 세는 명령 병기.", + "docs/upstream-sync-approach.md §4 결정 절 — ⑦행 라벨을 「깨져도 무해」에서 ★「CI 만」으로 정정(세 갈래 재측정 표 첨부) · 계수 1 → ★2 · 결정 논거 재구성(둘은 한 근인의 두 얼굴 · 「조항이 여럿이면?」 기각) · 재개 조건에 ★축② 「매트릭스 차원 대조」 추가 · 비용 논거의 수를 「다섯」 → ★「여섯」으로 정정하고 세는 명령 병기(★fix 회차는 이 파일 «한 자리»만 고쳤고 나머지 3자리는 fix2 에서 동기했다).", "STATE.md · REPORT.md · docs/worklog/2026-09-04-sync-contract-stale-assets-decision.{md,json} 갱신·신설.", - "★.github/workflows/rust.yml 은 무접촉 — 크레이트 이름 1건은 S8 회차가 이미 고쳐 착지시켰다." + "★.github/workflows/rust.yml 은 무접촉 — 크레이트 이름 1건은 S8 회차가 이미 고쳐 착지시켰다.", + "★[fix2] 「신고 ↔ 산출물」 전수 동기: ⒜「다섯 자리」 잔존 3자리(REPORT.md · 워크로그 .md · .json issues[2])를 «여섯»으로 통일하고 세는 법 병기 ⒝워크로그 .json verification 을 «지금의 사실»로 갱신(⑦ 라벨 정정 표지 · 근인 대조를 축 둘로 · 축② 착수값 1 · cargo +beta clippy 실행 기록) ⒞★전문 검색이 «반려 밖에서» 더 찾은 것 — 「CI 명령 5줄」 파생 수 6자리(REPORT×3 · STATE×1 · 워크로그 .md×3 · approach.md×1 · json summary) · 워크로그 .md 재개 조건 코드블록이 «축① 만» 싣고 있던 것 · 워크로그 .md 검증 표에 cargo +beta clippy 행이 없던 것." ], "deploy": { "sha": "", "urls": [] }, - "verification": "착수 실측: origin/main a76b305 · behind 0 · 열린 PR 0. 계약1⒝ 돌연변이(각각 깨뜨린 뒤 build/clippy/test 를 돌리고 원상 복구): ① tests/test_class_format.rs 의 test-data/ → test_data/ ⇒ build ok · clippy ok · test RED. ③ system.rs 의 setProperty 서술자 String → Object ⇒ test RED. ④ string.rs 의 Charset::resolve → from_name().unwrap() 우회 ⇒ test RED. ⑤ thread.rs 의 .instrument(span) 삭제 ⇒ clippy RED(미사용 import). ⑥ test_class_format.rs 의 ClassFormatError → Throwable ⇒ test RED. ⑦ jvm-bytecode/src/interpreter.rs 의 #[allow(clippy::double_must_use)] 삭제 ⇒ stable clippy ok · beta clippy 도 ok(깨져도 무해). ② cargo clippy --workspace --exclude test_utils --target wasm32-unknown-unknown ⇒ rc=101 이고 문면은 warning: excluded package(s) `test_utils` not found in workspace + tokio wasm 컴파일 실패(조용한 통과가 아니다) · 로컬 4종 중 어느 것도 그 인자를 쓰지 않는다. ⑧ scripts/check-worklog-json.py 이동 ⇒ rc=2(로컬 DoD 와 CI 둘 다 그 경로를 친다). 근인 대조: rust.yml 의 - run: 줄 5개 ↔ CLAUDE.md DoD 4개 ⇒ 차집합이 정확히 wasm32 clippy 한 줄. 재개 조건 세는 명령(회신·§4 동일)의 값: 착수 시 5 → 착지본 0. 계약6: CI 5줄을 워크플로 문면 그대로 실행해 전건 rc=0 · cargo test --all = 554 passed / 0 failed / 1 ignored(baseline 554/0/1 동수 · 새 red 0). 돌연변이 전부 복구 확인(git status 가 문서 2파일만). 계약5: .github/workflows/rust.yml:55 이 이미 --exclude test-utils 이므로 이 회차는 무접촉.", + "verification": "★[fix2 갱신 — 이 필드는 fix 회차에서 «통째로 미수정»이라 철회된 라벨을 싣고 있었다. 아래가 «지금의 사실»이다.]\n◆원 회차(2026-09-04 초판) 착수 실측: origin/main a76b305 · behind 0 · 열린 PR 0. 계약1⒝ 돌연변이(각각 깨뜨린 뒤 build/clippy/test 를 돌리고 원상 복구): ① tests/test_class_format.rs 의 test-data/ → test_data/ ⇒ build ok · clippy ok · test RED. ③ system.rs 의 setProperty 서술자 String → Object ⇒ test RED. ④ string.rs 의 Charset::resolve → from_name().unwrap() 우회 ⇒ test RED. ⑤ thread.rs 의 .instrument(span) 삭제 ⇒ clippy RED(미사용 import). ⑥ test_class_format.rs 의 ClassFormatError → Throwable ⇒ test RED. ② cargo clippy --workspace --exclude test_utils --target wasm32-unknown-unknown ⇒ rc=101 이고 문면은 warning: excluded package(s) `test_utils` not found in workspace + tokio wasm 컴파일 실패(조용한 통과가 아니다). ⑧ scripts/check-worklog-json.py 이동 ⇒ rc=2(로컬 DoD 와 CI 둘 다 그 경로를 친다). ⑦ jvm-bytecode/src/interpreter.rs 의 #[allow(clippy::double_must_use)] 삭제 ⇒ stable clippy ok · beta clippy 도 ok — ★★[게이트② request-changes 정정] 그 문장은 «거짓»이다. 돌연변이가 «비하중» 자리(같은 파일의 함수별 #[allow] 에 가려진 중복 crate-level attribute 한 곳)에 들어갔고, jvm/src/jvm.rs 의 7곳이 그대로 남아 있었다. 세 갈래 재측정(각 회 cargo fmt --all 로 삭제 artifact 정규화): interpreter.rs:1 만 삭제 ⇒ stable 0 / beta 0(초판 결과 재현) · jvm.rs:2 만 삭제 ⇒ 0 / 0 · ★9곳 «전건» 삭제 ⇒ stable 0 / ★beta error 7. ⇒ ⑦의 그물은 «CI 만»이고 ② 와 같은 칸이다 ⇒ 계수 = 2. ★allow 9곳을 지우지 마라(지우면 beta 3셀 red). ※검수 회신은 「8곳 · red 101」로 적었다 — 자리 수는 내 실측이 9곳(interpreter.rs:1067 포함)이고, 101 은 lint 발생 «건», 7 은 cargo 요약의 크레이트별 error 수다(같은 것을 다른 자로 잰 것). 판정은 동일하다.\n◆근인 대조[fix 갱신 — 초판은 «단일 축» 문면이었다]: 로컬 DoD 가 CI 의 «매트릭스»를 재현하지 않았다. 축①(target) = rust.yml 의 - run: 줄 5개 ↔ 초판 DoD 4개 ⇒ 차집합이 wasm32 clippy 한 줄. 축②(toolchain) = rust.yml 의 strategy.matrix rust: [stable, beta] ↔ 초판 DoD 에 beta 없음(repo 에 rust-toolchain.toml 이 없어 맨 cargo 는 stable 1개) ⇒ 차집합이 beta 축. 둘은 «한 근인의 두 얼굴»이다.\n◆재개 조건 세는 명령(회신 · approach.md §4 · 워크로그 .md §5 동일)의 값: 착수 시 ★축① 5 · ★축② 1 → 착지본 축① 0 · 축② 0. 축② 신설의 근거(3돌연변이 실측): rust: [stable, beta] → [stable] ⇒ 축① 0 · 축② 0(술어가 CI ∖ DoD 라 DoD 가 더 엄격한 것은 구멍이 아니다 — 옳은 값) · → [stable, beta, nightly] ⇒ 축② 1(축②만 반응) · - run: cargo doc --no-deps 1줄 추가 ⇒ 축① 1(축①만 반응).\n◆계약6[fix2 재실행 — 정정 후 DoD «6줄»을 문면 그대로]: cargo fmt --all -- --check rc=0 · cargo clippy --all -- -D warnings rc=0 · ★cargo +beta clippy --all -- -D warnings rc=0 · cargo clippy --workspace --exclude test-utils --target wasm32-unknown-unknown -- -D warnings rc=0 · cargo test --all rc=0 (554 passed / 0 failed / 1 ignored · baseline 554/0/1 동수 · 새 red 0) · python3 scripts/check-worklog-json.py rc=0. 돌연변이 전부 복구 확인 · .rs 변경 0 · allow 9곳 무접촉. 계약5: .github/workflows/rust.yml:55 가 이미 --exclude test-utils 이므로 이 회차는 무접촉.", "issues": [ "★★[게이트② request-changes 정정] 초판의 계수 「1」은 틀렸다 — 「아무것도 없음」은 «2개»(② · ⑦)다. 근인은 돌연변이를 비하중 자리에 넣은 것이고(중복 crate-level attribute 한 곳만 삭제), 9곳 전건 삭제로 재측정하면 beta error 7 이다. ★그리고 그 차를 놓친 «같은 근인»이 하나 더 있었다: 브리프가 「제안 2 ↔ 검수 1」의 차를 해소하라고 요구했는데 초판이 그것을 안 짚었다 — 이제 답이 나왔다: ★«2»가 맞다.", "★이 결정이 «막는» 것은 「우리 자산이 낡는 것」 자체가 아니라 「그것이 로컬에서 안 드러나고 CI 에서만 드러나는 것」이다. 낡음 자체는 여전히 일어나고, 다만 여섯 자리는 기계가(테스트·컴파일·clippy) 이미 잡는다.", - "★잡는 그물이 축마다 다르다(테스트/컴파일/CI)는 것이 「조항 하나로 못 덮는다」의 근거다 — 조항으로 덮으면 이미 그물이 있는 다섯 자리에까지 사람 확인을 얹게 된다.", + "★잡는 그물이 축마다 다르다(테스트/컴파일/CI)는 것이 「조항 하나로 못 덮는다」의 근거다 — 조항으로 덮으면 이미 그물이 있는 «여섯» 자리에까지 사람 확인을 얹게 된다. ★세는 법: 돌연변이 표 8행 − 그물이 「CI 만」인 2행(② · ⑦) = 6(수리 후에는 8). ★[게이트② fix2 정정] 초판은 여기서 「다섯」이라 적었다 — 계수 «1» 시절의 파생 수이고, 같은 파일 issues[1] 의 「여섯」과 «자기모순»이었다. 이제 두 자리가 같은 수다.", "★S8 이 고친 CI 크레이트 이름 1건과 이 회차의 산출은 «다른 층»이다: 전자는 증상 1건, 후자는 그 증상이 늦게 드러난 경로. 티켓이 「고쳤다고 조항 결정을 건너뛰지 마라」고 못박은 자리다.", "머지하지 않았다 — 게이트②·③은 별 세션이다. ★게이트③은 등재 repo 라 merge_strategy: merge 필수(bin/queue-lint 검사22). upstream 동기 회차를 새로 열지 않았다(behind 0 · S9 없음).", "★★[C1 승계 철회] 초판 후속 추천 3번(「double_must_use allow 가 이제 지워도 통과한다 — 정리할지는 별건」)을 «철회한다». 그 문장은 비하중 돌연변이에서 나온 것이고, 9곳을 전건 지우면 beta clippy 가 error 7 로 red 다. ★그대로 두면 다음 회차가 그 문장을 근거로 allow 를 지우고 beta 3셀을 빨갛게 만든다 ⇒ ★allow 9곳을 지우지 마라.", diff --git a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md index 793d94c2..0e808a33 100644 --- a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md +++ b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md @@ -75,12 +75,18 @@ error: could not compile `tokio` (lib) due to 1 previous error ← rc≠0 ★**S8 이 ⑶을 더해 «셋»이 됐다.** ⒞ ★★**같은 형태인가 → «아니다».** 잡는 그물이 각각 다르다(테스트 · 컴파일 · CI). -⇒ ★**조항 하나로 못 덮는다** — 덮으려 하면 **이미 그물이 있는 다섯 자리에까지 사람 확인을 얹는다**. 그것이 비용이다. +⇒ ★**조항 하나로 못 덮는다** — 덮으려 하면 **이미 그물이 있는 여섯 자리에까지 사람 확인을 얹는다**. 그것이 비용이다. +★**세는 법**(수리 전 기준): §1 돌연변이 표 **8행** − 그물이 「CI 만」인 **2행**(② · ⑦) = ★**6**. +★**[게이트② 정정] 초판의 「다섯」은 계수 «1» 시절의 파생 수다** — 계수가 **2**로 정정되며 **6**이 맞다. +(`:93` 의 「여섯 자리는 이미 기계가 지킨다」와 이제 **같은 수**다.) ## 4. ★★결정문 · 적은 «자리» · 이유 (계약 3) > ★**동기 회차 계약에 「우리 자산 서술자 목록을 문서화하고 머지 후 재확인한다」 상시 조항을 «넣지 않는다».** -> ★**대신 «그물이 없던 자리 하나»를 막는다 — `CLAUDE.md` §Definition of Done 이 CI 명령 5줄을 «축약 없이 그대로» 싣는다.** +> ★**대신 «구멍 하나»를 막는다 — `CLAUDE.md` §Definition of Done 이 CI 명령 5줄 + toolchain 축 1줄 = «6줄»을 축약 없이 싣는다.** + +★**[2026-09-04 정정 — 게이트②] 초판 결정문은 「그물이 없던 자리 «하나» … CI 명령 5줄」이었다** — +계수 «1» 시절 문면이다. 계수가 **2**가 되며 빠진 것은 «줄 하나»가 아니라 **두 축**(target · toolchain)이고 DoD 는 **6줄**이다. **⒜ ★계수가 «2»인데도 왜 여전히 조항이 아닌가**(★초판 논거 「1개니까」는 계수 정정으로 **무효** — 결론은 같고 이유가 다르다): - ★★**② 와 ⑦ 은 «다른 자산»이 아니라 «한 근인의 두 얼굴»이다 — «로컬 DoD 가 CI 매트릭스를 재현하지 않는다».** @@ -95,7 +101,7 @@ error: could not compile `tokio` (lib) due to 1 previous error ← rc≠0 **⒞ 적은 자리 — 워크로그에만 적지 않았다**: | 자리 | 무엇을 | 왜 그 자리인가 | |---|---|---| -| ★`CLAUDE.md` §Definition of Done | **CI 5줄 verbatim** + 「축약하지 마라」와 그 이유(S8 실사고) | ★**모든 회차가 반드시 읽는다**(DoD) | +| ★`CLAUDE.md` §Definition of Done | ★**6줄 verbatim**(CI `- run:` 5줄 + `cargo +beta` 1줄) + 「축약하지 마라」·「toolchain 축을 빼지 마라」와 그 이유(S8 실사고 · beta 실측) | ★**모든 회차가 반드시 읽는다**(DoD) | | ★`docs/upstream-sync-approach.md` §4 뒤 | **결정문 · 돌연변이 표 · 사료 표 · 재개 조건과 세는 명령** | ★**동기 회차가 반드시 읽는 계약 파일** | ## 5. ★★재개 조건 + 세는 명령 + 오늘의 값 (계약 4) @@ -105,11 +111,24 @@ error: could not compile `tokio` (lib) due to 1 previous error ← rc≠0 ```sh cd "$(git rev-parse --show-toplevel)" DOD=$(sed -n '/## Definition of Done/,/^- 착수·완료마다/p' CLAUDE.md) + +# ★축① — CI 의 `- run:` 줄 ∖ 로컬 DoD (0 이어야 한다) LC_ALL=C /usr/bin/grep -E '^[[:space:]]+- run: ' .github/workflows/rust.yml | sed 's/^[[:space:]]*- run: //' \ -| while IFS= read -r c; do printf '%s' "$DOD" | LC_ALL=C /usr/bin/grep -qF -- "$c" || echo "MISSING: $c"; done \ +| while IFS= read -r c; do printf '%s' "$DOD" | LC_ALL=C /usr/bin/grep -qF -- "$c" || echo "MISSING-RUN: $c"; done \ | /usr/bin/grep -c . + +# ★축② — CI 의 toolchain 매트릭스 ∖ 로컬 DoD (0 이어야 한다) +LC_ALL=C /usr/bin/grep -E '^[[:space:]]+rust: \[' .github/workflows/rust.yml \ +| sed 's/.*\[//; s/\].*//; s/, */\n/g' \ +| while IFS= read -r tc; do + [ "$tc" = stable ] && { printf '%s' "$DOD" | LC_ALL=C /usr/bin/grep -qE 'cargo (fmt|clippy|test)' || echo "MISSING-TC: $tc"; continue; } + printf '%s' "$DOD" | LC_ALL=C /usr/bin/grep -qF -- "cargo +$tc " || echo "MISSING-TC: $tc" + done | /usr/bin/grep -c . ``` +★**[2026-09-04 정정 — 게이트②] 초판은 이 블록에 «축① 만» 실어 놓고 아래 표에서는 두 축을 말했다.** +★**정본은 `docs/upstream-sync-approach.md` §4 이고, 이제 두 파일이 같은 명령을 싣는다.** + | | 값 | |---|---| | 착수 시 | 축① ★**5** · 축② ★**1**(beta 축이 DoD 에 없었다) | @@ -130,12 +149,13 @@ LC_ALL=C /usr/bin/grep -E '^[[:space:]]+- run: ' .github/workflows/rust.yml | se ## 7. 계약 6 — 기존 스위트 전건 · 새 red 0 -★**CI 5줄을 «워크플로 문면 그대로»** 실행: +★**정정 후 DoD «6줄»을 «문면 그대로»** 실행(★초판은 **5줄**이었다 — `+beta` 가 빠져 있었다): | 명령 | rc | |---|---| | `cargo fmt --all -- --check` | **0** | | `cargo clippy --all -- -D warnings` | **0** | +| ★`cargo +beta clippy --all -- -D warnings` | ★**0** | | `cargo clippy --workspace --exclude test-utils --target wasm32-unknown-unknown -- -D warnings` | **0** | | `cargo test --all` | **0** — ★**554 / 0 / 1** | | `python3 scripts/check-worklog-json.py` | **0** | From a7d0f2a986b9fda36d4c1d1f1564aa5916a2b109 Mon Sep 17 00:00:00 2001 From: jun0 Date: Fri, 4 Sep 2026 17:10:08 +0900 Subject: [PATCH 4/5] =?UTF-8?q?docs:=20=EC=88=98=20=EB=9D=BC=EB=B2=A8=20?= =?UTF-8?q?=E3=80=8Cbeta=20error=207=E3=80=8D=2018=EC=9E=90=EB=A6=AC=20?= =?UTF-8?q?=EC=A0=95=EC=A0=95=20=E2=80=94=20rc=3D101=20=C2=B7=20=EC=A7=84?= =?UTF-8?q?=EB=8B=A8=206=EA=B1=B4=20=C2=B7=20=ED=99=94=ED=95=B4=20?= =?UTF-8?q?=EB=AC=B8=EC=9E=A5=20=EC=B2=A0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 게이트② request-changes(C1·C2) 승계. 판정·본체·대조표 분모는 무접촉. C1 — 직접 재측정(9곳 삭제 → cargo fmt --all → cargo +beta clippy --all -D warnings): 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) 의 값이고 그 필드가 내건 정의가 아니었다. 착지본 18자리 전건 정정(CLAUDE.md 1 · approach.md 3 · REPORT.md 3 · STATE.md 2 · 워크로그 .md 3 · json 6) + 화해 문장 (「101 은 lint 건 · 7 은 크레이트별 error 수」) 철회. 「7 이 맞다」고 재주장하지 않는다. 덧붙임: 6 은 하한이다 — jvm-bytecode 가 jvm 에 의존해 jvm 이 깨지면 린트되지 않는다. C2 — 잔존 4건: 워크로그 「문서 2파일」 2자리 → 6파일(규범 2 + 기록 4) · json title 을 계수 2 문면으로 · 「채택 제안 둘/2건」 3자리를 셋으로 맞추고 s8#p0 열거. PR 제목도 계수 2 문면으로 고쳤다(착지 subject 에 남는다). 5건째를 스스로 찾았다 — changes[0]. 필터 걸린 sweep 이 거짓 0 을 냈기 때문이고 (zsh 가 따옴표 없는 $F 를 단어분할하지 않아 grep 이 파일을 못 열고 죽었다), 그 교훈을 approach.md §4 마감 절차 4번으로 박았다: 파일은 인자로 나열하고, 필터 없이 총계를 낸 뒤 한 건씩 정정 기록인가 잔존인가를 눈으로 갈라라. 검증: DoD 6줄 전건 rc=0 · cargo test --all 554/0/1(새 red 0) · 축① 0 · 축② 0 · .rs 변경 0 · allow 9곳 무접촉. [rustjava-sync-contract-standing-clause-for-our-assets-going-stale] --- CLAUDE.md | 4 +++- REPORT.md | 9 +++++---- STATE.md | 13 ++++++++++--- docs/upstream-sync-approach.md | 16 ++++++++++++---- ...9-04-sync-contract-stale-assets-decision.json | 15 ++++++++------- ...-09-04-sync-contract-stale-assets-decision.md | 16 ++++++++++------ 6 files changed, 48 insertions(+), 25 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 46b76896..40f16a8c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -35,7 +35,9 @@ `rust.yml` 의 `strategy.matrix.rust = [stable, beta]` 가 그 차원이고, 이 repo 엔 `rust-toolchain.toml` 이 **없어** 맨 `cargo` 는 **stable 1개**로만 돈다. ⇒ ★**toolchain 축을 안 적으면 「rust.yml 이 치는 그대로」가 «거짓»이 된다.** ★**실측 근거**(2026-09-04): `#[allow(clippy::double_must_use)]` **9곳을 전건 지우면** - ★**stable clippy 는 0인데 beta clippy 가 error 7** 이다 ⇒ ★**그 자산의 그물은 «beta 축»에만 있다.** + ★**stable clippy 는 0인데 beta clippy 는 RED**(★**rc=101** · `double_must_use` 진단 **6**건 — + 전건 `jvm/src/jvm.rs:140·404·438·779·791·1016` · cargo 요약 줄이 「due to **6** previous errors」라고 말한다) + ⇒ ★**그 자산의 그물은 «beta 축»에만 있다.** ★★**축약본도 쓰지 마라 — 그것이 2026-09-04 에 실제로 구멍을 만들었다.** 종전 문안은 `cargo fmt --check`·`cargo clippy`·`cargo test` 로 줄여 적어 ★**wasm32 줄이 통째로 빠져 있었고**, 그 줄이 ★**`--exclude <크레이트 이름>` 이 사는 «유일한» 자리**다. ⇒ upstream 이 `test_utils` 를 diff --git a/REPORT.md b/REPORT.md index 59a527c7..b6d07cf5 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,7 +1,8 @@ # REPORT ## [2026-09-04] 「우리 자산이 낡는다」 상시 조항 판정 — 넣지 않고 «구멍 하나»를 막았다 (rustjava-sync-contract-standing-clause-for-our-assets-going-stale) -- 무엇을: 운영자 채택 제안 둘(`2026-09-04-upstream-sync-s6#p1`·`…-s7#p1`)에 대한 **결정**이다. +- 무엇을: 운영자 채택 제안 ★**셋**(`2026-09-04-upstream-sync-s6#p1` · `…-s7#p1` · ★`…-s8#p0`)에 대한 **결정**이다. + (★**[fix3 정정] 초판은 「둘」** — 같은 제안의 세 번째 판이 도착해 `adoptedProposals` 는 **세 ref** 다.) ★**결론: 상시 조항을 «넣지 않는다».** 대신 ★**로컬 DoD 가 CI 의 «매트릭스»를 재현하지 않던 것**을 고쳤다 — `CLAUDE.md` DoD 가 이제 **CI 명령 5줄 + toolchain 축 1줄 = «6줄»**을 축약 없이 싣는다. ★**코드(`.rs`) 변경 0** · 규범 문서 **2파일**(`CLAUDE.md` · `docs/upstream-sync-approach.md`) + 기록 문서 4 @@ -13,14 +14,14 @@ `ClassFormatError` 종류 단정은 **`cargo test` RED**, 수동 span 은 **clippy RED**, `double_must_use` allow 는 **깨져도 무해**, 워크로그 스크립트는 **로컬 DoD 와 CI 둘 다** 잡는다. ⇒ ★★**[게이트② `request-changes` 정정] 「아무것도 없음」은 «2개»다**(② CI `--exclude` · ⑦ `double_must_use` allow). - 초판이 ⑦을 «비하중» 자리에서 재 「무해」로 적었으나, ★**9곳 전건 삭제로 재측정하면 stable 0 · ★beta error 7** + 초판이 ⑦을 «비하중» 자리에서 재 「무해」로 적었으나, ★**9곳 전건 삭제로 재측정하면 stable 0 · ★beta RED**(rc=101 · 진단 **6**건) ⇒ ⑦의 그물도 **CI 만**이다. ⇒ ★**「1개면 그 하나를 고쳐라」 규칙은 적용되지 않는다.** ★★**게다가 그 1개도 «조용히» 실패하지 않는다** — cargo 가 `warning: excluded package(s) … not found` 를 찍고 빌드가 깨진다 ⇒ ★**문제는 «침묵»이 아니라 «늦음»**(push 후 CI 에서만)이고, ★**근인은 「자산 목록이 없다」가 아니라 «로컬 DoD 가 CI «매트릭스»를 재현하지 않는다»** 였다 — ②는 빠진 `- run:` 줄(**target** 축) · ⑦은 빠진 **toolchain** 축(beta) ⇒ ★**한 근인의 두 얼굴**이다. ⇒ ★**결론은 그대로 「넣지 않는다」이나 논거가 바뀌었다**: 근인 하나를 고치면 둘 다 그물을 얻는다 - (DoD 에 `cargo +beta clippy` 를 넣자 ⑦이 **로컬에서 error 7** 로 잡힌다 · 실측). + (DoD 에 `cargo +beta clippy` 를 넣자 ⑦이 **로컬에서 RED**(rc=101 · 진단 **6**건)로 잡힌다 · 실측). - 사용자 영향: 런타임 동작 **무변경**. 회차가 로컬에서 CI 와 **같은 6줄**(★**toolchain 축 포함**)을 돌리게 되어 ★**「로컬 green 인데 CI red」 부류가 이 축에서 사라진다**(S5·S7·S8 이 실제로 그 부류였다). - 검증: **DoD 6줄을 문면 그대로** 실행 — 전건 **rc=0**(★`cargo +beta clippy --all -- -D warnings` **rc=0** 포함) · @@ -37,7 +38,7 @@ (축① `- run:` 줄 · ★축② **toolchain 매트릭스**) · ★**오늘의 값 = 축① 0 · 축② 0**(착수 시 축① 5 · 축② 1). ★세 돌연변이로 **각 축이 «자기 자리»에서만 반응**함을 실측했다. - ★★**[정정] 초판 후속 추천 3번을 «철회한다»** — 「`double_must_use` allow 가 이제 지워도 통과한다」는 - **비하중 돌연변이에서 나온 거짓**이다. ★**9곳을 전건 지우면 beta clippy 가 error 7 로 red 다** ⇒ ★**지우지 마라.** + **비하중 돌연변이에서 나온 거짓**이다. ★**9곳을 전건 지우면 beta clippy 가 RED 다**(rc=101 · 진단 **6**건) ⇒ ★**지우지 마라.** - 후속 추천: ⑴**게이트③은 `--merge`**(등재 repo). ⑵★**upstream 동기 «정기 축» 판정은 아직 열려 있다** (S8 워크로그 `proposals[1]` · behind 0 인 지금이 적기다) — 이 회차는 그것을 «건드리지 않았다». ⑶★**C7 고지**: DoD 블록 «개악»과 **OS 축 3종**은 이 대조가 못 잡는다 — 회차가 두 축을 «실제로 돌렸는지» 적어라. diff --git a/STATE.md b/STATE.md index f0b5f65d..a3a14fa9 100644 --- a/STATE.md +++ b/STATE.md @@ -9,10 +9,10 @@ 수동 span 은 **clippy RED** · `double_must_use` allow 는 **깨져도 무해** · 워크로그 스크립트는 **로컬+CI 둘 다**. ⇒ ★★**[게이트② 정정] 「아무것도 없음」은 «1개»가 아니라 «2개»**(② CI `--exclude` · ⑦ `double_must_use` allow) — 초판이 ⑦을 «비하중» 자리(중복 crate-level attribute 1곳)에서 재 「무해」로 적었고, ★**9곳 전건 삭제로 재측정하면 - stable 0 · ★beta error 7** 이라 ⑦의 그물도 **CI 만**이다. ⇒ 「1개면 그 하나를 고쳐라」 규칙은 **적용되지 않는다**. + stable 0 · ★beta RED**(rc=101 · 진단 **6**건)이라 ⑦의 그물도 **CI 만**이다. ⇒ 「1개면 그 하나를 고쳐라」 규칙은 **적용되지 않는다**. ★**결론은 그대로 「넣지 않는다」이나 논거를 다시 세웠다**: ②와 ⑦은 «한 근인의 두 얼굴»이다 — ★**로컬 DoD 가 CI «매트릭스»를 재현하지 않는다**(② = 빠진 `- run:` 줄 = target 축 · ⑦ = 빠진 toolchain 축). - ⇒ 근인 하나를 고치니 둘 다 그물을 얻었다(DoD 에 `cargo +beta clippy` 추가 ⇒ ⑦이 **로컬에서 error 7** 로 잡힌다). + ⇒ 근인 하나를 고치니 둘 다 그물을 얻었다(DoD 에 `cargo +beta clippy` 추가 ⇒ ⑦이 **로컬에서 RED**(rc=101 · 진단 **6**건)로 잡힌다). ★★**근인은 「자산 목록이 없다」가 아니었다** — ★**로컬 DoD 가 CI 검사 5종 중 «wasm32 clippy» 한 줄을 빠뜨렸고** 그 줄이 그 자산이 사는 **유일한 자리**다. ⇒ `CLAUDE.md` DoD 가 이제 ★**CI 명령 5줄 + toolchain 축 1줄 = «6줄»**을 축약 없이 싣는다(★**[게이트② 정정] 「5줄」은 계수 «1» 시절 수다 — 빠진 것은 «줄 하나»가 아니라 «두 축»이었다**). @@ -25,7 +25,14 @@ 철회된 라벨(「beta 도 ok — 깨져도 무해」)을 «검증 기록» 필드에 그대로 싣고 있었다. ★**전문 검색으로 반려 밖에서 «더» 찾았다**: 「CI 명령 5줄」 파생 수 **6자리** · 워크로그 재개 조건 블록이 «축① 만» 실은 것 · 워크로그 검증 표에 `+beta` 행이 없던 것. ⇒ ★**전건 동기 + 마감 절차 3줄을 §4 에 규율로 박았다.** - **PR 대기 — 게이트③ 미착지.** + ⇒ ★★**[게이트② 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자리 · json `title` · 「채택 제안 둘」 3자리) + ★**PR 제목**까지 동기. + ⑶★**«5건째»를 스스로 찾았다**(`changes[0]`) — ★**필터 걸린 sweep 이 «거짓 0»을 냈기 때문**이고(zsh 단어분할), + 그 교훈을 §4 마감 절차 **4번**으로 박았다. **PR 대기 — 게이트③ 미착지.** - [rustjava-upstream-sync-squash-defeats-convergence] ★**S1~S4 가 착지하고도 fork 가 upstream 에 한 걸음도 가까워지지 않은 근인을 확정하고 계보를 기록했다.** 근인 = 게이트③ 제품 repo **`--squash`**. 증명은 **머지커밋 부모 수**다 — `6bfe97c4`·`11ef5010`·`4bb796de`·`3a597768` **전건 1개**(커밋 7·10·15·21이 diff --git a/docs/upstream-sync-approach.md b/docs/upstream-sync-approach.md index 0b7301ab..31fea7de 100644 --- a/docs/upstream-sync-approach.md +++ b/docs/upstream-sync-approach.md @@ -187,7 +187,8 @@ upstream 은 여기서만 `UTF-8`/`EUC-KR` 하드코딩을 유지한다 ⇒ 그 ### ★★★[2026-09-04 결정] 「우리 자산이 낡는다」 — ★**상시 조항을 «넣지 않는다». 대신 구멍 하나를 막았다** -★**채택 제안 둘**(`2026-09-04-upstream-sync-s6#p1` · `2026-09-04-upstream-sync-s7#p1`)에 대한 **결정**이다. +★**채택 제안 ★셋**(`2026-09-04-upstream-sync-s6#p1` · `2026-09-04-upstream-sync-s7#p1` · ★`2026-09-04-upstream-sync-s8#p0`)에 대한 **결정**이다. +★**[fix3 정정] 초판은 「둘」이었다** — 세 번째 판(`s8#p0`)이 2026-09-04 13:07 에 도착해 총괄이 「이미 발권됨」으로 해제했고, `adoptedProposals` 는 **세 ref** 다. **결정문**: > ★**동기 회차 계약에 「우리 자산 서술자 목록을 문서화하고 머지 후 재확인한다」 상시 조항을 «넣지 않는다».** @@ -209,7 +210,7 @@ wasm32 clippy 한 줄」이었다.** 그것은 ★**계수 «1» 시절의 문 | ④ | charset 라우팅(PR #5) | `Charset::resolve` → 폴백 우회 | ★`cargo test` **RED** | | ⑤ | 수동 span(PR #4) | `.instrument(span)` 삭제 | ★`clippy` **RED**(미사용 import) | | ⑥ | `ClassFormatError` 종류 단정(PR #3) | `ClassFormatError` → `Throwable` | ★`cargo test` **RED** | -| ⑦ | `double_must_use` allow(PR #14) | ★**9곳 «전건» 삭제** | ★★**CI 만**(stable clippy **0** ↔ ★**beta clippy error 7**) | +| ⑦ | `double_must_use` allow(PR #14) | ★**9곳 «전건» 삭제** | ★★**CI 만**(stable clippy **0** ↔ ★**beta clippy RED** — rc=101 · 진단 **6**건) | | ⑧ | 워크로그 잠금 스크립트 경로 | 스크립트 이동 | 로컬 DoD **와** CI 둘 다 잡는다(rc=2) | ⇒ ★★**「아무것도 없음」 칸은 «2개»(② · ⑦)다.** @@ -224,7 +225,7 @@ wasm32 clippy 한 줄」이었다.** 그것은 ★**계수 «1» 시절의 문 | ⓪ 무돌연변이(기준선) | 0 | **0** | | ① `interpreter.rs:1` 만 삭제(★초판이 한 것) | 0 | **0** ← 초판 결과 재현됨 | | ② `jvm.rs:2` 만 삭제(함수별 6 존치) | 0 | **0** | -| ★**③ 9곳 «전건» 삭제** | 0 | ★**error 7** | +| ★**③ 9곳 «전건» 삭제** | 0 | ★**RED** — rc=**101** · `double_must_use` 진단 **6**건(`jvm/src/jvm.rs:140·404·438·779·791·1016`) · 요약 줄 「due to **6** previous errors」 | ⇒ ★**「지워도 stable·beta 둘 다 통과한다」는 «중복 attribute 하나»에만 참이고 «자산»에는 «거짓»이다.** ★**⑦의 그물은 «beta clippy» 뿐이고, 그것이 로컬 DoD 에 없었으므로 «CI 만» — ② 와 «문자 그대로 같은 칸»이다.** @@ -240,7 +241,7 @@ wasm32 clippy 한 줄」이었다.** 그것은 ★**계수 «1» 시절의 문 - ★★**② 와 ⑦ 은 «다른 자산»이 아니라 «한 근인의 두 얼굴»이다** — ②는 **빠진 `- run:` 줄**(wasm32 **target** 축) · ⑦은 **빠진 toolchain 축**(beta). ⇒ ★**근인 «하나»(DoD ≠ CI 매트릭스)를 고치면 «둘 다» 그물을 얻는다.** ★**실측**: DoD 에 `cargo +beta clippy --all -- -D warnings` 를 넣자 ⑦의 9곳 전건 삭제가 - ★**로컬에서 error 7 로 잡힌다**(종전엔 CI 에서만 났다). + ★**로컬에서 RED**(rc=101 · 진단 **6**건)**로 잡힌다**(종전엔 CI 에서만 났다). - ★**「조항이 «여럿»이면?」도 검토하고 기각한다** — 아래 사료 표대로 세 방향은 잡는 그물이 각각 다르므로 방향마다 조항을 두면 **셋**이 되고, 그중 둘(테스트·컴파일 축)은 ★**이미 기계가 지키는 자리에 사람 확인을 얹는 것**이다. - ⇒ 계약이 준 규칙(「1개면 …」)은 **적용되지 않지만**, 그 «취지»(★**「자산 목록」이 아니라 «구멍»을 고쳐라**)는 @@ -329,6 +330,13 @@ LC_ALL=C /usr/bin/grep -E '^[[:space:]]+rust: \[' .github/workflows/rust.yml \ ★**`.json` 의 «필드»가 사각이다** — `summary`·`changes`·`issues` 를 고치고 `verification` 을 빠뜨리기 쉽다. 3. ★**정정한 수는 «파생 수»를 데리고 다닌다.** 계수를 1 → 2 로 고치면 「다섯」·「5줄」·「자리 하나」가 전부 낡는다 — ★**고친 수 하나마다 그 수에서 유도된 문장을 «검색해서» 세라.** +4. ★★**[2026-09-04 추가 · fix3] 「0건」을 «필터 걸린 검색»으로 받지 마라 — 이 회차가 «거짓 0»을 실제로 받았다.** + fix3 이 잔존을 `grep … | grep -v '초판\|정정\|철회'` 로 세어 **전 패턴 0** 을 얻었는데, 그것은 ⑴zsh 가 따옴표 없는 + `$F`(파일 목록 변수)를 ★**단어분할하지 않아** grep 이 «파일 하나도 못 열고» stderr 로 죽었고 ⑵파이프의 `-c` 가 + 그 빈 출력을 **0** 으로 센 결과였다. ★**진짜 잔존이 그 뒤에 «하나 더»(`changes[0]`) 있었다.** + ⇒ ★**세는 법**: 파일을 **인자로 나열**하고(변수 전개에 기대지 마라 · `set -- $VAR` 도 zsh 에선 1개다), + ★**먼저 «필터 없이» 총계를 내고 «그다음» 한 건씩 «정정 기록인가 잔존인가»를 눈으로 갈라라.** + ★**필터는 세는 단계가 아니라 «읽는» 단계에 붙인다** — 세는 단계에 붙이면 그 필터가 잔존을 함께 지운다. ## 5. 단계 분할 — ★**커밋 수로 자르지 마라. 충돌은 앞쪽 7커밋에 몰려 있다** diff --git a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json index c16de279..208fff0d 100644 --- a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json +++ b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json @@ -1,31 +1,32 @@ { "schema": 1, "date": "2026-09-04", - "title": "「우리 자산이 낡는다」 상시 조항 판정 — 넣지 않고 로컬 DoD 의 CI 검사 누락 1건을 막았다", + "title": "「우리 자산이 낡는다」 상시 조항 판정 — 넣지 않고 로컬 DoD 가 CI 매트릭스를 재현하지 않던 «두 축»을 막았다", "services": [ "RustJava" ], "taskId": "rustjava-sync-contract-standing-clause-for-our-assets-going-stale", - "summary": "운영자 채택 제안 둘(2026-09-04-upstream-sync-s6#p1 · …-s7#p1)에 대한 결정이다. 결론: 동기 회차 계약에 「우리 자산 서술자 목록을 문서화하고 머지 후 재확인한다」 상시 조항을 넣지 않는다. 대신 구멍 하나(로컬 DoD 가 CI 매트릭스를 재현하지 않던 것)를 막았다 — CLAUDE.md §Definition of Done 이 이제 CI 명령 5줄 + toolchain 축 1줄 = «6줄»을 축약 없이 싣는다. 목록 문서화로 시작하지 않고 먼저 셌다: 우리 자산 8건을 돌연변이로 깨뜨려 무엇이 잡는지 실측했고(경로 문자열·setProperty 서술자·charset 라우팅·ClassFormatError 종류 단정은 cargo test RED · 수동 span 은 clippy RED · double_must_use allow 는 stable·beta 둘 다 ok 라 깨져도 무해 · 워크로그 스크립트는 로컬 DoD 와 CI 둘 다), ★[게이트② request-changes 정정] 「아무것도 없음」 칸은 1개가 아니라 «2개»다 — ② CI 워크플로의 --exclude 크레이트 이름 · ⑦ double_must_use allow. 초판이 ⑦을 「깨져도 무해」로 적은 것은 돌연변이를 «비하중» 자리(중복 crate-level attribute 한 곳)에 넣었기 때문이고, 9곳 전건 삭제로 재측정하면 stable 0 · beta error 7 이다 ⇒ ⑦의 그물도 «CI 만»이다. 계수가 2 라 「1개면 그 하나를 고쳐라」 규칙은 적용되지 않는다. 그리고 그 1개도 조용히 실패하지 않는다 — cargo 가 warning: excluded package(s) not found 를 찍고 빌드가 깨진다 ⇒ 문제는 침묵이 아니라 늦음이고, 근인은 「자산 목록이 없다」가 아니라 「로컬 DoD 가 CI 검사 5종 중 wasm32 clippy 한 줄을 빠뜨렸다」였다. 그 줄이 --exclude 크레이트 이름이 사는 유일한 자리다. ★결론은 그대로 「조항을 넣지 않는다」이나 논거를 다시 세웠다: ②와 ⑦은 다른 자산이 아니라 «한 근인의 두 얼굴»이다 — ②는 빠진 - run: 줄(target 축) · ⑦은 빠진 toolchain 축(beta) ⇒ 근인 하나(로컬 DoD 가 CI 매트릭스를 재현하지 않는다)를 고치면 둘 다 그물을 얻는다. DoD 에 cargo +beta clippy 를 넣자 ⑦의 9곳 전건 삭제가 로컬에서 error 7 로 잡힌다. 재개 조건도 축을 둘로 늘렸다(줄 문자열 축 + 매트릭스 차원 축) — 종전 명령은 rust: [stable, beta] 를 [stable] 로 줄여도 [stable, beta, nightly] 로 늘려도 0 을 냈다. ★[게이트② fix2 정정] 초판 문면의 「그물이 없던 자리 하나 = CI 명령 5줄」은 계수 «1» 시절의 파생 수다 — 계수가 2 가 되며 빠진 것은 «줄 하나»가 아니라 «두 축»(② target · ⑦ toolchain)이고, 따라서 DoD 는 5줄이 아니라 «6줄»이다. 그 파생 수가 REPORT.md · STATE.md · 워크로그 .md/.json · approach.md 에 남아 있던 것을 fix2 에서 전수 동기했다.", + "summary": "운영자 채택 제안 «셋»(2026-09-04-upstream-sync-s6#p1 · …-s7#p1 · ★…-s8#p0)에 대한 결정이다. ★[fix3 정정] 초판은 「둘」이라 적었다 — 같은 제안의 세 번째 판(s8#p0)이 2026-09-04 13:07 에 도착해 총괄이 「이미 발권됨」으로 해제했고, adoptedProposals 는 세 ref 다. 결론: 동기 회차 계약에 「우리 자산 서술자 목록을 문서화하고 머지 후 재확인한다」 상시 조항을 넣지 않는다. 대신 구멍 하나(로컬 DoD 가 CI 매트릭스를 재현하지 않던 것)를 막았다 — CLAUDE.md §Definition of Done 이 이제 CI 명령 5줄 + toolchain 축 1줄 = «6줄»을 축약 없이 싣는다. 목록 문서화로 시작하지 않고 먼저 셌다: 우리 자산 8건을 돌연변이로 깨뜨려 무엇이 잡는지 실측했고(경로 문자열·setProperty 서술자·charset 라우팅·ClassFormatError 종류 단정은 cargo test RED · 수동 span 은 clippy RED · double_must_use allow 는 stable·beta 둘 다 ok 라 깨져도 무해 · 워크로그 스크립트는 로컬 DoD 와 CI 둘 다), ★[게이트② request-changes 정정] 「아무것도 없음」 칸은 1개가 아니라 «2개»다 — ② CI 워크플로의 --exclude 크레이트 이름 · ⑦ double_must_use allow. 초판이 ⑦을 「깨져도 무해」로 적은 것은 돌연변이를 «비하중» 자리(중복 crate-level attribute 한 곳)에 넣었기 때문이고, 9곳 전건 삭제로 재측정하면 stable 0 · beta RED(rc=101 · double_must_use 진단 6건 — 전건 jvm/src/jvm.rs:140·404·438·779·791·1016) 이다 ⇒ ⑦의 그물도 «CI 만»이다. 계수가 2 라 「1개면 그 하나를 고쳐라」 규칙은 적용되지 않는다. 그리고 그 1개도 조용히 실패하지 않는다 — cargo 가 warning: excluded package(s) not found 를 찍고 빌드가 깨진다 ⇒ 문제는 침묵이 아니라 늦음이고, 근인은 「자산 목록이 없다」가 아니라 「로컬 DoD 가 CI 검사 5종 중 wasm32 clippy 한 줄을 빠뜨렸다」였다. 그 줄이 --exclude 크레이트 이름이 사는 유일한 자리다. ★결론은 그대로 「조항을 넣지 않는다」이나 논거를 다시 세웠다: ②와 ⑦은 다른 자산이 아니라 «한 근인의 두 얼굴»이다 — ②는 빠진 - run: 줄(target 축) · ⑦은 빠진 toolchain 축(beta) ⇒ 근인 하나(로컬 DoD 가 CI 매트릭스를 재현하지 않는다)를 고치면 둘 다 그물을 얻는다. DoD 에 cargo +beta clippy 를 넣자 ⑦의 9곳 전건 삭제가 로컬에서 RED(rc=101 · 진단 6건)로 잡힌다. 재개 조건도 축을 둘로 늘렸다(줄 문자열 축 + 매트릭스 차원 축) — 종전 명령은 rust: [stable, beta] 를 [stable] 로 줄여도 [stable, beta, nightly] 로 늘려도 0 을 냈다. ★[게이트② fix2 정정] 초판 문면의 「그물이 없던 자리 하나 = CI 명령 5줄」은 계수 «1» 시절의 파생 수다 — 계수가 2 가 되며 빠진 것은 «줄 하나»가 아니라 «두 축»(② target · ⑦ toolchain)이고, 따라서 DoD 는 5줄이 아니라 «6줄»이다. 그 파생 수가 REPORT.md · STATE.md · 워크로그 .md/.json · approach.md 에 남아 있던 것을 fix2 에서 전수 동기했다.", "changes": [ - "CLAUDE.md §Definition of Done — CI 가 치는 명령을 5줄 → ★6줄로(cargo +beta clippy --all -- -D warnings 추가). CI 는 이 검사를 6셀(toolchain 2 × OS 3)로 치는데 repo 에 rust-toolchain.toml 이 없어 맨 cargo 는 stable 1개로만 돈다 — toolchain 축을 안 적으면 「rust.yml 이 치는 그대로」가 거짓이 된다. 실측 근거(9곳 전건 삭제 시 stable 0 · beta error 7)와 OS 축은 로컬 재현 불가라 CI 가 유일한 그물이라는 고지를 함께 넣었다.", + "CLAUDE.md §Definition of Done — CI 가 치는 명령을 5줄 → ★6줄로(cargo +beta clippy --all -- -D warnings 추가). CI 는 이 검사를 6셀(toolchain 2 × OS 3)로 치는데 repo 에 rust-toolchain.toml 이 없어 맨 cargo 는 stable 1개로만 돈다 — toolchain 축을 안 적으면 「rust.yml 이 치는 그대로」가 거짓이 된다. 실측 근거(9곳 전건 삭제 시 stable 0 · beta RED — rc=101 · double_must_use 진단 6건)와 OS 축은 로컬 재현 불가라 CI 가 유일한 그물이라는 고지를 함께 넣었다.", "docs/upstream-sync-approach.md §4 결정 절 — ⑦행 라벨을 「깨져도 무해」에서 ★「CI 만」으로 정정(세 갈래 재측정 표 첨부) · 계수 1 → ★2 · 결정 논거 재구성(둘은 한 근인의 두 얼굴 · 「조항이 여럿이면?」 기각) · 재개 조건에 ★축② 「매트릭스 차원 대조」 추가 · 비용 논거의 수를 「다섯」 → ★「여섯」으로 정정하고 세는 명령 병기(★fix 회차는 이 파일 «한 자리»만 고쳤고 나머지 3자리는 fix2 에서 동기했다).", "STATE.md · REPORT.md · docs/worklog/2026-09-04-sync-contract-stale-assets-decision.{md,json} 갱신·신설.", "★.github/workflows/rust.yml 은 무접촉 — 크레이트 이름 1건은 S8 회차가 이미 고쳐 착지시켰다.", - "★[fix2] 「신고 ↔ 산출물」 전수 동기: ⒜「다섯 자리」 잔존 3자리(REPORT.md · 워크로그 .md · .json issues[2])를 «여섯»으로 통일하고 세는 법 병기 ⒝워크로그 .json verification 을 «지금의 사실»로 갱신(⑦ 라벨 정정 표지 · 근인 대조를 축 둘로 · 축② 착수값 1 · cargo +beta clippy 실행 기록) ⒞★전문 검색이 «반려 밖에서» 더 찾은 것 — 「CI 명령 5줄」 파생 수 6자리(REPORT×3 · STATE×1 · 워크로그 .md×3 · approach.md×1 · json summary) · 워크로그 .md 재개 조건 코드블록이 «축① 만» 싣고 있던 것 · 워크로그 .md 검증 표에 cargo +beta clippy 행이 없던 것." + "★[fix2] 「신고 ↔ 산출물」 전수 동기: ⒜「다섯 자리」 잔존 3자리(REPORT.md · 워크로그 .md · .json issues[2])를 «여섯»으로 통일하고 세는 법 병기 ⒝워크로그 .json verification 을 «지금의 사실»로 갱신(⑦ 라벨 정정 표지 · 근인 대조를 축 둘로 · 축② 착수값 1 · cargo +beta clippy 실행 기록) ⒞★전문 검색이 «반려 밖에서» 더 찾은 것 — 「CI 명령 5줄」 파생 수 6자리(REPORT×3 · STATE×1 · 워크로그 .md×3 · approach.md×1 · json summary) · 워크로그 .md 재개 조건 코드블록이 «축① 만» 싣고 있던 것 · 워크로그 .md 검증 표에 cargo +beta clippy 행이 없던 것.", + "★[fix3] ⒜「beta error 7」 수 라벨을 착지본 «18자리 전건»에서 「rc=101 · double_must_use 진단 6건(전건 jvm/src/jvm.rs)」으로 정정 — CLAUDE.md 1 · approach.md 3 · REPORT.md 3 · STATE.md 2 · 워크로그 .md 3 · json 6. ★그 수는 CLAUDE.md·approach.md 처럼 «모든 동기 회차가 읽는» 파일에 박혀 나가므로 다음 회차가 근거로 인용한다. ⒝verification 의 화해 문장(「101 은 lint 건 · 7 은 크레이트별 error 수」)을 철회 — 둘 다 반증됐다. ⒞잔존 4건 동기: 워크로그 .md 의 「문서 2파일」 2자리(:5 · :163) → 6파일(규범 2 + 기록 4) · json title 을 계수 2 문면으로 · 「채택 제안 둘/2건」 3자리를 «셋»으로 맞추고 s8#p0 를 열거. ⒟PR 제목도 계수 2 문면으로 고쳤다(착지 subject 에 남는다). ★«5건째»는 이 항목 자신이었다 — changes[0] 의 「beta error 7」. 찾은 경위가 중요하다: 필터 붙인 sweep 이 «0»을 냈는데 그것은 «거짓 0»이었다(zsh 가 따옴표 없는 $F 를 단어분할하지 않아 grep 이 파일 하나도 못 열고 stderr 로 죽었고 파이프의 -c 가 0 을 셌다). ★목록으로 다시 세니 나왔다." ], "deploy": { "sha": "", "urls": [] }, - "verification": "★[fix2 갱신 — 이 필드는 fix 회차에서 «통째로 미수정»이라 철회된 라벨을 싣고 있었다. 아래가 «지금의 사실»이다.]\n◆원 회차(2026-09-04 초판) 착수 실측: origin/main a76b305 · behind 0 · 열린 PR 0. 계약1⒝ 돌연변이(각각 깨뜨린 뒤 build/clippy/test 를 돌리고 원상 복구): ① tests/test_class_format.rs 의 test-data/ → test_data/ ⇒ build ok · clippy ok · test RED. ③ system.rs 의 setProperty 서술자 String → Object ⇒ test RED. ④ string.rs 의 Charset::resolve → from_name().unwrap() 우회 ⇒ test RED. ⑤ thread.rs 의 .instrument(span) 삭제 ⇒ clippy RED(미사용 import). ⑥ test_class_format.rs 의 ClassFormatError → Throwable ⇒ test RED. ② cargo clippy --workspace --exclude test_utils --target wasm32-unknown-unknown ⇒ rc=101 이고 문면은 warning: excluded package(s) `test_utils` not found in workspace + tokio wasm 컴파일 실패(조용한 통과가 아니다). ⑧ scripts/check-worklog-json.py 이동 ⇒ rc=2(로컬 DoD 와 CI 둘 다 그 경로를 친다). ⑦ jvm-bytecode/src/interpreter.rs 의 #[allow(clippy::double_must_use)] 삭제 ⇒ stable clippy ok · beta clippy 도 ok — ★★[게이트② request-changes 정정] 그 문장은 «거짓»이다. 돌연변이가 «비하중» 자리(같은 파일의 함수별 #[allow] 에 가려진 중복 crate-level attribute 한 곳)에 들어갔고, jvm/src/jvm.rs 의 7곳이 그대로 남아 있었다. 세 갈래 재측정(각 회 cargo fmt --all 로 삭제 artifact 정규화): interpreter.rs:1 만 삭제 ⇒ stable 0 / beta 0(초판 결과 재현) · jvm.rs:2 만 삭제 ⇒ 0 / 0 · ★9곳 «전건» 삭제 ⇒ stable 0 / ★beta error 7. ⇒ ⑦의 그물은 «CI 만»이고 ② 와 같은 칸이다 ⇒ 계수 = 2. ★allow 9곳을 지우지 마라(지우면 beta 3셀 red). ※검수 회신은 「8곳 · red 101」로 적었다 — 자리 수는 내 실측이 9곳(interpreter.rs:1067 포함)이고, 101 은 lint 발생 «건», 7 은 cargo 요약의 크레이트별 error 수다(같은 것을 다른 자로 잰 것). 판정은 동일하다.\n◆근인 대조[fix 갱신 — 초판은 «단일 축» 문면이었다]: 로컬 DoD 가 CI 의 «매트릭스»를 재현하지 않았다. 축①(target) = rust.yml 의 - run: 줄 5개 ↔ 초판 DoD 4개 ⇒ 차집합이 wasm32 clippy 한 줄. 축②(toolchain) = rust.yml 의 strategy.matrix rust: [stable, beta] ↔ 초판 DoD 에 beta 없음(repo 에 rust-toolchain.toml 이 없어 맨 cargo 는 stable 1개) ⇒ 차집합이 beta 축. 둘은 «한 근인의 두 얼굴»이다.\n◆재개 조건 세는 명령(회신 · approach.md §4 · 워크로그 .md §5 동일)의 값: 착수 시 ★축① 5 · ★축② 1 → 착지본 축① 0 · 축② 0. 축② 신설의 근거(3돌연변이 실측): rust: [stable, beta] → [stable] ⇒ 축① 0 · 축② 0(술어가 CI ∖ DoD 라 DoD 가 더 엄격한 것은 구멍이 아니다 — 옳은 값) · → [stable, beta, nightly] ⇒ 축② 1(축②만 반응) · - run: cargo doc --no-deps 1줄 추가 ⇒ 축① 1(축①만 반응).\n◆계약6[fix2 재실행 — 정정 후 DoD «6줄»을 문면 그대로]: cargo fmt --all -- --check rc=0 · cargo clippy --all -- -D warnings rc=0 · ★cargo +beta clippy --all -- -D warnings rc=0 · cargo clippy --workspace --exclude test-utils --target wasm32-unknown-unknown -- -D warnings rc=0 · cargo test --all rc=0 (554 passed / 0 failed / 1 ignored · baseline 554/0/1 동수 · 새 red 0) · python3 scripts/check-worklog-json.py rc=0. 돌연변이 전부 복구 확인 · .rs 변경 0 · allow 9곳 무접촉. 계약5: .github/workflows/rust.yml:55 가 이미 --exclude test-utils 이므로 이 회차는 무접촉.", + "verification": "★[fix2 갱신 — 이 필드는 fix 회차에서 «통째로 미수정»이라 철회된 라벨을 싣고 있었다. 아래가 «지금의 사실»이다.]\n◆원 회차(2026-09-04 초판) 착수 실측: origin/main a76b305 · behind 0 · 열린 PR 0. 계약1⒝ 돌연변이(각각 깨뜨린 뒤 build/clippy/test 를 돌리고 원상 복구): ① tests/test_class_format.rs 의 test-data/ → test_data/ ⇒ build ok · clippy ok · test RED. ③ system.rs 의 setProperty 서술자 String → Object ⇒ test RED. ④ string.rs 의 Charset::resolve → from_name().unwrap() 우회 ⇒ test RED. ⑤ thread.rs 의 .instrument(span) 삭제 ⇒ clippy RED(미사용 import). ⑥ test_class_format.rs 의 ClassFormatError → Throwable ⇒ test RED. ② cargo clippy --workspace --exclude test_utils --target wasm32-unknown-unknown ⇒ rc=101 이고 문면은 warning: excluded package(s) `test_utils` not found in workspace + tokio wasm 컴파일 실패(조용한 통과가 아니다). ⑧ scripts/check-worklog-json.py 이동 ⇒ rc=2(로컬 DoD 와 CI 둘 다 그 경로를 친다). ⑦ jvm-bytecode/src/interpreter.rs 의 #[allow(clippy::double_must_use)] 삭제 ⇒ stable clippy ok · beta clippy 도 ok — ★★[게이트② request-changes 정정] 그 문장은 «거짓»이다. 돌연변이가 «비하중» 자리(같은 파일의 함수별 #[allow] 에 가려진 중복 crate-level attribute 한 곳)에 들어갔고, jvm/src/jvm.rs 의 7곳이 그대로 남아 있었다. 세 갈래 재측정(각 회 cargo fmt --all 로 삭제 artifact 정규화): interpreter.rs:1 만 삭제 ⇒ stable 0 / beta 0(초판 결과 재현) · jvm.rs:2 만 삭제 ⇒ 0 / 0 · ★9곳 «전건» 삭제 ⇒ stable 0 / ★beta RED — rc=101 · double_must_use 진단 «6»건(전건 jvm/src/jvm.rs:140·404·438·779·791·1016) · cargo 요약 줄은 「could not compile `jvm` (lib) due to «6» previous errors」. ⇒ ⑦의 그물은 «CI 만»이고 ② 와 같은 칸이다 ⇒ 계수 = 2. ★allow 9곳을 지우지 마라(지우면 beta 3셀 red). ★★[fix3 철회 — 게이트② C1] 앞선 회차가 여기 적은 화해 문장(「101 은 lint 발생 «건» · 7 은 cargo 요약의 크레이트별 error 수」)을 «철회한다». ★두 문장 다 반증됐다: 101 은 «종료코드(rc)»이고, cargo 요약 줄은 「due to «6» previous errors」라고 말한다. ★「7」이 나오는 자는 /usr/bin/grep -c '^error' «하나뿐»이다 — 진단 6줄 + 요약 줄 1 = 7 이고, 그것은 이 필드가 스스로 내건 정의가 아니었다. ★«7 이 맞다»고 재주장하지 않는다. 옳은 라벨은 「rc=101 · 진단 6건」이다. ※검수 회신의 「8곳」과 내 실측 「9곳」의 차는 interpreter.rs:1067 을 세느냐이고, 판정(stable 0 ↔ beta RED)은 동일하다. ★그리고 「6」은 «하한»이다 — jvm-bytecode 는 jvm 에 의존하므로(jvm-bytecode/Cargo.toml `jvm = { workspace = true }`) jvm 이 컴파일에 실패하면 그 크레이트는 아예 린트되지 않는다. interpreter.rs 의 진단 0 은 «깨끗해서»가 아니라 «도달하지 못해서»다.\n◆근인 대조[fix 갱신 — 초판은 «단일 축» 문면이었다]: 로컬 DoD 가 CI 의 «매트릭스»를 재현하지 않았다. 축①(target) = rust.yml 의 - run: 줄 5개 ↔ 초판 DoD 4개 ⇒ 차집합이 wasm32 clippy 한 줄. 축②(toolchain) = rust.yml 의 strategy.matrix rust: [stable, beta] ↔ 초판 DoD 에 beta 없음(repo 에 rust-toolchain.toml 이 없어 맨 cargo 는 stable 1개) ⇒ 차집합이 beta 축. 둘은 «한 근인의 두 얼굴»이다.\n◆재개 조건 세는 명령(회신 · approach.md §4 · 워크로그 .md §5 동일)의 값: 착수 시 ★축① 5 · ★축② 1 → 착지본 축① 0 · 축② 0. 축② 신설의 근거(3돌연변이 실측): rust: [stable, beta] → [stable] ⇒ 축① 0 · 축② 0(술어가 CI ∖ DoD 라 DoD 가 더 엄격한 것은 구멍이 아니다 — 옳은 값) · → [stable, beta, nightly] ⇒ 축② 1(축②만 반응) · - run: cargo doc --no-deps 1줄 추가 ⇒ 축① 1(축①만 반응).\n◆계약6[fix2 재실행 — 정정 후 DoD «6줄»을 문면 그대로]: cargo fmt --all -- --check rc=0 · cargo clippy --all -- -D warnings rc=0 · ★cargo +beta clippy --all -- -D warnings rc=0(무돌연변이 기준선) · cargo clippy --workspace --exclude test-utils --target wasm32-unknown-unknown -- -D warnings rc=0 · cargo test --all rc=0 (554 passed / 0 failed / 1 ignored · baseline 554/0/1 동수 · 새 red 0) · python3 scripts/check-worklog-json.py rc=0. 돌연변이 전부 복구 확인 · .rs 변경 0 · allow 9곳 무접촉. 계약5: .github/workflows/rust.yml:55 가 이미 --exclude test-utils 이므로 이 회차는 무접촉.", "issues": [ - "★★[게이트② request-changes 정정] 초판의 계수 「1」은 틀렸다 — 「아무것도 없음」은 «2개»(② · ⑦)다. 근인은 돌연변이를 비하중 자리에 넣은 것이고(중복 crate-level attribute 한 곳만 삭제), 9곳 전건 삭제로 재측정하면 beta error 7 이다. ★그리고 그 차를 놓친 «같은 근인»이 하나 더 있었다: 브리프가 「제안 2 ↔ 검수 1」의 차를 해소하라고 요구했는데 초판이 그것을 안 짚었다 — 이제 답이 나왔다: ★«2»가 맞다.", + "★★[게이트② request-changes 정정] 초판의 계수 「1」은 틀렸다 — 「아무것도 없음」은 «2개»(② · ⑦)다. 근인은 돌연변이를 비하중 자리에 넣은 것이고(중복 crate-level attribute 한 곳만 삭제), 9곳 전건 삭제로 재측정하면 beta RED(rc=101 · double_must_use 진단 6건 — 전건 jvm/src/jvm.rs:140·404·438·779·791·1016) 이다. ★그리고 그 차를 놓친 «같은 근인»이 하나 더 있었다: 브리프가 「제안 2 ↔ 검수 1」의 차를 해소하라고 요구했는데 초판이 그것을 안 짚었다 — 이제 답이 나왔다: ★«2»가 맞다.", "★이 결정이 «막는» 것은 「우리 자산이 낡는 것」 자체가 아니라 「그것이 로컬에서 안 드러나고 CI 에서만 드러나는 것」이다. 낡음 자체는 여전히 일어나고, 다만 여섯 자리는 기계가(테스트·컴파일·clippy) 이미 잡는다.", "★잡는 그물이 축마다 다르다(테스트/컴파일/CI)는 것이 「조항 하나로 못 덮는다」의 근거다 — 조항으로 덮으면 이미 그물이 있는 «여섯» 자리에까지 사람 확인을 얹게 된다. ★세는 법: 돌연변이 표 8행 − 그물이 「CI 만」인 2행(② · ⑦) = 6(수리 후에는 8). ★[게이트② fix2 정정] 초판은 여기서 「다섯」이라 적었다 — 계수 «1» 시절의 파생 수이고, 같은 파일 issues[1] 의 「여섯」과 «자기모순»이었다. 이제 두 자리가 같은 수다.", "★S8 이 고친 CI 크레이트 이름 1건과 이 회차의 산출은 «다른 층»이다: 전자는 증상 1건, 후자는 그 증상이 늦게 드러난 경로. 티켓이 「고쳤다고 조항 결정을 건너뛰지 마라」고 못박은 자리다.", "머지하지 않았다 — 게이트②·③은 별 세션이다. ★게이트③은 등재 repo 라 merge_strategy: merge 필수(bin/queue-lint 검사22). upstream 동기 회차를 새로 열지 않았다(behind 0 · S9 없음).", - "★★[C1 승계 철회] 초판 후속 추천 3번(「double_must_use allow 가 이제 지워도 통과한다 — 정리할지는 별건」)을 «철회한다». 그 문장은 비하중 돌연변이에서 나온 것이고, 9곳을 전건 지우면 beta clippy 가 error 7 로 red 다. ★그대로 두면 다음 회차가 그 문장을 근거로 allow 를 지우고 beta 3셀을 빨갛게 만든다 ⇒ ★allow 9곳을 지우지 마라.", + "★★[C1 승계 철회] 초판 후속 추천 3번(「double_must_use allow 가 이제 지워도 통과한다 — 정리할지는 별건」)을 «철회한다». 그 문장은 비하중 돌연변이에서 나온 것이고, 9곳을 전건 지우면 beta clippy 가 RED 다(rc=101 · double_must_use 진단 6건). ★그대로 두면 다음 회차가 그 문장을 근거로 allow 를 지우고 beta 3셀을 빨갛게 만든다 ⇒ ★allow 9곳을 지우지 마라.", "★[C7 고지] ⑸ⓐ 처방(DoD 가 CI 명령을 verbatim 싣는 것)의 «개악»을 자동으로 잡는 것은 없다 — 누군가 DoD 블록에서 한 줄을 지우면 재개 조건 축①이 1 이 되지만, 그 축을 «돌리는 것»이 사람이다. ★기계 강제(예: DoD 블록과 rust.yml 을 대조하는 CI job)는 이 회차 범위 밖이고, 고칠 수 없으면 «고지»가 처방이다 ⇒ 여기 적는다.", "★[C7 고지 2] OS 축(macos·ubuntu·windows 3종)은 로컬에서 재현할 수 없다 — 그 차원은 CI 가 유일한 그물이고 재개 조건 대조의 대상이 아니다. 이것은 결함이 아니라 «알고 두는» 값이다." ], diff --git a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md index 0e808a33..4ad992ed 100644 --- a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md +++ b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.md @@ -1,8 +1,10 @@ # [2026-09-04] 「우리 자산이 낡는다」 상시 조항 «판정» — 넣지 않고 «구멍 하나»를 막았다 **티켓**: `rustjava-sync-contract-standing-clause-for-our-assets-going-stale` -**채택 제안 2건**: `2026-09-04-upstream-sync-s6#p1` · `2026-09-04-upstream-sync-s7#p1` -**성격**: 결정 회차 · 코드 변경 **0** · 문서 **2파일** +**채택 제안 ★3건**: `2026-09-04-upstream-sync-s6#p1` · `2026-09-04-upstream-sync-s7#p1` · ★`2026-09-04-upstream-sync-s8#p0` +**성격**: 결정 회차 · 코드(`.rs`) 변경 **0** · 문서 ★**6파일**(규범 2: `CLAUDE.md`·`docs/upstream-sync-approach.md` / 기록 4: `REPORT.md`·`STATE.md`·이 `.md`·`.json`) +★**[fix3 정정] 초판은 「제안 2건 · 문서 2파일」이었다** — 제안은 세 번째 판(`s8#p0`)이 도착해 **셋**이고, +「문서 2파일」은 **규범 문서만** 센 수라 이 PR 이 실제로 만지는 **6파일**과 어긋났다. --- @@ -19,7 +21,7 @@ | ④ | charset 라우팅(PR #5) | `Charset::resolve` → 폴백 우회 | ok | ok | ★**RED** | 있음 | | ⑤ | 수동 span(PR #4) | `.instrument(span)` 삭제 | ok | ★**RED** | ok | 있음 | | ⑥ | `ClassFormatError` 종류 단정(PR #3) | `ClassFormatError` → `Throwable` | ok | ok | ★**RED** | 있음 | -| ⑦ | `double_must_use` allow(PR #14) | ★**9곳 «전건» 삭제** | ok | ★**beta RED**(error 7) | ok | ★★**없음 — CI 만**(② 와 같은 칸) | +| ⑦ | `double_must_use` allow(PR #14) | ★**9곳 «전건» 삭제** | ok | ★**beta RED**(rc=101 · 진단 **6**건) | ok | ★★**없음 — CI 만**(② 와 같은 칸) | | ⑧ | 워크로그 잠금 스크립트 경로(PR #15) | 스크립트 이동 | — | — | — | 있음(로컬 DoD **와** CI 둘 다 · rc=2) | ★★**[2026-09-04 정정 — 게이트② `request-changes`] 초판의 ⑦행 「깨져도 무해」는 «거짓»이다.** @@ -32,7 +34,7 @@ | ⓪ 무돌연변이 | 0 | **0** | | ① `interpreter.rs:1` 만(★초판) | 0 | **0** ← 초판 결과 재현됨 | | ② `jvm.rs:2` 만(함수별 6 존치) | 0 | **0** | -| ★③ **9곳 전건** | 0 | ★**error 7** | +| ★③ **9곳 전건** | 0 | ★**RED** — rc=**101** · `double_must_use` 진단 **6**건(전건 `jvm/src/jvm.rs`) | ⇒ ★**⑦의 그물은 «beta clippy» 뿐이고 그것이 로컬 DoD 에 없었으므로 «CI 만» — ② 와 같은 칸이다.** @@ -91,7 +93,7 @@ error: could not compile `tokio` (lib) due to 1 previous error ← rc≠0 **⒜ ★계수가 «2»인데도 왜 여전히 조항이 아닌가**(★초판 논거 「1개니까」는 계수 정정으로 **무효** — 결론은 같고 이유가 다르다): - ★★**② 와 ⑦ 은 «다른 자산»이 아니라 «한 근인의 두 얼굴»이다 — «로컬 DoD 가 CI 매트릭스를 재현하지 않는다».** ②는 빠진 `- run:` 줄(**target** 축) · ⑦은 빠진 **toolchain** 축(beta). - ⇒ ★**근인 하나를 고치면 둘 다 그물을 얻는다**(실측: DoD 에 `+beta` 를 넣자 ⑦이 로컬에서 error 7 로 잡힌다). + ⇒ ★**근인 하나를 고치면 둘 다 그물을 얻는다**(실측: DoD 에 `+beta` 를 넣자 ⑦이 로컬에서 RED — rc=101 · 진단 **6**건 — 으로 잡힌다). - ★**「조항이 «여럿»이면?」도 기각한다** — 세 방향은 잡는 그물이 각각 달라 조항이 셋이 되고, 그중 둘은 ★**이미 기계가 지키는 자리에 사람 확인을 얹는 것**이다. - ★**사람 기억에 맡기지 않는다** — 추가한 것은 «체크리스트 항목»이 아니라 ★**실제로 도는 명령**이다. @@ -160,7 +162,9 @@ LC_ALL=C /usr/bin/grep -E '^[[:space:]]+rust: \[' .github/workflows/rust.yml \ | `cargo test --all` | **0** — ★**554 / 0 / 1** | | `python3 scripts/check-worklog-json.py` | **0** | -★**새 red 0**(baseline **554/0/1** 동수) · ★**돌연변이는 전부 복구**했고 워킹트리는 **문서 2파일**만 바뀌었다. +★**새 red 0**(baseline **554/0/1** 동수) · ★**돌연변이는 전부 복구**했고 ★**`.rs` 변경은 0**이다. +★**[fix3 정정] 초판은 「워킹트리는 문서 2파일만」이라 적었다** — 그 회차의 워킹트리 기준으로는 참이었으나, +★**이 PR 이 착지시키는 것은 문서 «6파일»**(규범 2 + 기록 4)이다. ★**같은 문장을 `verification` 에선 고치고 여기엔 남겼던 것**을 이제 닫는다. ## 8. 경계 준수 From 406a1da6060ed3262ca4b3fb6627c0c50eca4947 Mon Sep 17 00:00:00 2001 From: jun0 Date: Fri, 4 Sep 2026 18:10:28 +0900 Subject: [PATCH 5/5] docs: record gate3 execution in the ledger [rustjava-sync-contract-standing-clause-for-our-assets-going-stale] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit STATE.md 진행중 → 완료(게이트③ PR #25 · --merge · 등재 repo · 게이트② 5회차 만에 approve · 반려 넷이 전부 「신고한 것 ↔ 산출물」의 어긋남이었고 그 대가로 §4 마감 절차 4줄이 남았다 · 남은 minor F1 은 이 회차가 고치지 않았음을 명시) + worklog .json 게이트③ 집행 1줄 (동봉 전 head 가 핀과 일치했음 · fetch 를 먼저 쳐 거짓 일치를 막았음). 코드 변경 0. --- STATE.md | 53 +++++++++++-------- ...4-sync-contract-stale-assets-decision.json | 3 +- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/STATE.md b/STATE.md index a3a14fa9..465d4b6b 100644 --- a/STATE.md +++ b/STATE.md @@ -1,6 +1,28 @@ # STATE ## 진행중 +- [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-base` **`62cf0c6a` → `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-sync-contract-standing-clause-for-our-assets-going-stale] ★**「우리 자산이 낡는다」 상시 조항 «판정» — 결론: ★★넣지 «않는다». 대신 «구멍 하나»(로컬 DoD 가 CI 매트릭스를 재현하지 않던 것)를 막았다.** ★코드(`.rs`) 변경 0 · 규범 문서 2 + 기록 문서 4. @@ -32,29 +54,14 @@ ★**「6」은 «하한»이다** — `jvm-bytecode` 가 `jvm` 에 의존해 jvm 이 깨지면 그 크레이트는 **린트되지 않는다**. ⑵잔존 4건(워크로그 「문서 2파일」 2자리 · json `title` · 「채택 제안 둘」 3자리) + ★**PR 제목**까지 동기. ⑶★**«5건째»를 스스로 찾았다**(`changes[0]`) — ★**필터 걸린 sweep 이 «거짓 0»을 냈기 때문**이고(zsh 단어분할), - 그 교훈을 §4 마감 절차 **4번**으로 박았다. **PR 대기 — 게이트③ 미착지.** -- [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-base` **`62cf0c6a` → `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 대기 — 게이트③ 미착지.** - -## 완료 + 그 교훈을 §4 마감 절차 **4번**으로 박았다. + ★게이트③ 완료: PR #25 — ★★**`--merge` 착지**(★`--squash` 아님 · 등재 repo `contracts/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-base` `ba5797b` → `bd42427` · behind ★**12 → 0** · 부모 2개 ⇒ ★★**upstream 을 «완전히» 따라잡았다.** 착수 재측정(신 서식): **누적 8 · 델타 +8**(base `3fb08a8` · merge-base `ba5797b`) — 「재서 8 이었다」. diff --git a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json index 208fff0d..9b22273e 100644 --- a/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json +++ b/docs/worklog/2026-09-04-sync-contract-stale-assets-decision.json @@ -28,7 +28,8 @@ "머지하지 않았다 — 게이트②·③은 별 세션이다. ★게이트③은 등재 repo 라 merge_strategy: merge 필수(bin/queue-lint 검사22). upstream 동기 회차를 새로 열지 않았다(behind 0 · S9 없음).", "★★[C1 승계 철회] 초판 후속 추천 3번(「double_must_use allow 가 이제 지워도 통과한다 — 정리할지는 별건」)을 «철회한다». 그 문장은 비하중 돌연변이에서 나온 것이고, 9곳을 전건 지우면 beta clippy 가 RED 다(rc=101 · double_must_use 진단 6건). ★그대로 두면 다음 회차가 그 문장을 근거로 allow 를 지우고 beta 3셀을 빨갛게 만든다 ⇒ ★allow 9곳을 지우지 마라.", "★[C7 고지] ⑸ⓐ 처방(DoD 가 CI 명령을 verbatim 싣는 것)의 «개악»을 자동으로 잡는 것은 없다 — 누군가 DoD 블록에서 한 줄을 지우면 재개 조건 축①이 1 이 되지만, 그 축을 «돌리는 것»이 사람이다. ★기계 강제(예: DoD 블록과 rust.yml 을 대조하는 CI job)는 이 회차 범위 밖이고, 고칠 수 없으면 «고지»가 처방이다 ⇒ 여기 적는다.", - "★[C7 고지 2] OS 축(macos·ubuntu·windows 3종)은 로컬에서 재현할 수 없다 — 그 차원은 CI 가 유일한 그물이고 재개 조건 대조의 대상이 아니다. 이것은 결함이 아니라 «알고 두는» 값이다." + "★[C7 고지 2] OS 축(macos·ubuntu·windows 3종)은 로컬에서 재현할 수 없다 — 그 차원은 CI 가 유일한 그물이고 재개 조건 대조의 대상이 아니다. 이것은 결함이 아니라 «알고 두는» 값이다.", + "★[게이트③ 집행] PR #25 를 --merge 로 착지시켰다(등재 repo — 스쿼시는 계보를 접는다). 동봉 «전» head 가 검수 핀 a7d0f2a986b9fda36d4c1d1f1564aa5916a2b109 과 일치함을 확인했고(git fetch 를 먼저 쳐 거짓 일치를 막았다), 이 원장 동봉으로 head 가 움직인 전/후 sha 는 머지 회신에 적었다. 배포 워크플로 0개 ⇒ 배포 0. 코드(.rs) 변경 0." ], "proposals": [ {