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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ jobs:
steps:
- uses: actions/checkout@v7
- run: python3 scripts/check-worklog-json.py
- run: python3 scripts/check-ledgers-frozen.py

# a conflict resolution that drops one side's work leaves no other trace: no marker, mergeable
# CLEAN, suite green. fetch-depth 0 because the check needs the merge commits and their parents,
Expand Down
24 changes: 24 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,30 @@ basename** in `docs/worklog/`: `YYYY-MM-DD-<slug>.md` (the human axis) and
`YYYY-MM-DD-<slug>.json` (the machine axis). Without the `.json`, the proposal is
**structurally unreachable** by the cockpit "후속 작업 추천" panel — its scanner reads `.json` only.

**Since 2026-09-25 the `.md` is written by every round, and it is the round record.** `REPORT.md`
and `STATE.md` are frozen (ticket `rustjava-report-state-md-per-round-files-port-from-wie`, ported
from wie `a5091df6`). Every PR used to add to the top of those two shared files, so each landing
made every open sibling conflict: **42 union merges out of 61 PRs** from 2026-09-10 to 2026-09-25.
A file named after its own round has no shared line to fight over. So:

- **Every round** creates `docs/worklog/YYYY-MM-DD-<slug>.md`. Its first line is
`## [YYYY-MM-DD] title (<ticket-id>)`, followed by the 무엇을·왜·사용자 영향 lines that used to go
into `REPORT.md`. Add the `.json` sibling when the round leaves proposals or disposes of them,
as below.
- **진행중** is `gh pr list -R Jun025/RustJava`. **완료** is this directory:
`grep -H '^## \[' docs/worklog/*.md | sort -r`. **다음** is `docs/next.md`, and a round edits it
only when a prerequisite chain or an item outside the cards changes. Adopting or declining a
card is recorded in the round's own `.json`, which is not a shared file.
- `scripts/check-ledgers-frozen.py` pins both frozen files by hash. It runs in the `worklog_json`
CI job and in the local DoD, and any edit to either file turns it red. If a merge conflict
offers you one of those files, take `main`'s side and move your entry into your own `.md`.
- Names are `date-slug`, not wie's serial `NNNN--`. The slug is the round's own name, so two open
PRs never pick the same filename. That also means this repo does not need wie's
serial-collision checker.

Text below that says "into `REPORT.md`" means the round's `.md` from 2026-09-25 on. It is kept
as written because it records decisions that were made at the time.

**Do not invent a schema** — these key names are shared with otterpebble/dodu/qts. The consumer
(`/api/proposals`, `scanRepoSimple`) reads exactly these:

