mcpField
W
web-content-audit

web-content-audit

github.com/kevintsai1202テスト・品質5263 回インストール24 週間前に更新
リポジトリ

web-content-audit について

ソースファイルとデプロイ済みデータを比較し、人が確認するレポートを作る監査スクリプトの作成を支援するスキルです。ファイル間参照、素材の不足、内容の差分、IDの安定性、生成物の検査を扱い、監査結果はリリースを止めず判断材料を提供します。

主な機能

  1. 01ファイル間参照の確認
  2. 02素材カバレッジと不足レポート
  3. 03ソースとデプロイ内容の差分確認
  4. 04IDの安定性チェック
  5. 05生成物の検査

活用シーン

  1. 01リリース前の教材参照確認
  2. 02挿絵が必要な可能性のある章の特定
  3. 03企業版の内容とソースの比較
  4. 04生成したDOCXやPDFの納品物検査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/kevintsai1202/teaching-site-skills --skill web-content-audit

インストール後、Claude Code で/web-content-auditを入力して読み込まれたか確認します。

詳細

Web コンテンツ監査

スキーマの基準:ファイル間の一貫性ルール(教材の3か所同期、タスク ID の安定性、クイズの再採番トラップ)は、_shared/domain-primitives.md §13 に規定されています。このスキルの監査スクリプトは、これらのルールを運用に落とし込みます。

ファイル名の規則(英語優先):監査レポートは data/audit-*.md に、スクリプトは scripts/audit-*.mjs に保存します。

このスキルでは、ソースファイルとデプロイ済みデータを読み込み、比較して、人が読めるレポートを出力する監査スクリプトを作成します。目的はデプロイを阻止することではありません(それは検証の役目です)。人が確認すべき差異を明らかにすることです。

実行するタイミング

  • 大規模なコンテンツリリースの前(学生が目にする前に、アウトライン ↔ コースデータ ↔ ビジュアルのずれを検出します)。
  • 単元/教材/クイズ項目の追加・削除後(三か所同期ルールを再確認します)。
  • 企業向け版をクライアントに引き渡す前(短縮版 COURSE がソースと一致することを確認します)。
  • 「何かおかしい」と感じるものの、実行時のバグが見つからないとき(監査は目に見えないずれを検出します)。
  • 次のイテレーションを計画するとき(例:「新しいイラストが必要なセクションはどれですか?」)。

「ページが正しくレンダリングされるか?」という質問には実行しないでください。その場合は web-visual-verification を使います。

監査と検証 — 運用モードの違い

特徴監査検証
出力Markdown レポート(人が読む)合格/不合格(CI のゲート)
ツールファイル読み込み、正規表現、JSON 差分、必要に応じて PlaywrightPlaywright + アサーション
失敗時の動作常に終了コード 0。修正すべき点はレポートで人に知らせる問題があればゼロ以外の終了コードで終了
実行タイミング手動、マイルストーン時すべての PR/デプロイ前
考え方「何がずれたか見せてください」「これが再発しないようにしてください」

スクリプトに assert.* や process.exit(1) が含まれているなら、それは監査ではありません。web-visual-verification に移してください。

5つの監査カテゴリ

監査 1:アーティファクト間の参照解決

よくある教育サイトのバグです。course-data.js:materials[] がディスク上にないファイルを参照していたり、getMaterialUrl() にルールが不足していたりします。

// scripts/audit-material-references.mjs
import fs from 'node:fs/promises';
import path from 'node:path';

// Read course-data.js (via vm or regex extract)
const COURSE = await loadCourse('./course-data.js');

const report = ['# Material reference audit\n'];
for (const m of COURSE.materials) {
  // 1. Does the file router know about it?
  const routerCovers = await checkRouterCoverage(m.name);
  // 2. Does the actual file exist?
  const fileExists = await checkFileExists(m);
  // 3. Is it referenced in any unit's materials[]?
  const referencedInUnit = findReferencingUnits(COURSE, m.id);

  if (!routerCovers || !fileExists || referencedInUnit.length === 0) {
    report.push(`## ⚠️ ${m.id}: ${m.name}`);
    report.push(`- Router: ${routerCovers ? '✅' : '❌'}`);
    report.push(`- File: ${fileExists ? '✅' : '❌'}`);
    report.push(`- Referenced in units: ${referencedInUnit.join(', ') || '❌ NONE'}`);
  }
}
await fs.writeFile('data/audit-materials.md', report.join('\n'));

