chat 経由ではなく、利用者から直接受けた回。依頼文は 1 行だった。
html2md のリポジトリ・ファイル群を調査。適切か? 矛盾等は無いか? コードレビュー・品質レビューして。
N:/ai-agent-tools は共通ルールが用途を明示している共有環境なので、確認なしで参照してよい。ただし他プロジェクトなので書き換えは一切しない。
| 項目 | 内容 |
|---|---|
| 読んだもの | C# 3 本(Html2Md 8 ファイル・ConvertEncoding 4・Text 6)、html2md-ps.ps1(64KB の参照実装)、check-contrast.ps1・check-markdown.ps1・contrast/check-contrast.cjs、テスト 4 本と tests/cases 16 ファイル、資料 8 対(README・USAGE-FOR-PROJECTS・計画 5 本・クラス名の取り決め)、issues.html、ビルド 3 本の cmd |
| 実行したもの | --help 系、text read、text find、git log ・ git ls-files。いずれも書き込みを伴わないもの |
| 実行しなかったもの | テストスイート 4 本(tmp/ に書き込むため)、text edit ・ text write、convert-encoding --to |
| 追跡ファイル | 75 件。*.exe は .gitignore で除外され、csc.exe で直接ビルドする形(csproj を持たない) |
この回は「ワークフローで並列に読む」形を初めて使った。対象が 3 ツール + 参照実装 + 8 対の資料で、1 本の読み進めでは 1 周が終わらない規模だったため。
11 観点で並列に読み、出た指摘 1 件ごとに反証役を当てた。反証役には「あなたの役目は反証すること。迷ったら棄却」と渡し、指摘者の読み違い・別の場所での手当て・資料に書かれた断りを探させた。
| 段 | 数 | やったこと |
|---|---|---|
| Review | 11 | 変換エンジン / 表・SVG・強調・検査 / convert-encoding / text / C# 版と ps1 の乖離 / CLI と資料 / 資料同士 / 構成とルール準拠 / テスト / 安全性 / HTML/MD の同期 |
| Verify | 55 | 各観点の上位 5 件に反証役を 1 人ずつ。下位は当てていない |
| Critic | 1 | 「食い違い無し」の報告を疑い、誰も見ていない場所を読む役 |
合計 67 エージェント・エラー 0。確定 46 件 / 棄却 9 件 / Critic の追加 7 件。
検証を各観点の上位 5 件で打ち切ったため、47 件が未検証で残った。行番号の裏取りもしていない。黙って落とすと「全部見た」と読めてしまうので、一覧をそのまま相手に渡して検証を依頼した(4 章)。
棄却 9 件のうち 3 件は、疑った点が計画書に既に書いてあった。これは相手の資料の質が高いことの裏返しでもある。
| 出した指摘 | 棄却の理由 |
|---|---|
text find が .gitignore を見ない |
p260907-01-text-tools に「既定で外すのは .git と先頭 _ の 2 つだけ。既定で外しすぎない」と理由付きで明記されており、コードと仕様が一致していた。USAGE も仕様書への参照を張っている |
| root 直下配置と PATH の理由が資料に無い | html2md-plan.html 256・314-329 に「この形の代償」節があり、「git clone しただけでは変換できない/置き場への依存は受け入れる」まで書いてあった |
root の CLAUDE.md と local-rules.html が無い |
挙げた影響 3 つ(SJIS を Edit で壊す・C# 5 の制約・exe と ps1 の一致)が、共通ルールと build.cmd のコメントと run-tests.cmd で既に手当てされていた。残るのは置き場の乱れだけ |
この 1 件目は、こちらが最初に「有力」と利用者へ報告していたもの。反証役が仕様書を読んで覆した。先に出した見立てを、同じ回のうちに訂正できたのが今回の収穫である。
欠陥は新しいツールほど集中していた。text(2 日前追加)と convert-encoding のデコード側、そして「静かに間違った結果を返す」類に偏っている。
src/Html2Md/Inline.cs 204-208。セルの縦棒を \| にする処理が、コードスパンを退避した後の文字列に走る。退避キーに縦棒が含まれないため <code> 内の縦棒は素通りし、Converter.cs 98 で表の組み立て後に戻される。
このリポジトリ自身の資料が既に壊れている。notes/10_plan/html2md-plan.md 54 行は local-llm 列が ❌ になっており(HTML では ✅)、5 実装の比較表を逆に読む。p260907-01-text-tools.md 289 行は --to <用途> の説明が途中で切れ、cmd 以外の用途名が渡せることが Markdown 側から分からない。
自前の検査も気づけない。Checks.Normalize(108-110)が比較前に \| を縦棒に戻したうえで縦棒とバッククォートを落とすため、差分が消えて exit 0 で通る。
src/ConvertEncoding/Converter.cs 90。ExceptionFallback は GetStrict()(37-56)に仕込まれているが、その唯一の呼び出し(122 行)は GetBytes なので、効くのはエンコード方向だけ。読み取りは GetRaw() のため、読めなかったバイトが別の文字に化けたまま書き戻されて終了コード 0 が返る。--force の有無に関係しない。
41 85 40 42 … UTF-8 として不正/CP932 として妥当 → 自動判定は SJIS
… 85 40 は CP932 未割当だが best-fit で U+30FB「・」へ
--to ps1 … 41 E3 83 BB 42 を書いて exit 0
… 再変換しても 85 40 には戻らない(「・」は 81 45)
上書きが起きるのは変換先が --from と別の種別のときで、--to utf8 はバイト保持分岐(Program.cs 216)、--to cmd は U+FFFD が CP932 に無いため exit 4 で止まる。「表現できない文字があれば止まる」保証が片方向にしか無いのが根っこ。
src/Text/WriteCmd.cs 78・91-92。中身の取り方が --in → 標準入力 → 第 2 引数の順で、標準入力は「リダイレクトされているか」だけを見て、中身が空でも採用する。エージェントのシェルは標準入力が常にリダイレクト状態である。
text write foo.cmd --to cmd "@echo off"
→ foo.cmd が 0 byte。「書きました: foo.cmd [sjis/crlf]」と出て exit 0
既存ファイルなら中身が消える。54-64 行の File.WriteAllBytes は無条件。この 1 件だけは実行して確かめていない(text write を実行禁止としたため、経路と標準入力の状態からの判断)。
src/Text/Engine.cs 256。既定フォールバックのままの Encoding.GetEncoding(932) で、src/Text 全体に未対応文字の検出経路が 1 つも無い。絵文字・ハングル・簡体字などが ? になったファイルを書き、「書きました」「置換しました」だけを出して exit 0 を返す。
同じ危険に convert-encoding は ExceptionFallback + 書き込み前検査を張って exit 4 で止める。同じリポジトリで守り方が違う。
資料の側も揃っていない。USAGE-FOR-PROJECTS.md 209 行は「SJIS・UTF-16・UTF-8BOM でも壊さず読み・検索・編集・書き込みができる」と無条件に書き、失われる文字への断りが無い。README.md 338 行の「元に戻せない/exit 4 で終える」は convert-encoding の章の記述である。p260907-01-text-tools.md 10 行は strict 検出を将来分として挙げるが、対象を write と書いており edit は挙げていない。
| 場所 | 何が起きるか |
|---|---|
ConvertEncoding/Program.cs129-151 | --read / --info が --from hex でファイルを上書きする。展開分岐が read/info(184・196)より前にあり、併用の拒否は 131 の --to だけ |
ConvertEncoding/Program.cs211-216 | --to ps1 --from ps1 が BOM 無しのまま「変換済み」と表示して 0 を返す。5.1 で日本語が壊れる ps1 が残る |
Text/FindCmd.cs31-32 | text find <語> <パス>(Grep と同じ書き方)が黙って cwd を探す。0 件で無出力 exit 1 なので、無いのか対象違いか区別できない |
Text/EditCmd.cs46-47 | read は最終行の ContentEnd まで、edit は text.Length まで。末尾が改行のファイルでは read の合言葉が edit で必ず不一致。read し直しても抜け出せない |
Html2Md/Converter.cs338-353 | figure は最初の svg と figcaption だけを見て 269 で全体を読み飛ばす。<img>・2 つめ以降の svg・<p>・表が消える。仕様の表どおりだが、決着 4「テキストが消えないことを先にした」と食い違う |
Html2Md/Checks.cs107 | Normalize の列挙に details・summary が無く「HTML に無い文言」と誤検出。details を含むページは毎回 exit 1。run-tests.ps1 138 は -gt 1 で許容するため自リポジトリでも落ちない |
Html2Md/Svg.cs29-31 | id 分岐だけページ名の接頭辞が無く、101 行は存在確認なしの書き出し。同フォルダの別ページが同じ id を使うと上書き。検査は実在だけ見る |
Html2Md/Program.cs83・85 | --dir / --exclude は既定を置き換える(足さない)。USAGE の言うとおり --dir docs だけ渡すと notes/ が対象外になり、それでも「指摘なし」exit 0 |
html2md-ps.ps11382 / 1351 / 416 ほか | 参照実装との乖離 3 件。① ps1 は pre/code を落とさず href を拾うため html-class-rules.html 234 のコード例で誤検出 ② ps1 に「これから生成するファイル」の一覧が無く -DryRun が全件リンク切れ exit 1 ③ バッジと callout の対応表が 2 本で手書きされ、同じ HTML から違う Markdown が出る |
run-tests.ps1 201 | 一致検査が片方向(exe が生成した鍵だけ比較)。md-skip と extra で ps1 が余分に生成しても [OK]。この 2 ケースは「生成してはいけない」ことが要点 |
tag-spec.html 181 | 「ここに書いた挙動は tests/cases で固定してある」と書くが、rowspan/colspan・num の右寄せ・callout の種別振り分けの入力が 1 つも無い。colspan が壊れて 1 列ずれても 10 ケース全部緑 |
Converter.cs 273 / 58 | md-skip が li・tr・td・dt・span に効かない(27 ブロックタグだけ)/段落外の a が地の文を割り、範囲をまたぐ strong が消える |
p260908-01 180 | --to utf8 を「その場で UTF-8/LF 化」と書いているが、--to に改行を書かなければ改行は変わらない。受領時に「記述ミス」として直した箇所と同じ形 |
p260906-01 454 / 855 | SJIS 先頭バイト範囲が 3 章と 8 章で食い違う。3 章どおりに実装し直すと、資料自身が例に挙げる外字が「不正」になる |
.editorconfig ・ .gitattributes ・ .vscode/settings.json が 3 点とも無い / .gitignore の 4 行では先頭 _ のフォルダと .claude の共有分を取りこぼす / run-all-tests.ps1 は 1 本が例外で落ちると残りが走らず集計も出ない / 閉じた課題 i260907-01 の .exe 表記が 3 本の cmd に残っている(調査範囲を SJIS の 3 件に限ったため ASCII の 3 本が漏れた) / check-contrast -Path . -Recurse は contrast/selftest.html を拾うので自リポジトリでは常に 4 件・exit 1 / README の目次とツール表に text 一式が無く、ビルド節も 3 本の cmd を書いていない。
#649(2026/09/08)で html2md のルームへ投稿した。high 4 件と medium を場所付きで並べ、low は場所だけの列挙にし、棄却した 9 件も「出し直さないための記録」として添えた。
未検証の 47 件は、一覧をそのまま渡して検証を依頼した。「見つけた側の主張のままで、行番号も裏取り前。実物と突き合わせて成り立つものだけ拾ってほしい」と明記した。こちらで確度を上げるより、実装を持っている側が見るほうが速いと判断した。
| 観点 | 未検証 | 主なもの |
|---|---|---|
| 表・SVG・強調・検査 | 7 | 強調の両端の空白が消えて語が繋がる(Emphasis.cs 136)/先頭・末尾が * でも記法にする/--exclude の効き方が説明と違う |
| 資料同士 | 6 | convert-encoding の記録値が資料間で違う/済の課題の本文が「まだ提示していない」/クラス名の取り決めの更新日が改訂前 |
| 安全性 | 6 | パスのマスキングが text だけにある/check-contrast の一時ファイルが固定名で共有場所/内容ファイル・標準入力を組の曖昧さを無視して復号 |
| text | 5 | --no-number でも ◆ ヘッダが出る/edit のバイト位置が再エンコードに依存/書き戻しは直書きで中断すると残らない |
| 構成 | 5 | 研究ノート 1 件が Markdown だけで HTML の原本が無い/contrast/ が src・tests の外/追跡ファイルに subst ドライブの既定値がリテラルで入っている |
| 変換エンジン | 4 | 入れ子 section で InSection が戻らない/クエリ付きリンクはパスを解決できない/範囲外の数値参照で実行全体が中断 |
| convert-encoding | 4 | --force は ? ではなく best-fit 置換/--dump --bytes が大きいと何も出ない/書き込み失敗時に一時ファイルが残る |
| CLI と資料 | 3 | 必須指定エラーが実際の受付と違う/計画書が決めた CodePages 登録を実装が入れていない |
| C# 版と ps1 | 3 | クラス名の照合が ps1 だけ大小文字を無視する/対象 0 件のときの終了コードが違う |
| テスト | 3 | 「書き換えない」の判定が長さだけで常に真の節を含む/テスト本体がランチャー側に直書き |
| HTML/MD の同期 | 1 | HTML の原本を持たない md が 1 件だけある |
対応あり同じ日のうちに 3 通の返信が届いた。high 4 件はすべて本物と確認され、修正・コミット済み(回帰テスト付き)。
| 返信 | 内容 |
|---|---|
| #654 (09/08 17:51) |
high 4 件を検証して全て本物と確認、修正してコミット。text write の 0 バイト上書き → 第 2 引数を stdin より優先+空 stdin で停止/text edit・write の黙った ? → strict 検査で exit 5/convert-encoding のデコード側 → 再エンコード経路に検査 exit 4(バイト保持・--force は対象外)/表セル内 code の | → 退避前にエスケープ、壊れていた .md を再生成。medium・low と未検証 47 件はそちらで検証する |
| #659 (09/08 18:59) |
text・convert-encoding の medium と未検証分を修正: find の位置引数パス、--lines 無し digest の全文一致、--read / --info + --from hex の併用拒否、--no-number の ◆ ヘッダ抑止、--dump の int オーバーフロー、edit / write の原子的書き込み。設定ファイル(.gitignore / .editorconfig / .gitattributes / .vscode)も共通ルールの形に。テストは convert-encoding 98・text 50・html2md 10 |
| #664 (09/08 19:15) |
details / summary の誤検出、README・USAGE・cmd の整合まで修正。残るのは html2md 中核コンバータ(figure の中身が消える・早期復号でリンク文字欠落・svg id 衝突・md-skip の範囲・段落外 a)と exe / ps1 の乖離。回帰リスクと仕様判断(figure は仕様表と決着 4 が食い違う)を伴うため個別に判断。指摘は課題 i260908-01〜04 に集約 |
2026-09-10 の定期レビュー(html2md #1、発言 #732)で現物と突き合わせた。high 4 件はいずれも解消を確認。前回 low の 3 点(cmd の .exe 表記・設定ファイル 3 点・README のツール表)も解消済み。残ったのは「同じ修正が参照実装 html2md-ps.ps1 に入っていない」形が 5 件で、そちらの記録に書いた。
並列に読ませると、同じ根に 2 方向から当たることがある。表セル内の縦棒は「コードを読む観点」と「生成物を読む観点」の両方から出た。片方だけなら見立てで終わったが、実際に壊れている行を突きつけられたので確度が上がった。
反証役を挟むと、自分の第一報を訂正できる。text find の .gitignore の件は、こちらが「有力」として利用者へ先に報告していた。指摘を出す側と潰す側を分けたから、同じ回のうちに引っ込められた。
上限で切った分を黙って落とさない。47 件を捨てれば「11 観点を全部見た」と読めてしまう。数と一覧を出して、誰が続きを持つかまで書くところまでが 1 回である。