Expand Down
12 changes: 7 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
cargo clippy --workspace --exclude test-utils --target wasm32-unknown-unknown -- -D warnings
cargo test --all
python3 scripts/check-worklog-json.py
python3 scripts/check-ledgers-frozen.py
python3 scripts/check-dod-ci-parity.py
python3 scripts/check-named-exception-classes-are-loadable.py
python3 scripts/check-merge-dropped-symbols.py
Expand All @@ -53,10 +54,11 @@
`test-utils` 로 개명(S8)했을 때 **로컬에서는 어떤 명령으로도 드러나지 않고 CI 에서만** 빨개졌다.
⇒ ★**CI 가 검사를 늘리거나 «매트릭스 차원»을 바꾸면 이 블록도 «같이» 고쳐라**(아래 재개 조건이 둘 다 센다).
※OS 축(3종)은 로컬에서 재현할 수 없다 — ★**그 차원만은 CI 가 유일한 그물이고, 그것은 «알고 두는» 값이다.**
- 착수·완료마다 STATE.md 의 "진행중/완료/다음" 을 갱신하고, 완료 시 REPORT.md 상단에
`[YYYY-MM-DD]` 요약 3줄(무엇을·왜·사용자 영향) + 후속 추천을 append 한다.
- ★**후속 추천을 적었으면 `docs/worklog/YYYY-MM-DD-<slug>.{md,json}` 한 쌍도 남긴다** —
`.json` 이 없으면 그 추천은 cockpit 「후속 작업 추천」 패널에 **구조적으로 도달하지 못한다**
(규약·되돌릴 수 = `AGENTS.md` §Round Worklog).
- ★**회차 기록은 회차마다 새 파일 `docs/worklog/YYYY-MM-DD-<slug>.md` 에 쓴다.** 첫 줄에
`## [YYYY-MM-DD] 제목 (<ticket-id>)`, 그 아래 무엇을·왜·사용자 영향 3줄을 적는다. 후속 추천을 적었으면
같은 basename 의 `.json` 도 쓴다. `.json` 이 없으면 그 추천은 cockpit 「후속 작업 추천」 패널에 **닿지 못한다**.
★**`REPORT.md`·`STATE.md` 는 2026-09-25 에 동결됐다 — 건드리지 마라**(`scripts/check-ledgers-frozen.py` 가 red 를 낸다).
진행중 = `gh pr list -R Jun025/RustJava` · 완료 = `docs/worklog/` · 다음 = `docs/next.md`
(규약 = `AGENTS.md` §Round Worklog).
- ★작업 티켓의 **완주 지점 = PR 오픈**이다. 머지는 게이트② 검수자가 approve 와 같은 턴에 집행한다(`<id>-merge` 는 예외 경로)
(`main` 직push 0 — `AGENTS.md` §Git Workflow).
1 change: 1 addition & 0 deletions REPORT.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# REPORT
> ★**동결 — 2026-09-25 이후 기록은 `docs/worklog/YYYY-MM-DD-<slug>.md`(회차마다 새 파일) · 다음 = `docs/next.md` · 진행중 = `gh pr list -R Jun025/RustJava`.** 이 파일을 고치면 `scripts/check-ledgers-frozen.py` 가 red 를 낸다(규약 `AGENTS.md` §Round Worklog).
## [2026-09-24] «파일 끝에 남는 바이트» 거부가 클래스가 끝난 위치를 말한다 (rustjava-2026-09-23-validation-rules-name-their-position-adopt-p0)
- 무엇을: parse-level 거부 3종을 재어, 정확한 위치를 쥔 «extra bytes» 하나만 `Location::ByteOffset` 으로 오프셋을 싣는다. «truncated or unparsable» 은 nom 오프셋이 손상 지점을 절반 가까이 빗나가 두었고, «version < 45.0» 은 가리킬 자리가 없다.
- 왜: 채택 제안 `2026-09-23-validation-rules-name-their-position#p0`. 제안의 예상(«truncated» 가 후보, 나머지는 없음)은 측정으로 뒤집혔다.
Expand Down
1 change: 1 addition & 0 deletions STATE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# STATE
> ★**동결 — 2026-09-25 이후 기록은 `docs/worklog/YYYY-MM-DD-<slug>.md`(회차마다 새 파일) · 다음 = `docs/next.md` · 진행중 = `gh pr list -R Jun025/RustJava`.** 이 파일을 고치면 `scripts/check-ledgers-frozen.py` 가 red 를 낸다(규약 `AGENTS.md` §Round Worklog).

