Skip to content

Commit ce69b70

Browse files
author
jun0
committed
[rustjava-adopt-class-format-mutation-audit-p0] docs(state): 회차 기록 · worklog 쌍 · 제안 #p0 채택 기록
1 parent b177732 commit ce69b70

4 files changed

Lines changed: 122 additions & 0 deletions

File tree

‎REPORT.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,23 @@
11
# REPORT
2+
## [2026-09-17] 픽스처가 «정확히 한 곳만» 망가졌는가 — 감사의 «나머지 반쪽» (rustjava-adopt-class-format-mutation-audit-p0)
3+
- 무엇을: 채택 제안 `2026-09-16-class-format-mutation-audit#p0`. ★**제품 코드 0줄**(감사 스크립트 1개).
4+
- 왜: 종전 감사는 「테스트가 자기 가지의 개악에 죽는가」를 물었다. 이 회차는 ★**「픽스처가 정확히 한 곳만 망가졌는가」**를 묻는다.
5+
★**두 곳이 망가진 픽스처는 한 곳을 고쳐도 테스트가 계속 green** 이고, 나머지 하나가 «더는 덮이지 않는다»는 사실이 **조용히** 묻힌다.
6+
- ★★**판정식을 «로드»가 아니라 «바이트 동일»로 잡았다** — 제안은 「수리 후 로드되는가」를 제시했으나
7+
생성기가 결함을 **인자로 받으므로** 더 강한 검사가 더 싸게 된다:
8+
`generator(결함) == 커밋본`(생성기가 여전히 그 파일을 설명한다) **그리고** `generator(수리) == generator(표준)`(그 밖에 차이가 없다).
9+
★**강한 이유**: 우리 로더가 «마침» 신경 쓰지 않는 둘째 결함은 로드 검사를 통과하지만 이 검사는 통과하지 못한다. ★**싼 이유**: JVM 이 필요 없다.
10+
- ★★**결과: 검사 18건 «전건» single-defect · 결함 없는 유효 파일 5건 · rc=0.**
11+
(`indy` 근접실패 6 · `ldc` 9 · `cp` 3 / 무결함 5 = `MakeConcat`·`LdcMethodHandle`·`LdcMethodType`·`LdcDynamic`·`Ldc2WDynamic`)
12+
⇒ 제안이 예고한 「'이미 괜찮다'는 한 줄」이 맞았다. ★**그래도 값한다** — 그 규율은 회차마다 «적용»돼 왔을 뿐
13+
★**코퍼스 전체로 «측정»된 적이 없어**, 지금까지 그것은 «사실»이 아니라 «습관»이었다.
14+
- ★**덮지 않는 것을 스크립트 머리에 «적었다»**(조용히 건너뛰지 않았다): javac 산출물(결함 0) · 적법하나 미구현(결함 0) ·
15+
★**테스트 «안»에서 바이트 패치로 만드는 픽스처**(디스크에 없어 읽을 수 없다 — 그쪽 근거는 각 주석이고 **더 약하다**).
16+
- ★**개악 2종 전건 red**: **M1** 둘째 결함 심기 → `MULTI-DEFECT` **rc=1** · **M2** 커밋본 1바이트 반전 → `GENERATOR DRIFT` **rc=2**.
17+
★**M2 가 첫 등식을 지킨다** — 생성기가 커밋본을 설명하지 못하면 위 판정은 전부 공허해지고, 스크립트는 통과 대신 그렇게 «말한다».
18+
- 검증: `cargo test --all` **576 passed / 0 failed / 1 ignored**(★Rust 무접촉이라 불변) · worklog 46/0 · parity 대칭차 0.
19+
- ★후속: 이 감사를 ★**상시 검사로 올릴지 «결정»하라**(S) — 안 돌리는 감사는 썩는다 ↔ DoD 8번째 명령 + parity 갱신이 대가다.
20+
221
## [2026-09-17] `StringConcatFactory.makeConcat` 도 링크한다 — 단 «이유는 제안이 적은 것이 아니다» (rustjava-adopt-link-stringconcatfactory-p0)
322
- 무엇을: 레시피 없는 진입점 `makeConcat` 을 링크한다. ★**실행기 무접촉** — 콜사이트 인자 수로 **레시피를 합성**한다.
423
- 왜: 채택 제안 `2026-09-16-link-stringconcatfactory#p0`.