出力先は data/audit-*.md です。人がそれを開き、何を修正するか判断します。

監査 2:アセットの網羅性/不足分析

「まだイラストのないセクションはどれですか?」――今後の作業の参考にするためのものであり、失敗扱いにはしません。

// scripts/audit-illustrations.mjs
// Walks every .chapter / .accordion-content; counts text length, image count, list density
// For each section: if (textLength > 500 && imageCount === 0) → candidate for illustration
// Output: data/illustration-audit.md (a markdown list with section titles + screenshots)

スクリーンショットの撮影に Playwright を使う場合があります(撮影モード — アサーションなし)。ただし、成果物は不足項目の一覧であり、スクリーンショットではありません。分析結果を出力しない web-visual-verification の capture-*.mjs と混同しないでください。

監査 3:インラインデータ ↔ ソースのずれ(企業向け版)

企業向け版で window.COURSE が index.html にインライン化されている場合、短縮元のソースファイルとの間にずれが生じることがあります。差分を監査します。

// scripts/audit-corp-content.mjs
const inlined = await loadCourseFromIndexHtml('corporate-editions/client_6h/index.html');
const source = await loadSourceMarkdown('course-package/');

const report = ['# Corporate edition content audit\n'];

// Compare meta
report.push(`## Meta`);
report.push(diff(inlined.meta, source.meta));

// Per-unit: deliverables / prompts / tasks count
for (const day of ['day1', 'day2']) {
  for (const unit of inlined[day].units) {
    report.push(`## ${unit.id}: ${unit.title}`);
    report.push(`- Prompts: ${unit.prompts?.length || 0}`);
    report.push(`- Tasks: ${unit.tasks?.length || 0}`);
    report.push(`- Materials: ${unit.materials?.length || 0}`);
  }
}
await fs.writeFile('data/audit-corp-content.md', report.join('\n'));

サンプルのワークショップにある audit-corp-6h-content.mjs がまさにこれを行います。企業向けセッションのたびに、講師がざっと確認できる Markdown のダンプを生成します。

監査 4:ID の安定性と再利用

task.id、quiz.id、unit.id は安定した契約です(localStorage キー、内部参照)。これらを監査します。

// scripts/audit-id-stability.mjs
// 1. Collect all task IDs across course-data.js — check no duplicates
// 2. Read git log for course-data.js — flag any task ID that was renamed (not just deleted)
// 3. Cross-check quiz[N].sourceUnit references actual unit IDs
// 4. Cross-check materials[].id appears in at least one unit's materials[]

これは「誤って d2-u3-t1 を d2-u3-task1 に変更した」といったケースを検出する監査です。全学生の localStorage の進捗が、気づかれないまま消去されます。

監査 5:生成されたアーティファクトの検査

パイプラインがバイナリの成果物(DOCX、PDF、zip)を生成する場合、内部構造を監査して、ビルドの不具合を早期に検出します。

// scripts/inspect-docx-images.mjs
import JSZip from 'jszip';
const zip = await JSZip.loadAsync(await readFile('dist/ebook.docx'));
const images = Object.keys(zip.files).filter(f => f.startsWith('word/media/'));
console.log(`📷 內嵌圖片:${images.length} 張`);
for (const f of images) {
  const size = zip.files[f]._data?.uncompressedSize || 0;
  console.log(`   ${f}  ${(size / 1024).toFixed(1)} KB`);
}

画像が約30枚あるはずなのに DOCX に3枚しかない場合、ビルド中に何かが気づかれないまま失敗しています。Word を開いてスクロールするより、この方法のほうが速く確認できます。

出力の規則

data/
├── audit-materials.md            ← Audit 1
├── audit-illustrations.md         ← Audit 2 (gap analysis)
├── audit/section-*.png            ←   ↳ supporting screenshots
├── audit-corp-content.md          ← Audit 3
├── audit-id-stability.md          ← Audit 4
└── audit-ebook-inspection.txt     ← Audit 5

すべての監査出力はバージョン管理可能な Markdown(または JSON)にします。リリースのマイルストーンでコミットしてください。リリース間の差分から、「実際に変更されたコンテンツ」がわかります。