## 진행중
(없음 — 2026-09-17 실측: 착수 시 열린 PR **4건**(#56·#57·#58·#59). ★**내 경로와 겹치는 것은 둘**이다 —
Expand Down
25 changes: 25 additions & 0 deletions docs/next.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# 다음

`STATE.md` `## 다음` 을 옮긴 것이다(2026-09-25 · `rustjava-report-state-md-per-round-files-port-from-wie`).
그 뒤로 `STATE.md` 는 동결됐다. 규칙은 `AGENTS.md` §Round Worklog 에 있다.

★**이 파일에는 카드가 표현하지 못하는 것만 적는다**: 선행 사슬과 카드 밖 항목(PR 번호). 열린 카드 목록은 적지 마라 — 아래 명령으로 세라.
옮기기 전 `STATE.md` 의 「순서 없음」 4줄 중 2줄은 이미 닫혀 있었다(`…bootstrap-argument-index-and-tag#p0`·`…unraisable-error-variant#p0`).
직접 적어 둔 목록은 이렇게 낡는다.

```sh
# 열린 카드 = proposals − adopted − declined (tower 의 «− injected» 술어가 아니다)
python3 -c "
import json,glob,os
refs=[];done=set()
for f in sorted(glob.glob('docs/worklog/*.json')):
d=json.load(open(f));b=os.path.basename(f)[:-5]
refs+=[f'{b}#p{i}' for i in range(len(d.get('proposals',[])))]
done|=set(d.get('adoptedProposals',[]))|set(d.get('declinedProposals',[]))
print(*[r for r in refs if r not in done],sep='\n')"
```

1. **선행 사슬**: `2026-09-17-link-lambdametafactory#p1`(결정) → `#p0`(어댑터) → `java.lang.invoke` 패키지(카드 없음 · 근거 = `rustjava-runtime/src/classes/java/lang/invoke` **부재**) → `2026-09-17-string-concat-recipe-arity#p1`.
2. **카드 밖**: PR **#81**. 2026-09-23 에 `CONFLICTING` 이었고 충돌 해소가 먼저다.

지난 판(⓪-사료·①~⑤)은 동결된 `STATE.md` `## 다음` 아래에 그대로 있다.
6 changes: 6 additions & 0 deletions docs/worklog/2026-09-25-ledgers-frozen-per-round-files.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## [2026-09-25] `REPORT.md`·`STATE.md` 동결 — 회차 기록은 회차별 파일로 (rustjava-report-state-md-per-round-files-port-from-wie)
- 무엇을: 두 원장 머리에 동결 1줄을 달고 해시로 고정했다(`scripts/check-ledgers-frozen.py` · CI `worklog_json` job + 로컬 DoD). 회차 기록은 `docs/worklog/YYYY-MM-DD-<slug>.md`, 진행중은 `gh pr list`, 다음은 `docs/next.md` 로 옮겼다.
- 왜: 모든 PR 이 두 파일 맨 앞에 덧붙여서 착지 1회가 열린 형제 PR 전건을 충돌시켰다. 2026-09-10~25 PR 61건에 합집합 머지가 42건이었다(`origin/main` 실측). wie `a5091df6` 선례를 포팅했다.
- 사용자 영향: 없음(문서·검사). 회차 PR 이 공유 줄을 만지지 않으니 원장 충돌 재회차가 사라진다. ★열린 PR #81 은 두 원장을 만진다 — 착지 전에 그 항목을 자기 worklog `.md` 로 옮겨야 한다.

wie 와 다른 점: 새 `docs/report/NNNN--` 연번 디렉터리 대신 기존 `docs/worklog/` 의 `date-slug` 이름을 쓴다(파일 이름이 겹치지 않으니 연번 충돌 검사기가 필요 없다). `STATE.md` 도 한 번에 전부 동결했다(wie 는 진행중·완료를 두 번에 걸쳐 포인터로 바꿨다). 과거 기록은 옮기지 않았다.
37 changes: 37 additions & 0 deletions scripts/check-ledgers-frozen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env python3
"""Refuse any change to the frozen ledgers `REPORT.md` and `STATE.md`.

Why: until 2026-09-25 every PR prepended to these two files. Each landing then conflicted with
every open sibling PR: 42 union merges out of 61 PRs between 2026-09-10 and 2026-09-25. Round
records now go to per-round files in `docs/worklog/` (AGENTS.md §Round Worklog), and the two files
are kept as history. A round that goes back to the old habit would bring the conflicts back, so
the files are pinned by hash here.

A merge conflict in either file means your side added an entry. Take `main`'s side and move the
entry into your round's `docs/worklog/*.md`.
"""

import hashlib
import sys
from pathlib import Path

FROZEN = {
"REPORT.md": "dd2f16f4e0da590919fcfcdb71d4f9ad6105d1c58b8284472fdaff1b0dab9079",
"STATE.md": "38a53e3c415a609b265334e69a59cfd4b31cc4ad4a284b567d9377c47f5b6e02",
}

root = Path(__file__).resolve().parent.parent
bad = []
for name, want in FROZEN.items():
path = root / name
got = hashlib.sha256(path.read_bytes()).hexdigest() if path.exists() else "missing"
if got != want:
bad.append(f"{name}: sha256 {got} != frozen {want}")

if bad:
print("check-ledgers-frozen: FAIL — these files are frozen since 2026-09-25", file=sys.stderr)
for line in bad:
print(f" {line}", file=sys.stderr)
print(" write the round entry to docs/worklog/YYYY-MM-DD-<slug>.md instead (AGENTS.md §Round Worklog)", file=sys.stderr)
sys.exit(1)
print(f"check-ledgers-frozen: ok — {len(FROZEN)} frozen ledgers unchanged")
Loading