‎STATE.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44
(없음 — 2026-09-16 실측: 착수 시 진행 티켓 0 · 열린 PR 0. ※「열린 PR 0」은 ★**이 회차 PR 착지 시점 기준**이다 — 회신 시점에는 그 PR 자신이 열려 있다)
55

66
## 완료
7+
- [rustjava-adopt-class-format-mutation-audit-p0] ★★**픽스처 «단일 결함» 감사 — 18/18 통과.** 채택 제안
8+
`2026-09-16-class-format-mutation-audit#p0`(worklog json `adoptedProposals` 기록). ★**제품 코드 0줄**(감사 스크립트 1개).
9+
★**판정식을 «로드»가 아니라 «바이트 동일»로** 잡았다(생성기가 결함을 인자로 받으므로 더 강하고 더 싸다):
10+
`generator(결함)==커밋본` **그리고** `generator(수리)==generator(표준)`.
11+
★결과 **검사 18 전건 single-defect · 무결함 유효 파일 5 · rc=0** ⇒ 회차마다 «적용»돼 온 규율을 처음으로 «측정»했다.
12+
★**덮지 않는 것을 스크립트에 적었다**(javac 산출물 · 적법-미구현 · 테스트 안 바이트 패치분).
13+
★개악 2종 red(둘째 결함 심기 **rc=1** · 커밋본 1바이트 반전 **rc=2**) · `--all` **576/0/1**(Rust 무접촉이라 불변).
714
- [rustjava-adopt-link-stringconcatfactory-p0] ★★**`StringConcatFactory.makeConcat` 도 링크한다 — 단 «이유는 제안이 적은 것이 아니다».**
815
채택 제안 `2026-09-16-link-stringconcatfactory#p0`(worklog json `adoptedProposals` 기록).
916
★**제품 동작 변경**: `makeConcat` 콜사이트가 **거부 대신 실행**된다. ★**실행기(`concat_with_constants`)는 한 줄도 안 바뀌었다.**
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"schema": "worklog/v1",
3+
"date": "2026-09-17",
4+
"taskId": "rustjava-adopt-class-format-mutation-audit-p0",
5+
"summary": "Audit the hand-assembled fixtures for single-defectness — is each file broken in exactly one way? Answered by byte equality against the canonical build rather than by loading, which is both stronger and cheaper. Result: 18 defective fixtures checked, all single-defect; 5 carry no defect at all.",
6+
"changes": [
7+
"test-data/src/audit-fixture-single-defect.py: repairs each generated fixture's named defect and requires the bytes to equal the canonical build"
8+
],
9+
"verification": [
10+
"audit: 18 checked / 18 single-defect / 5 no-defect (valid files) / rc=0",
11+
"mutation M1: plant a second defect (NotFactoryDescriptor also gets reference kind 7) -> MULTI-DEFECT, rc=1",
12+
"mutation M2: flip one byte of a committed fixture -> GENERATOR DRIFT, rc=2",
13+
"cargo test --all unchanged (this round adds no Rust)"
14+
],
15+
"issues": [
16+
"The audit is a standalone script, not wired into DoD or CI. An audit nobody runs rots; whether this property is worth a permanent check is a separate decision, argued in the proposal below.",
17+
"Three fixture classes are outside its reach and are named in the script header rather than silently skipped: javac output (no defect), legal-but-unimplemented files (no defect), and fixtures byte-patched inside a test (not on disk)."
18+
],
19+
"adoptedProposals": [
20+
"2026-09-16-class-format-mutation-audit#p0"
21+
],
22+
"proposals": [
23+
{
24+
"title": "Decide whether single-defectness is a standing check or a one-off",
25+
"plainSummary": "The audit passes today. Nobody runs it tomorrow.",
26+
"userBenefit": "A fixture that grows a second defect stops covering what its test claims, and the test keeps passing — which is exactly the silence this round measured away.",
27+
"why": "Every fixture is generated from a parameterised generator, so the check costs one python3 invocation and no JVM. The repository's own doctrine says a rule kept only in prose is the worst state: 'the rule exists and has no effect'.",
28+
"tradeoff": "It would be an eighth DoD command, and check-dod-ci-parity.py then has to carry it in both directions — the parity lock is deliberately strict about that. Against: the property is stable by construction (the generators take the defect as a parameter), so the check may earn nothing for years.",
29+
"effort": "S",
30+
"target": "CLAUDE.md, .github/workflows/rust.yml"
31+
}
32+
]
33+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# 2026-09-17 — Is each fixture broken in exactly one way?
2+
3+
`taskId: rustjava-adopt-class-format-mutation-audit-p0` ·
4+
adopts `2026-09-16-class-format-mutation-audit#p0`
5+
6+
The mutation audits so far asked one half of the question: *does each test fail when the thing it
7+
names is broken?* This is the other half — **is each fixture broken in exactly one way?**
8+
9+
It matters because the failure is silent. A fixture that is wrong twice keeps its test green after
10+
one of the two is repaired, and nothing anywhere says that the other stopped being covered.
11+
12+
## The test, and why byte equality rather than loading
13+
14+
The proposal suggested "remove the named defect and check the file now loads". Every fixture here
15+
is produced by a generator that takes the defect **as a parameter**, which makes a stronger test
16+
available at lower cost:
17+
18+
```
19+
generator(name, …defect…) == the committed fixture (the generator still describes it)
20+
generator(name, …repaired…) == generator(name, …canonical…) (and nothing else differs)
21+
```
22+
23+
Stronger, because a second defect our loader happens not to care about would pass a loading test
24+
and fail this one. Cheaper, because it needs no JVM — it is bytes against bytes.
25+
26+
## Result
27+
28+
```
29+
검사 18건 · 결함 없음(유효 파일) 5건 · 합계 23건 · rc=0
30+
```
31+
32+
**All 18 defective fixtures are single-defect.** The five others carry no defect at all and are
33+
listed rather than skipped, so the census stays complete:
34+
35+
| family | checked | axis examples |
36+
|---|---|---|
37+
| `indy` near misses | 6 | owning class · method name · descriptor · reference kind · static argument |
38+
| `ldc` | 9 | `ldc2_w` width · illegal tags 13/14/19 · class file version · missing BootstrapMethods · static argument index · bootstrap index · duplicate table |
39+
| `cp` | 3 | tag 13 / 14 / 19 |
40+
| no defect | 5 | `MakeConcat`, `LdcMethodHandle`, `LdcMethodType`, `LdcDynamic`, `Ldc2WDynamic` — valid files whose feature is unimplemented |
41+
42+
This is the "row of already fine" the proposal predicted. It is still worth having: the discipline
43+
had been applied per round and **never measured across the corpus**, so until now "all our fixtures
44+
carry one defect" was a habit, not a fact.
45+
46+
## What it does not cover — said in the script, not only here
47+
48+
* **javac output** (`Lambda`, `StringConcat`, `ConstantKinds`, `LambdaKinds`) — not defective;
49+
"exactly one" does not apply to zero.
50+
* **Legal-but-unimplemented** files — same; the file is valid and the feature is missing.
51+
* **Fixtures byte-patched inside a test** — they never exist on disk, so this script cannot read
52+
them. Their single-defectness rests on the comment beside each, which is weaker, and that is the
53+
honest limit of this round.
54+
55+
## Mutations
56+
57+
| | mutation | result |
58+
|---|---|---|
59+
| **M1** | plant a second defect (`NotFactoryDescriptor` also gets reference kind 7) | **rc=1** · `MULTI-DEFECT — 수리 후에도 1 바이트 남는다` |
60+
| **M2** | flip one byte of a committed fixture | **rc=2** · `GENERATOR DRIFT — 커밋본을 재현하지 못한다` |
61+
62+
M2 is the half that keeps the first equation honest: if the generator stops describing the
63+
committed bytes, every verdict above is vacuous, and the script says so instead of passing.

0 commit comments

Comments
 (0)