人がざっと確認しやすいレポートにする

監査担当者はじっくり読むのではなく、ざっと目を通します。流し読みしやすい構成にします。

# {Audit name} — {timestamp}

## Summary
- ✅ 24 of 30 materials fully wired
- ⚠️ 4 materials missing router rules
- ❌ 2 materials referenced but file missing

## ⚠️ Warnings (need attention but not blocking)
...

## ❌ Errors (likely broken in production)
...

## ℹ️ Notes (FYI)
...

最初に概要を示し、すべてのセクション見出しの先頭に絵文字を付けます。監査の役目は、世界で最も効率的なコードレビューになることです。

「3 か所同期」監査(教育サイトでは重要)

static-spa-conversion のパターンでは、すべての教材が次の 3 か所に存在する必要があります。(1)ファイルシステム、(2)course-data.js:materials[]、(3)getMaterialUrl() ルーター。監査スクリプト:

const fsFiles = new Set(await fs.readdir('course-package/materials/'));
const dataMaterials = new Set(COURSE.materials.map(m => routerNameToFile(m.name)));
const routerCoverage = extractRouterRules(indexHtmlContent);

const inFsNotInData = [...fsFiles].filter(f => !dataMaterials.has(f));
const inDataNotInFs = [...dataMaterials].filter(f => !fsFiles.has(f));
const inDataNotInRouter = [...dataMaterials].filter(f => !routerCoverage.has(f));

// Emit a 3-column markdown table showing each file's coverage in each of the three places.

この単一のスクリプトで、「教材のリンクが壊れている」バグの 90% を検出できます。

監査はブロックせず、情報を提供する

最も重要な原則は、問題を検出した場合でも、監査スクリプトは常に終了コード 0 で終了することです。その理由は次のとおりです。

  • 監査は定期的に実行されます。「次のリリースで修正する」とわかっている問題のために、CI を赤くしたくありません。
  • 監査では、判断を要する問題(例:「セクションにイラストがありません。これは意図的ですか?」)が表面化しますが、自動化で判断すべきではありません。
  • 監査が失敗すると、検証のように感じられます。その結果、人は監査をゲートとして扱い、レポートは「読まれない」状態に陥ります。

問題がリリースをブロックしなければならない場合は、assert.* を使う検証スクリプト(web-visual-verification)に移してください。監査は情報を提供し、検証はゲートとして機能します。

監査の実施タイミング(頻度)

トリガー実行する監査
単元の追加・削除id-stability、material-references
教材ファイルの追加material-references(特に 3 か所同期)
クイズの番号変更id-stability + ハードコードされた (N題) 文字列を手動で確認
法人向け版の引き渡し前corp-content(インライン ↔ ソース)+ material-references
電子書籍の公開前inspect-docx-images / inspect-pdf-pagecount
四半期ごとのメンテナンスillustrations(ギャップ分析)→ 次のコンテンツサイクルを計画

アンチパターン

  • assert.* またはゼロ以外の終了コードを使う監査スクリプト — これは監査ではなく検証です。移動してください。
  • 誰も読まない監査レポート — 簡潔にし、集計数を最初に示し、ひと目でわかるように絵文字を積極的に使ってください。
  • 5 つの役割をこなす 1 つの監査 — 分割してください。audit-materials.mjs と audit-illustrations.mjs は、異なる判断のために異なるフォルダーへ異なるレポートを出力します。
  • 検証と同じように CI で監査を実行する — ノイズとなり、無効化され、役に立たなくなります。必要に応じて、またはリリースの節目に実行してください。
  • レポートにタイムスタンプ/バージョンがない — 2 つの監査実行結果を比較する際、どちらが新しいかを知る必要があります。

引き継ぎ

このスキルの完了時には、次の状態になっています。

  • audit-*.mjs スクリプト(および補助的な inspect-*.mjs スクリプト)が scripts/ にある。
  • その出力が data/audit-*.md(ツールでの利用を想定する場合は .json)に保存される。
  • プロジェクトの README に「監査レポートの読み方」を説明するセクションがある(上記の規約へのリンクを含む)。
  • ユーザーが、すべてのコミットごとではなく、リリースの節目に監査を実行することを把握している。

コメント