Skip to content

Restore ONIX 2.1 from git history instead of the network - #70

Open
kogai wants to merge 3 commits into
mainfrom
claude/schema-from-git-history
Open

kogai wants to merge 3 commits into
mainfrom
claude/schema-from-git-history

Conversation

@kogai

@kogai kogai commented Sep 13, 2026

Copy link
Copy Markdown
Owner

editeur.org が自動リクエストに CAPTCHA を返すため make schema が機能せず、コード生成が止まっています(詳細は #58)。2.1 についてはこれを回避できます。

足元にありました

コミット 9352123 は、ビルド時ダウンロード方式に移行する際に 2_1_rev03_schema/ を削除しました。その親コミットには XSD 6 本がそのまま残っています。 git show で、ネットワークを一切使わずに取り出せます。

make schema-from-history を追加しました。手元での実行結果です。

$ make schema-from-history
restored schema/v2/ONIX_BookProduct_CodeLists.xsd
restored schema/v2/ONIX_BookProduct_Release2.1_reference.xsd
restored schema/v2/ONIX_BookProduct_Release2.1_short.xsd
restored schema/v2/ONIX_XHTML_Subset.xsd
restored schema/v2/ONIX_XHTML_Subset_reference.xsd
restored schema/v2/ONIX_XHTML_Subset_short.xsd

$ make -n schema
mkdir -p schema
npx bazelisk build onix_v3      ← v2 は要求されない

計 1.8 MB、src/Lib.hs が読む schema/v2/ONIX_BookProduct_Release2.1_reference.xsd を含みます。schema/% は prerequisite を持たないパターンルールなので、ディレクトリが存在すれば make はダウンロードを試みません。

EDItEUR のファイルはコミットしていません

これは意図的です。schema/ は .gitignore 済みなので、このリポジトリが配布するものは何も変わりません。追加しているのは自前の make ターゲットだけで、第三者の著作物ではありません。

したがって #58 が提起しているライセンスの論点には触れません。復元されるファイルは、この変更の有無にかかわらず 2021 年からこのリポジトリの公開履歴に存在しています。

3.0 / 3.1 には効きません

履歴にあるのは 2.1 だけです。最新スキーマへの追従には、依然として #58 の判断(vendoring / ミラー / --distdir)が必要です。

確認したこと・していないこと

  • 6 ファイルすべての復元と、make -n schema が v2 を要求しなくなることを実行して確認
  • 生成の実行そのものは未確認。 この環境に GHC / stack が無く(haskell.org が egress ポリシーでブロック)、CI も生成を回していません。「スキーマが揃う」ところまでの確認です
  • レビュアーサブエージェント未実施。 アカウントが月間の利用上限に達しており、起動できません(HTTP 429)

🤖 Generated with Claude Code

https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z


Generated by Claude Code

editeur.org answers automated requests with a CAPTCHA, so `make schema`
cannot fetch anything and code generation is stuck. For 2.1 that turns
out to be avoidable: commit 9352123 deleted 2_1_rev03_schema/ when the
build moved to downloading at build time, and its parent still has all
six XSDs. `git show` reaches them with no network at all.

`make schema-from-history` restores them into schema/v2. Verified here:
all six files land (1.8 MB), including the XHTML subset, and `make -n
schema` afterwards only tries to download v3 — the pattern rule treats
schema/v2 as satisfied once the directory exists.

This deliberately does not commit any EDItEUR file. schema/ is
gitignored, so what this repository distributes is unchanged, and the
licensing question ADR-0003 raises is untouched: the target is our own
code, and the files it recovers have been in this repository's public
history since 2021 either way.

It does not help 3.0 or 3.1 — neither is in the history — so the schema
acquisition decision in ADR-0003 still has to be made for those.

Not reviewed by a subagent: the account is at its monthly spend limit and
review agents fail to start.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z

kogai commented Sep 14, 2026

Copy link
Copy Markdown
Owner Author

総評

動きます。狙いも機構の選び方も妥当で、ブロッカーはありません。 一時クローンで make schema-from-history を実行し、6 ファイルすべてが復元され、内容が履歴中の blob と SHA-1 一致 (バイト単位で同一) であること、6 本とも XML として well-formed であること、xs:include が 2 本 (ONIX_BookProduct_CodeLists.xsd / ONIX_XHTML_Subset.xsd) でどちらも復元対象に含まれること、src/Lib.hs が読む schema/v2/ONIX_BookProduct_Release2.1_reference.xsd が存在すること、その後の make -n schema が v3 しか取りにいかないことを確認しました。git checkout ではなく git show を選んだのも正しい判断です (根拠は後述)。一方で、shallow clone で失敗したとき中途半端な schema/v2 が残り、以後 make schema が v2 を「済み」とみなす点と、このターゲットだけでは make generated/go/v2 は依然として通らない点は、実際に再現できたので直すか明記するかしてほしいところです。あと ADR-0003 との整合 (この方式は「検討した他の選択肢」に留まっていて、決定されたのは --distdir のみ) の扱いも一言ほしいです。


指摘

必須

なし。

推奨 1: shallow clone で失敗し、空の schema/v2 が残って make schema を黙らせる

  • 場所: Makefile L54-60 (schema-from-history レシピ全体)

  • 問題: git clone --depth 1 したツリーで実行すると fatal: invalid object name '9352123^' で落ちます。|| exit 1 は正しく伝播していて make も Error 1 を返すのですが (これは想定どおり)、mkdir -p schema/v2 (L56) と、リダイレクトが git show の実行前にファイルを作る性質のせいで、0 バイトの ONIX_BookProduct_CodeLists.xsd を含む schema/v2/ が残ります。 ターゲットは .PHONY なので make による削除も効きません。実測:

    $ git clone --depth 1 --branch claude/schema-from-git-history ... shallow && cd shallow
    $ make schema-from-history
    mkdir -p schema/v2
    fatal: invalid object name '9352123^'.
    make: *** [Makefile:57: schema-from-history] Error 1
    $ ls -l schema/v2/
    -rw-r--r-- 1 root root 0 ONIX_BookProduct_CodeLists.xsd
    $ make -n schema
    mkdir -p schema
    npx bazelisk build onix_v3        ← v2 は「済み」扱いになっている
    
  • なぜ効くか: schema/% は prerequisite を持たないパターンルールなので、ディレクトリの存在だけが判定基準です。PR 本文が正しく指摘しているこの性質が、失敗時には裏目に出ます。以後 make schema / make build は v2 を取りにいかなくなります。

    なお 「壊れたまま静かに誤った生成物が出る」ことはありません。ここは念のため確かめました。xsd-parser の getSchema は xs:include を親ファイル基準の相対パスで再帰的にたどり (Xsd.hs の goInclude / combineURIs)、ローカルファイルのパースに失敗すると fail で例外になります。実際 ONIX_XHTML_Subset.xsd を 0 バイトにして xmllint に同じ include を解決させると WXS schema ... failed to compile になります。したがって実害は「分かりにくい失敗に化ける」ことであって、サイレントな誤生成ではない、というのが調べた範囲での結論です。

  • 修正案: 前段でオブジェクトの存在を確認して人間が読めるメッセージを出し、書き込みは一時ディレクトリに対して行って最後に差し替える (全部そろったときだけ schema/v2 が生える)。ついでに完全 SHA にしておくと将来の曖昧さも消えます (9352123^ = 0134b80e0f713b7049f11860e1535fd466c15b39)。

    ONIX_V2_TREE := 0134b80e0f713b7049f11860e1535fd466c15b39:2_1_rev03_schema
    
    .PHONY: schema-from-history
    schema-from-history:
    	@git cat-file -e $(ONIX_V2_TREE)/ONIX_BookProduct_Release2.1_reference.xsd 2>/dev/null || { \
    		echo "error: ONIX 2.1 の blob がこのクローンにありません。"; \
    		echo "  shallow clone の場合: git fetch --unshallow を実行してください。"; \
    		exit 1; \
    	}
    	@rm -rf schema/v2.tmp && mkdir -p schema/v2.tmp
    	@for f in $(ONIX_V2_FILES); do \
    		git show $(ONIX_V2_TREE)/$$f > schema/v2.tmp/$$f || { rm -rf schema/v2.tmp; exit 1; }; \
    		echo "restored schema/v2/$$f"; \
    	done
    	@rm -rf schema/v2 && mv schema/v2.tmp schema/v2

    git fetch --unshallow してから再実行すれば通ることも確認済みです。なお現行 CI (.github/workflows/test.yml) は make test と //e2e/go:snapshot_test の 2 ジョブだけで、どちらもこのターゲットを呼ばないので、今日ただちに CI が壊れるわけではありません。将来 CI から呼ぶ可能性を考えると、actions/checkout の既定が depth 1 である以上、ガードは入れておく価値があります。

推奨 2: これ単体では make generated/go/v2 は通らない

  • 場所: Makefile L62 (schema: schema/v2 schema/v3) との関係

  • 問題: generated/go/% → build → schema → schema/v3 という依存があるため、v2 だけそろえても make 経由の v2 生成は v3 の取得で止まります。実測:

    $ ls schema/       # v2 のみ
    v2
    $ make -n generated/go/v2
    mkdir -p schema
    npx bazelisk build onix_v3        ← ここで CAPTCHA に当たって失敗する
    cp -r /v3/ schema/v3/
    stack build --fast
    stack exec onix-exe -- --schemaVersion v2 --language go
    
  • なぜ重要か: PR 本文 (および ADR-0003 の該当項) の「これで v2 のコード生成は editeur.org なしで動く」は、厳密には 「v2 のスキーマがそろう」までしか意味しません。実際に v2 を生成するには、別途 --distdir で v3 を用意するか、stack exec onix-exe -- --schemaVersion v2 --language go を直接叩く必要があります。

  • 修正案: コード変更は不要だと思います。PR 本文か Makefile のコメントに一行足して、「このターゲットは v2 のスキーマを用意するところまで。make build は v3 を要求するので、生成は stack exec 直叩きか --distdir の併用が要る」と明記してください。

推奨 3: BUILD.bazel の onix2p1 と 2 ファイルずれている

  • 場所: Makefile L46-52 (ONIX_V2_FILES)
  • 問題: 9352123 が削除したのは 8 ファイルで、BUILD.bazel の onix2p1 filegroup も 8 エントリ (readme.txt / readme2.txt を含む) を列挙しています。このターゲットは XSD 6 本だけを復元します。
  • なぜ重要か: 生成には影響しません (xs:include は XSD 2 本だけを指しており、6 本の中で閉じていることを確認済み)。ただし ADR-0003 が EDItEUR の著作権表示の一次確認に使ったのがまさにこの readme.txt / readme2.txt です。make schema の出力と揃えるという意味でも、著作権表示をファイルと一緒に置いておくという意味でも、2 本足しておくほうが筋が良いと思います。
  • 修正案: ONIX_V2_FILES に readme.txt と readme2.txt を追加。あるいは「XSD のみ意図的に復元」とコメントに明記。

推奨 4: AGENTS.md に載っていない

  • 場所: AGENTS.md L47-56 のコマンド一覧、および L62-63 の「make schema は現在 editeur.org から取得できない」の段落
  • 問題: 新しいターゲットがどこにも文書化されていません。L62-63 は「生成系を動かすには手元に zip を用意する必要がある」と言い切っており、v2 についてはこの PR で状況が変わります。
  • 修正案: コマンド一覧に make schema-from-history # ONIX 2.1 のみ、git 履歴から復元 (ネットワーク不要) を追加し、L62-63 の段落に v2 の例外と推奨 2 の但し書きを足す。

推奨 5: ADR-0003 との整合

  • 場所: docs/adr/0003-editeur-schema-acquisition.md の「検討した他の選択肢」、および Makefile L44 のコメント
  • 問題: ADR-0003 はこの方式を 「検討した他の選択肢」の一つとして、まったく同じ 6 ファイルのループ付きで記載していますが、「決定」節で採用されたのは --distdir のみです。加えて当該項には「ただしメンテナが意図的に削除した経緯があるため、戻すかどうかは判断が要る」とあります。この PR は Makefile コメントから ADR-0003 を参照していますが、ADR 側は「この方式を採る」とは書いていない状態です。
  • なぜ重要か: 記録された決定とコードが食い違ったままになります。ライセンス面については PR 本文の主張に同意です — schema/ は .gitignore 済みで EDItEUR のファイルは 1 バイトもコミットされないので、再配布の論点には触れません (.gitignore と実際のツリーで確認済み)。争点は「再配布してよいか」ではなく「この方式を正式な手段として採ったのか」です。
  • 修正案: ADR-0003 に短い追記 (または ADR-0004) を入れて、「v2 に限り git 履歴からの復元を make schema-from-history として採用する。EDItEUR のファイルはコミットしないため再配布には当たらない。3.0/3.1 は引き続き --distdir」と記録する。

任意 1: mkdir -p schema/v2 だけ @ が付いていない

  • 場所: Makefile L56
  • L57 の for ループには @ が付いているのに L56 には無いため、出力に mkdir -p schema/v2 だけが混じります。推奨 1 の修正案を採れば自然に解消します。

任意 2: 変数名が中身と合っていない

  • 場所: Makefile L45
  • ONIX_V2_COMMIT という名前ですが、中身はコミットではなく <rev>:<path> (tree への参照) です。ONIX_V2_TREE などのほうが読み違えにくいです。

git show と git checkout について (指摘ではなく確認)

git show の選択は正しいです。 2 点、実測で差が出ました。

  1. インデックスを汚さない。 git checkout <commit> -- <path> は対象パスを インデックスにステージします。試したところ git status に AD 2_1_rev03_schema/... が出ました。作業ツリーを共有しているクローンでこれをやると、他の作業を巻き込みます。git show は副作用ゼロです。
  2. 改行変換を受けない。 core.autocrlf=true の設定下で比較すると、git checkout は smudge フィルタを通すため 238909 → 245288 バイト に膨らみました (CRLF 変換)。git show は blob のバイトをそのまま出すので 238909 バイトのまま、ハッシュも blob と一致します。復元後のファイルは ONIX_XHTML_Subset*.xsd の 3 本が元々 CRLF、他の 3 本が LF という混在ですが、これは EDItEUR 配布物そのままの状態で、git show はそれを忠実に保ちます。

このリポジトリには .gitattributes が無く core.autocrlf も未設定なので現状では差が出ませんが、Windows の開発者が触った瞬間に効いてきます。

Makefile に置くべきか

置くべきだと思います。 ADR-0003 が既に同じ 6 ファイルのループを散文で書いており、手順が文書とコードの 2 箇所に散るくらいなら、実行可能な形が 1 つあるほうが良いです。特に ONIX_XHTML_Subset.xsd は xs:include の解決先なので、手でコピペする運用だと落とした瞬間に生成が壊れます。build: に繋いでいないのも正しい判断で、あくまで避難ハシゴとして独立させる形を支持します。残りは推奨 4 / 5 のとおり、AGENTS.md と ADR から参照が張られていれば十分です。


確認したこと / できなかったこと

確認したこと

読み取り専用の一時クローン (/tmp 配下) で実行しました。共有クローンの作業ツリーは触っていません。

$ make schema-from-history
mkdir -p schema/v2
restored schema/v2/ONIX_BookProduct_CodeLists.xsd
... (6 本すべて)

$ ls -l schema/v2/          # 計 1,852,375 バイト
1143192  ONIX_BookProduct_CodeLists.xsd
 238909  ONIX_BookProduct_Release2.1_reference.xsd
 227332  ONIX_BookProduct_Release2.1_short.xsd
  80910  ONIX_XHTML_Subset.xsd
  81020  ONIX_XHTML_Subset_reference.xsd
  81012  ONIX_XHTML_Subset_short.xsd
  • バイト単位の一致: 各ファイルの git hash-object が git rev-parse 9352123^:2_1_rev03_schema/<f> と 6 本すべて一致 (例: ONIX_BookProduct_CodeLists.xsd = 98bb74e9...)。サイズも git ls-tree -l の blob サイズと完全一致。
  • XML の妥当性: 6 本とも xml.etree でパース成功。さらに xmllint --schema で ONIX_BookProduct_Release2.1_reference.xsd をスキーマとしてコンパイルさせ、include 解決を含めて WXS のコンパイルが通ることを確認 (出力されたのは「自分自身を検証しようとした」ことによる No matching global declaration のみで、スキーマ自体のコンパイルエラーは無し)。
  • include の網羅性: 6 本を grep した結果、xs:include / xs:import は ONIX_BookProduct_Release2.1_reference.xsd L98-99 と ..._short.xsd L98-99 のみ。指し先は ONIX_BookProduct_CodeLists.xsd と ONIX_XHTML_Subset.xsd の 2 本で、どちらも復元対象に含まれる。ONIX_XHTML_Subset_reference.xsd / _short.xsd は誰からも include されていないが、BUILD.bazel の onix2p1 に載っているので同梱は妥当。
  • schemaRoot の存在: src/Lib.hs L81-86 の V2 パス ./schema/v2/ONIX_BookProduct_Release2.1_reference.xsd が復元後に存在。
  • include の解決方式: xsd-parser (stack.yaml の extra-deps、commit e08a37c) の src/Xsd.hs を読み、getSchema が goInclude / combineURIs で親ファイル基準の相対パス解決を再帰的に行うこと、ローカルファイルのパース失敗が fail (例外) になることを確認。
  • make -n schema: 復元後、v2 は要求されず v3 のみ (npx bazelisk build onix_v3)。PR 本文の主張どおり。
  • 失敗時の伝播: shallow clone で make が Error 1 / exit 2 を返すことを確認 (|| exit 1 は正しく効いている)。同時に残骸の 0 バイトファイルも確認 (推奨 1)。
  • git fetch --unshallow 後の再実行: 6 本すべて正常に復元。
  • ファイル集合の照合: 9352123 が削除したのは 8 ファイル (XSD 6 + readme 2)。BUILD.bazel の onix2p1 も 8 エントリ。本 PR は 6 本 (推奨 3)。
  • git show vs git checkout: 上記セクションのとおり、インデックス汚染と core.autocrlf=true 下の 245288 バイト化を実測。
  • 9352123 が main の祖先であること: git merge-base --is-ancestor 9352123 origin/main → YES。したがって当該 blob は到達可能で、通常の git gc で消えることはありません。履歴が書き換えられた場合のみ壊れます (推奨 1 のガードがそのケースも拾います)。

確認できなかったこと

  • 実際のコード生成 (stack exec onix-exe): この環境に GHC / stack が入っておらず、haskell.org も egress ポリシーでブロックされているため未実行です。PR 本文の申告と同じ制約です。「スキーマがそろい、XSD として include 込みでコンパイルできる」ところまでが確認範囲で、生成物の中身は見ていません。
  • editeur.org 由来のファイルとの突き合わせ: editeur.org に到達できないため、履歴中の 2.1 rev03 が EDItEUR 配布物と同一かは確認していません (ADR-0003 と同じ制約)。
  • make schema の v3 パスを実際に走らせること: サンドボックスから npm レジストリ経由で bazelisk を取得できず (npm error ENOVERSIONS)、make -n によるドライラン確認に留めました。BZL_BIN が空に展開されて cp -r /v3/ schema/v3/ と表示されるのはそのためで、この PR とは無関係の既存挙動です。

Generated by Claude Code

claude and others added 2 commits September 14, 2026 02:23
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
Review found the failure mode that mattered. In a shallow clone — which is
what actions/checkout produces by default — `git show 9352123^:...` fails,
but the shell had already created the redirect target, leaving a 0-byte
XSD behind. `schema/%` then treats schema/v2 as satisfied and `make
schema` stops trying to fetch v2, so the next build reads a truncated
schema.

Restore into schema/v2.tmp and mv it into place only once every file is
written, and guard the whole thing with `git cat-file -e` so a shallow
clone gets a message naming the fix instead of a git error. Verified in a
`--depth 1` clone: the target fails with that message, no schema/
directory is created at all, and `make -n schema` still wants both v2 and
v3.

The pin is now the full SHA of the parent (0134b80), not `9352123^`.

Also correct a claim this PR made. `make generated/go/v2` does not work
after restoring: it goes through `build` -> `schema`, which wants v3 too
and still hits the CAPTCHA — confirmed with `make -n generated/go/v2`.
Generating v2 means calling the executable directly, and the Makefile
comment, AGENTS.md and ADR-0003 now all say so.

Restore all eight files rather than six. readme.txt and readme2.txt are
in the deleted tree and in BUILD.bazel's onix2p1 filegroup, and they are
the files that carry EDItEUR's copyright notice.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants