Website Copy Review(ウェブサイトコピーレビュー)
ウェブサイトのコードベースを、非技術系のレビューアがページごとに読み、マークアップできるドキュメントに変換します。 すべての文字列にはアドレス(Ref コード)が保持されているため、その編集をソースに機械的に適用できます。
このように構築された理由
ウェブサイトのコピーは散文ではありません。マークアップ内の固定レイアウトスロットに配置された何百もの短い文字列です。そのため:
- 散文のダンプを変更履歴付きで返しても、マークアップに正しく配置できない挿入のぼやけとして戻ってきます。そこで、文字列ごとに1行、Ref コードを付けます。
- 4単語のカード見出しを12単語に変更するレビューアはレイアウトを壊し、Word からそれを確認できません。そこで、制約のある行には文字数と平易な長さのガイダンスを表示します。
- レビューアはコードを見ることはありません。そこで、各行には平易な言葉でその種類(「ボタンラベル」、「代替テキスト」)が表示され、各ページセクションにはライブサイト上の場所が表示されます。
ドキュメントはページごとに上から下に読める必要があります(トーンとナラティブを判断できるように)が、各文字列を個別にアドレス可能に保ちます。
バンドルファイル
scripts/merge_and_verify.py、scripts/build_review_docx.py、references/extraction-brief.md、assets/pages.example.json はこのファイルと一緒に配置されています。これらが存在しない場合(スキルが SKILL.md のみでインストールされた場合)、~/my-skills/website-copy-review/ または brianitsup/website-copy-review リポジトリを探してください。どちらもアクセスできない場合は、ドキュメントレイアウトを独自に作成するのではなく、ユーザーにその旨を伝えてください。実行間でレイアウトが変わってはいけません。
基本ルール
- 読み取り専用。 リポジトリを編集しないでください。すべての出力は、ユーザーがリポジトリ内を要求しない限り、スクラッチパッドに出力します。
python-docxをグローバルではなく、スクラッチパッドの仮想環境にインストールしてください:python3 -m venv <scratch>/venv && <scratch>/venv/bin/pip install python-docx- 正直に報告してください。ファイルを解析できなかった場合やチェックを実行できなかった場合は、その旨を伝え、静かに範囲を狭めないでください。
- リポジトリに
AGENTS.md、CLAUDE.md、PROJECT_WORKFLOW.md、CONTRIBUTING.mdなどに issue-first(または同様の)ワークフロー規則がある場合は、ユーザーに、返された編集と欠陥は実装前に issue が必要になることを伝えてください。依頼なしに issue を開かないでください。
規模を想定してください:中規模のブローシャーサイトでは、15〜20 ページで約 400〜600 項目、50〜60 ページのドキュメントになります。これは正常です。ページごとのテーブルにより、ナビゲート可能に保たれます。
ステップ 1 — 範囲を確定する(デフォルトで一度だけ質問する)
これらを一緒に質問し(AskUserQuestion が利用可能な場合)、デフォルトを推奨します:
- どのコピー? テンプレート/コンポーネントのハードコードされたコピーのみ (デフォルト — エディターコンテンツはコード変更なしで CMS で修正可能)、または CMS で作成された投稿/ページも含めるか?
- レビューアはどのように変更をマークするか? 空白の「推奨修正」列 (デフォルト — 明確で機械的に適用可能)、または Word コメント/変更履歴(自然だが、適用するのは難しい)か?
- どのコンテンツ状態? ワーキングツリー、またはライブ/プロダクション?ローカルデータベースまたはコンテンツスナップショットが実際に公開されているものより遅れる可能性があることにフラグを立てます。
ユーザーが不在の場合は、デフォルトを採用し、レポートの先頭にその旨を記載します。回答はカバーページに移動します(pages.json の meta.scope)。
ステップ 2 — コピーの保存場所を発見する
スタックを想定しないでください。リポジトリを検査し(package.json、テーママニフェスト、フレームワーク設定、ディレクトリ構造)、コピーソースをリストします:
- コード内:
.hbs、JSX/TSX、Vue、Svelte、Astro、Blade、ERB、Twig、PHP テーマ、HTML、Markdown/MDX コンテンツファイル、i18n/ロケール JSON または YAML。 - コード外: CMS データベース/API(Ghost、WordPress、Sanity、Contentful、Strapi)およびリポジトリにない訪問者向けサイト設定 — サイトタイトル、メタディスクリプション、ナビゲーションラベル、管理画面で設定された CTA/ボタンラベル。これらを取得するときは、生のエクスポートを
<scratch>/snapshots/に保存し、他のソースと同様に検証できるようにします(ステップ 4 を参照)。
これらの見落とされがちなカテゴリを必ずカバーし、レビューアが何を見ているかを把握できるようにラベルを付けます:alt テキスト(スクリーンリーダーと検索エンジンが読み取る — パートナー/製品名が正しい必要があります)、aria-label、フォームプレースホルダー、送信ラベル、成功/エラー/検証メッセージ、空の状態、404/エラーページ、著作権表示と法的フッター。
各ページテンプレートをそのライブ URL パスにマッピングします(routes.yaml、ファイルベースのルーティング、ルーター設定、CMS ページ→テンプレート割り当て)。テンプレートにページまたはルートがない場合は、そのページのノートに明示的にその旨を記載します — そのコピーは到達不能であり、レビューアはそれに時間を費やす前に知っておく必要があります。
次に、assets/pages.example.json から <scratch>/pages.json を作成します:ドキュメントが表示する順序でページごとに 1 エントリ、key、title、url、source、オプションの note、および meta ブロック(プロジェクト、範囲の回答、除外、ハードコードされたコピーのないテンプレート)を含めます。ビルドスクリプトはこれを読み取ります — ページメタデータがハードコードされることはありません。
ステップ 3 — 固定されたコントラクトで並行して抽出する
- 最初に表面全体を列挙する:すべてのページテンプレートおよびそれらのページに含まれるすべての部分/共有コンポーネント(ヘッダー、フッター、カード、ニュースレターフォーム、CTA)。部分は、ファイルがエージェント間で分割されると失われるものです。
- 重複しないグループに分割し(おおよそ 3〜6 ファイル、または約 1,500 行)、各ファイルを明示的に割り当てます。共有部分は、すべてのページで繰り返されるのではなく、独自のページエントリ(例:
FOOTER、NAV)を取得し、サイト全体に表示されるというノートを付けます。 - グループごとに 1 つのサブエージェントを、単一のターンで、ミッドティアモデル(例:Sonnet)で起動します:作業は機械的ですが、省略は目に見えず致命的です。
references/extraction-brief.mdをそのまますべてのプロンプトに貼り付け、その後にそのエージェントのファイルリスト、各ファイルに使用するpage_key、リポジトリルート、および出力パス<scratch>/extract/<group>.jsonを続けます。 - それらが戻ってきたら、列挙されたすべてのファイルが何らかの出力に現れていることを確認します(またはコピーが含まれていないと報告された)。不足しているものを再割り当てします。
各エージェントの報告された判断事項を収集します。これらはステップ 4 と最終レポートで必要になります。
ステップ 4 — 独立してマージして検証する(スキップしない)
エージェントの自己チェックは検証ではありません。実行:
<venv>/bin/python scripts/merge_and_verify.py \
--extract-dir <scratch>/extract --pages <scratch>/pages.json \
--repo <repo-root> [--snapshot-dir <scratch>/snapshots] --out <scratch>/out
これは、pages.json の順序ですべての抽出をマージし、PAGEKEY-NN Ref を割り当て、chars を再計算し、すべての文字列をそのソースファイルに対して 3 つの徐々に緩い正規化(生(空白が縮小)、タグ除去、空白圧縮)で再チェックします。それぞれが異なるものをキャッチするためです(属性テキストは生のチェックを通過し、構造上タグ除去で失敗します。これは想定内です)。また、重複 Ref、空のテキストがないこと、およびすべてのアイテムの page_key が pages.json に存在することをアサートします。出力:items.json、copy-review-manifest.csv、verification.md。
未解決のものがある間は終了コードがゼロ以外になります。各 UNMATCHED 行について、ソースを開いて確認します。正当な残留は通常、条件付き/ループブロックであり、エージェントがリテラルサブストリングではなくレンダリングされたテキストを記録した場合です — 記録されたとおりにレンダリングされることを確認し、<scratch>/accepted.json に {"REF": "理由"} としてリストし、--accept <scratch>/accepted.json で再実行します。抽出 JSON の真のエラーを修正し(リポジトリではなく)、再実行します。Ref はマージ時に割り当てられるため、データを修正し、再実行し、ビルドします。
また、完全性をスポットチェックします:最も密度の高いファイルを 2 つか 3 つ選び、アイテム数をファイルの簡単な読み取りと比較します。欠落した文字列は自動チェックに現れません。
ステップ 5 — ドキュメントをビルドする
<venv>/bin/python scripts/build_review_docx.py \
--pages <scratch>/pages.json --items <scratch>/out/items.json \
--out <scratch>/out/<Project>-Website-Copy-Review.docx
スクリプトはレイアウトを所有しているため、実行間で変わることはありません:ランドスケープ A4、1.4 cm マージン。カバーページ(範囲、含まれるもの/含まれないもの、レビュー方法、長さに敏感な行をその長さの近くに保つ、Ref の番号を付け直したり削除したりしない、事実 — 年、従業員数、数字、パートナー名、役職 — を文言と同じくらい注意深く確認する)。目次(合計と空のテンプレートを含む)。新しいページごとに 1 セクション。列:Ref 2.2 / 要素 4.3 / 現在のコピー 8.4 / 推奨修正 8.4 / ノート 3.6 cm。暗い繰り返しヘッダー行。色付き大文字セクションバナー行。ゼブラストライピング。制約のある行に文字数ガイダンス。動的セクションには色付きセルと「{{…}} 部分を保持」の警告。最後のページには次のステップとサインオフテーブル。ファイルを再度開き、行数が一致し、改訂/ノート列が空であることをアサートします。
「推奨修正」または「ノート」を事前に入力しないでください。レビューアの判断がポイントです。
ユーザーがステップ 1 で Word コメント/変更履歴を選択した場合でも、このドキュメントをビルドし(Ref コードは変更履歴を追跡可能にするものです)、編集に手動マッチングが必要になる可能性があることを伝えてください。
ステップ 6 — 配信前に確認する
構造チェックはデータが正しいことを証明しますが、読みやすいことを証明するわけではありません。レンダリングして実際に表示します:カバー、設定/ナビゲーションページ、および最も密度の高い長い段落のページ(幅が失敗する可能性があります)。
soffice --headless --convert-to pdf --outdir <dir> <file>.docx
pdftoppm -png -r 80 -f <n> -l <n> <file>.pdf <prefix>
Read で PNG を開きます。これらのツールがない場合は、視覚チェックが行われなかったことを明確に伝えてください。
ステップ 7 — ソースの欠陥を別途報告する
マークアップのすべての行を読むことで、実際のバグが明らかになります。これらを別のセクション(または別の source-defects.md)で報告します — これらはコードの問題であり、文言の問題ではありません。一般的なもの:
- レンダリングされた HTML 内のリテラル Markdown(ページに
**太字**が表示される) - どこにも存在しない ID へのアンカーリンク
- 存在するがアクション可能なものを含まないセクションへのリンク
- ページ/ルートのないテンプレート。そのコピーは到達不能
- それを上書きするカスタムテンプレートの背後にある孤立した CMS コンテンツ
- 再利用可能なテンプレートにハードコードされたプレースホルダー値
報告する前にそれぞれを自分で確認してください — ターゲット ID を grep し、テンプレートを開きます。エージェントはこれらを誇張します。「壊れたアンカー」は、実際には有効なターゲットがあり、そのセクションには単に行動するものが何もなかったことが判明しました。実際にあるものを、ファイルと行で説明してください。
ステップ 8 — 配信する
.docx をユーザーに送信します。簡単に、合計アイテム数とページ数、行われた範囲決定、マニフェスト CSV(Ref による返された編集を適用するため — レビューアの手に渡らないようにする)、受け入れた検証残留物とその理由、欠陥リスト、およびリポジトリにその規則がある場合は issue-first ノートを記載します。
返された修正の適用(ユーザーが戻ってきた場合)
返された .docx テーブル行(Ref + 推奨修正 + ノート)を読み、copy-review-manifest.csv と Ref で結合し、空でない修正ごとに、file 内の line 近くの text を見つけて置き換えます。制約のある行で chars を大幅に超える修正、および {{…}} 式を削除する修正は、静かにトリミングするのではなくフラグを立てます。リポジトリを編集する前に、計画された変更をユーザーに表示します。