when-detecting-fake-code-use-theater-detection
実装は完成しているように見えても実際には機能しない「見せかけ」コードを検出します。静的解析では正しく見えても、実行時に失敗するコードを特定でき、偽の実装が本番環境に到達するのを防げます。疑わしいパターンをスキャンし、実際の機能性を検証して、推奨事項と共に結果をレポートします。
description の原文を見る
Detects non-functional "theater" code that appears complete but doesn't actually work. Use this skill to identify code that looks correct in static analysis but fails during execution, preventing fake implementations from reaching production. Scans for suspicious patterns, validates actual functionality, and reports findings with recommendations.
SKILL.md 本文
シアターコード検出
このスキルを使用する場合
トリガー条件:
- AI生成コードをメインブランチにマージする前
- コードレビューで疑わしく完全な実装が明らかになった場合
- ドキュメントと動作の矛盾を検出した後
- 本番環境へのデプロイ前の品質ゲート(重要なシステム)
- サードパーティまたは不慣れなコードを統合する場合
- セキュリティ監査中に不正なセキュリティ対策を特定する場合
シアター検出が必要な状況:
- コンパイルされるが意味のあるロジックを実行しないコード
- 適切なシグネチャがあるが何もしない関数
- コード変更に関係なく常にパスするテスト
- 簡単にバイパスできるセキュリティチェック
- エラーをキャッチするがハンドルしないエラー処理
- 本番環境に誤って残されたモック実装
概要
シアターコードは、実装をサボりながら「正しさを演じる」コードです。静的分析を通過し、構造的には健全に見え、テストもあるかもしれません。しかし意図した動作の実装に失敗しています。このスキルはパターン認識、実行分析、動作検証を通じてシアターコードを体系的に識別します。
検出プロセスは、疑わしいパターン(空のcatchブロック、何もしない関数、常にパスするテスト)のコードベースをスキャンし、意味のあるロジックの実装を分析し、実際の動作を検証するコードを実行し、改善のための実行可能な推奨事項付きで検出結果をレポートします。
フェーズ1:コードベーススキャン(並行)
エージェント: code-analyzer(リード)、reviewer(検証) 期間: 10~15分
スクリプト:
# フェーズを初期化
npx claude-flow hooks pre-task --description "Phase 1: Scan Codebase for Theater Patterns"
npx claude-flow swarm init --topology mesh --max-agents 2
# エージェントをスポーン
npx claude-flow agent spawn --type code-analyzer --capabilities "pattern-matching,ast-analysis,static-analysis"
npx claude-flow agent spawn --type reviewer --capabilities "code-quality,suspicious-pattern-detection"
# メモリ調整 - スキャンパラメータを定義
npx claude-flow memory store --key "testing/theater-detection/phase-1/analyzer/scan-config" --value '{"patterns":["empty-catch","no-op-function","always-pass-test"],"severity":"high"}'
# フェーズワークを実行
# 1. 空のcatchブロックをスキャン
echo "Scanning for empty error handlers..."
grep -r "catch\s*(\w*)\s*{\s*}" --include="*.js" --include="*.ts" . > empty-catches.txt || true
# 2. 何もしない関数をスキャン
grep -r "function\s+\w+.*{\s*return\s*[;}]" --include="*.js" --include="*.ts" . > noop-functions.txt || true
# 3. 常にパスするテストをスキャン
grep -r "expect(true).toBe(true)" --include="*.test.js" --include="*.test.ts" . > always-pass-tests.txt || true
# 4. 不完全な作業を示すTODO/FIXME/HACKコメントをスキャン
grep -rn "TODO\|FIXME\|HACK" --include="*.js" --include="*.ts" . > incomplete-markers.txt || true
# 5. 疑わしいインポート(未使用、本番環境のテストダブル)をスキャン
echo "Analyzing imports..."
cat > scan-imports.js << 'EOF'
const fs = require('fs');
const path = require('path');
function scanImports(dir) {
const suspicious = [];
function walkDir(currentPath) {
const files = fs.readdirSync(currentPath);
files.forEach(file => {
const filePath = path.join(currentPath, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory() && !file.includes('node_modules')) {
walkDir(filePath);
} else if (file.endsWith('.js') || file.endsWith('.ts')) {
const content = fs.readFileSync(filePath, 'utf-8');
// 本番環境コード内のモックインポートをチェック
if (!filePath.includes('test') && content.includes("'mock'")) {
suspicious.push({
file: filePath,
reason: 'Mock import in production code',
line: content.split('\n').findIndex(l => l.includes("'mock'")) + 1
});
}
// 未使用のインポートをチェック
const importMatch = content.match(/import\s+{([^}]+)}\s+from/g);
if (importMatch) {
importMatch.forEach(imp => {
const symbols = imp.match(/{([^}]+)}/)[1].split(',').map(s => s.trim());
symbols.forEach(symbol => {
const usageCount = (content.match(new RegExp(`\\b${symbol}\\b`, 'g')) || []).length;
if (usageCount === 1) { // インポートにのみ出現
suspicious.push({
file: filePath,
reason: `Unused import: ${symbol}`,
line: content.split('\n').findIndex(l => l.includes(symbol)) + 1
});
}
});
});
}
}
});
}
walkDir(dir);
return suspicious;
}
const results = scanImports(process.cwd());
fs.writeFileSync('suspicious-imports.json', JSON.stringify(results, null, 2));
EOF
node scan-imports.js
# 6. スキャン結果をコンパイル
cat > scan-summary.json << 'EOF'
{
"empty_catches": 0,
"noop_functions": 0,
"always_pass_tests": 0,
"incomplete_markers": 0,
"suspicious_imports": 0,
"total_issues": 0,
"scanned_at": ""
}
EOF
# 実際のカウントで更新
EMPTY_CATCHES=$(wc -l < empty-catches.txt)
NOOP_FUNCTIONS=$(wc -l < noop-functions.txt)
ALWAYS_PASS=$(wc -l < always-pass-tests.txt)
INCOMPLETE=$(wc -l < incomplete-markers.txt)
SUSPICIOUS_IMPORTS=$(jq 'length' suspicious-imports.json)
TOTAL=$((EMPTY_CATCHES + NOOP_FUNCTIONS + ALWAYS_PASS + INCOMPLETE + SUSPICIOUS_IMPORTS))
jq --arg ec "$EMPTY_CATCHES" \
--arg nf "$NOOP_FUNCTIONS" \
--arg ap "$ALWAYS_PASS" \
--arg im "$INCOMPLETE" \
--arg si "$SUSPICIOUS_IMPORTS" \
--arg total "$TOTAL" \
--arg ts "$(date -Iseconds)" \
'.empty_catches = ($ec | tonumber) |
.noop_functions = ($nf | tonumber) |
.always_pass_tests = ($ap | tonumber) |
.incomplete_markers = ($im | tonumber) |
.suspicious_imports = ($si | tonumber) |
.total_issues = ($total | tonumber) |
.scanned_at = $ts' \
scan-summary.json > scan-summary-updated.json
mv scan-summary-updated.json scan-summary.json
# 結果を保存
npx claude-flow memory store --key "testing/theater-detection/phase-1/analyzer/scan-results" --value "$(cat scan-summary.json)"
# フェーズを完了
npx claude-flow hooks post-task --task-id "phase-1-scan"
メモリパターン:
- 入力:
testing/theater-detection/phase-0/user/codebase-path - 出力:
testing/theater-detection/phase-1/analyzer/scan-results - 共有:
testing/theater-detection/shared/suspicious-files
成功条件:
- すべてのパターンタイプについてコードベース全体をスキャン
- すべての疑わしいパターンを抽出およびカウント
- スキャン結果を構造化形式で作成
- 誤検知なし(レビュアーエージェントで検証)
- 結果を次のフェーズ用にメモリに保存
成果物:
- 問題数を含むスキャンサマリーJSON
- パターン固有の結果ファイル(empty-catches.txt等)
- 疑わしいインポート分析
- ファイルレベルの問題マッピング
フェーズ2:実装を分析(順序)
エージェント: code-analyzer(リード)、reviewer(深層分析) 期間: 15~20分
スクリプト:
# フェーズを初期化
npx claude-flow hooks pre-task --description "Phase 2: Analyze Implementation Depth"
npx claude-flow swarm scale --target-agents 2
# スキャン結果を取得
SCAN_RESULTS=$(npx claude-flow memory retrieve --key "testing/theater-detection/phase-1/analyzer/scan-results")
# メモリ調整
npx claude-flow memory store --key "testing/theater-detection/phase-2/analyzer/analysis-depth" --value '{"ast_parsing":true,"control_flow":true,"data_flow":true}'
# フェーズワークを実行
# 1. フラグ付きファイルの深層分析
echo "Performing deep implementation analysis..."
# 分析スクリプトを作成
cat > analyze-implementation.js << 'EOF'
const fs = require('fs');
const path = require('path');
function analyzeImplementation(filePath) {
const content = fs.readFileSync(filePath, 'utf-8');
const analysis = {
file: filePath,
theater_indicators: [],
confidence_score: 0
};
// 意味のあるロジックをチェック
const lines = content.split('\n').filter(l => l.trim() && !l.trim().startsWith('//'));
const codeLines = lines.length;
const commentLines = content.split('\n').filter(l => l.trim().startsWith('//')).length;
if (commentLines > codeLines) {
analysis.theater_indicators.push('More comments than code - possible placeholder');
}
// 実際の計算をチェック
const hasComputation = /[\+\-\*\/\%]/.test(content) ||
/if\s*\(/.test(content) ||
/for\s*\(/.test(content) ||
/while\s*\(/.test(content);
if (!hasComputation && codeLines > 5) {
analysis.theater_indicators.push('No computational logic despite size');
}
// データ変換をチェック
const hasTransformation = /\.map\(|\.filter\(|\.reduce\(/.test(content) ||
/Object\.(keys|values|entries)/.test(content);
// 関数の戻り値をチェック
const returnMatches = content.match(/return\s+([^;]+);/g) || [];
const trivialReturns = returnMatches.filter(r =>
r.includes('return null') ||
r.includes('return undefined') ||
r.includes('return true') ||
r.includes('return false') ||
r.includes('return {}') ||
r.includes('return []')
);
if (trivialReturns.length > returnMatches.length * 0.5) {
analysis.theater_indicators.push('Majority of returns are trivial values');
}
// エラーハンドリングシアターをチェック
const catchBlocks = content.match(/catch\s*\([^)]*\)\s*{([^}]*)}/g) || [];
const emptyCatches = catchBlocks.filter(c => {
const body = c.match(/{([^}]*)}/)[1].trim();
return body === '' || body === 'console.log' || body.includes('// TODO');
});
if (emptyCatches.length > 0) {
analysis.theater_indicators.push(`${emptyCatches.length} empty catch blocks`);
}
// 信頼度スコアを計算(0-100)
analysis.confidence_score = Math.min(100, analysis.theater_indicators.length * 20);
return analysis;
}
// 疑わしいファイルをすべて分析
const suspiciousFiles = [
...fs.readFileSync('empty-catches.txt', 'utf-8').split('\n').filter(Boolean).map(l => l.split(':')[0]),
...fs.readFileSync('noop-functions.txt', 'utf-8').split('\n').filter(Boolean).map(l => l.split(':')[0])
];
const uniqueFiles = [...new Set(suspiciousFiles)];
const analyses = uniqueFiles.map(analyzeImplementation);
// 信頼度の高いシアターコードをフィルター
const theaterCode = analyses.filter(a => a.confidence_score >= 40);
fs.writeFileSync('theater-analysis.json', JSON.stringify({
total_analyzed: analyses.length,
theater_detected: theaterCode.length,
files: theaterCode
}, null, 2));
console.log(`Analyzed ${analyses.length} files, detected ${theaterCode.length} theater implementations`);
EOF
node analyze-implementation.js
# 2. 重大度別に分類
cat > categorize-theater.js << 'EOF'
const fs = require('fs');
const analysis = JSON.parse(fs.readFileSync('theater-analysis.json', 'utf-8'));
const categories = {
critical: [], // 全く動作しないコード
high: [], // 主要な機能ギャップがあるコード
medium: [], // マイナーなシアター要素があるコード
low: [] // 改善の可能性があるコード
};
analysis.files.forEach(file => {
const score = file.confidence_score;
const indicators = file.theater_indicators;
if (score >= 80 || indicators.some(i => i.includes('empty catch'))) {
categories.critical.push(file);
} else if (score >= 60) {
categories.high.push(file);
} else if (score >= 40) {
categories.medium.push(file);
} else {
categories.low.push(file);
}
});
fs.writeFileSync('theater-categories.json', JSON.stringify(categories, null, 2));
console.log('Critical:', categories.critical.length);
console.log('High:', categories.high.length);
console.log('Medium:', categories.medium.length);
console.log('Low:', categories.low.length);
EOF
node categorize-theater.js
# 分析結果を保存
npx claude-flow memory store --key "testing/theater-detection/phase-2/analyzer/theater-analysis" --value "$(cat theater-analysis.json)"
npx claude-flow memory store --key "testing/theater-detection/phase-2/analyzer/categories" --value "$(cat theater-categories.json)"
# フェーズを完了
npx claude-flow hooks post-task --task-id "phase-2-analyze"
メモリパターン:
- 入力:
testing/theater-detection/phase-1/analyzer/scan-results - 出力:
testing/theater-detection/phase-2/analyzer/theater-analysis - 共有:
testing/theater-detection/shared/analysis-results
成功条件:
- フラグ付きファイルをすべて実装の深さについて分析
- シアター指標を信頼度スコア付きで特定
- 問題を重大度別に分類(critical、high、medium、low)
- 分析結果を構造化して包括的に作成
- レビュアーエージェントによる検証結果
成果物:
- 信頼度スコア付きのシアター分析JSON
- 重大度の分類(critical/high/medium/low)
- ファイルごとのシアター指標リスト
- 実装の深さ評価
フェーズ3:テスト実行(並行)
エージェント: tester(リード)、code-analyzer(サポート) 期間: 15~20分
スクリプト:
# フェーズを初期化
npx claude-flow hooks pre-task --description "Phase 3: Test Execution Validation"
npx claude-flow swarm scale --target-agents 2
# 分析結果を取得
THEATER_ANALYSIS=$(npx claude-flow memory retrieve --key "testing/theater-detection/phase-2/analyzer/theater-analysis")
# メモリ調整
npx claude-flow memory store --key "testing/theater-detection/phase-3/tester/test-strategy" --value '{"execution_validation":true,"behavior_testing":true,"edge_case_testing":true}'
# フェーズワークを実行
# 1. 実行検証テストを作成
echo "Creating execution validation tests..."
cat > execution-validator.test.js << 'EOF'
const fs = require('fs');
const theaterFiles = JSON.parse(fs.readFileSync('theater-analysis.json', 'utf-8')).files;
describe('Theater Code Execution Validation', () => {
theaterFiles.forEach(fileData => {
describe(`File: ${fileData.file}`, () => {
test('should execute without errors', () => {
try {
const module = require(`./${fileData.file}`);
expect(module).toBeDefined();
} catch (error) {
// ロードできない場合、確実にシアター
expect(error).toBeUndefined();
}
});
test('should have non-trivial exports', () => {
try {
const module = require(`./${fileData.file}`);
const exports = Object.keys(module);
// エクスポートが存在し、空のオブジェクトではないことをチェック
expect(exports.length).toBeGreaterThan(0);
exports.forEach(exp => {
if (typeof module[exp] === 'function') {
// 関数が「return null」だけではないことをチェック
const fnString = module[exp].toString();
expect(fnString.length).toBeGreaterThan(50); // trivialな実装以上
}
});
} catch (error) {
// モジュールが正しくロードされない
fail(`Cannot validate exports: ${error.message}`);
}
});
test('should produce meaningful output', () => {
try {
const module = require(`./${fileData.file}`);
// エクスポートされた各関数について、サンプル入力で呼び出し
Object.keys(module).forEach(key => {
if (typeof module[key] === 'function') {
// 様々な入力で呼び出しを試行
const results = [
module[key](),
module[key](null),
module[key]({}),
module[key]('test')
];
// 結果がバリエーションするかチェック(常に同じ trivial 値ではない)
const uniqueResults = new Set(results.map(r => JSON.stringify(r)));
// すべての結果が同一の場合、おそらくシアター
if (uniqueResults.size === 1) {
const result = results[0];
// 例外:結果が複雑なオブジェクトの場合は OK の可能性
if (result === null || result === undefined ||
result === true || result === false ||
(typeof result === 'object' && Object.keys(result).length === 0)) {
fail(`Function ${key} returns trivial constant`);
}
}
}
});
} catch (error) {
// 何らかの実行が発生した、これは何もないよりは良い
console.log(`Execution validation: ${error.message}`);
}
});
});
});
});
EOF
# 2. 実行検証を実行
npm test -- execution-validator.test.js --verbose > execution-validation.log 2>&1
EXECUTION_EXIT_CODE=$?
# 3. テスト結果を分析
cat > analyze-execution.js << 'EOF'
const fs = require('fs');
const log = fs.readFileSync('execution-validation.log', 'utf-8');
const results = {
files_tested: 0,
files_failed_load: 0,
files_trivial_exports: 0,
files_constant_output: 0,
confirmed_theater: []
};
// テスト出力をパース
const fileTests = log.split('File:').slice(1);
fileTests.forEach(section => {
const fileName = section.split('\n')[0].trim();
results.files_tested++;
if (section.includes('Cannot validate exports')) {
results.files_failed_load++;
results.confirmed_theater.push({
file: fileName,
reason: 'Failed to load or execute'
});
} else if (section.includes('returns trivial constant')) {
results.files_constant_output++;
results.confirmed_theater.push({
file: fileName,
reason: 'Returns constant trivial values'
});
} else if (section.includes('FAIL')) {
results.files_trivial_exports++;
results.confirmed_theater.push({
file: fileName,
reason: 'Trivial or no-op implementation'
});
}
});
fs.writeFileSync('execution-results.json', JSON.stringify(results, null, 2));
console.log(`Confirmed theater code: ${results.confirmed_theater.length} files`);
EOF
node analyze-execution.js
# 実行結果を保存
npx claude-flow memory store --key "testing/theater-detection/phase-3/tester/execution-results" --value "$(cat execution-results.json)"
# フェーズを完了
npx claude-flow hooks post-task --task-id "phase-3-execute"
メモリパターン:
- 入力:
testing/theater-detection/phase-2/analyzer/theater-analysis - 出力:
testing/theater-detection/phase-3/tester/execution-results - 共有:
testing/theater-detection/shared/execution-logs
成功条件:
- すべての疑わしいシアターコードを実行して検証
- 実行動作を有意性について分析
- 確認されたシアターコードを理由付きで特定
- テスト結果を包括的かつ確定的に作成
- レポートフェーズ用に結果を保存
成果物:
- 実行検証テストスイート
- 確認されたシアターを含む実行結果JSON
- テスト実行ログ
- 動作分析レポート
フェーズ4:検出結果をレポート(順序)
エージェント: reviewer(リード)、code-analyzer(サマリー) 期間: 10~15分
スクリプト:
# フェーズを初期化
npx claude-flow hooks pre-task --description "Phase 4: Report Theater Detection Findings"
npx claude-flow swarm scale --target-agents 2
# すべてのフェーズ結果を取得
SCAN_RESULTS=$(npx claude-flow memory retrieve --key "testing/theater-detection/phase-1/analyzer/scan-results")
THEATER_ANALYSIS=$(npx claude-flow memory retrieve --key "testing/theater-detection/phase-2/analyzer/theater-analysis")
CATEGORIES=$(npx claude-flow memory retrieve --key "testing/theater-detection/phase-2/analyzer/categories")
EXECUTION=$(npx claude-flow memory retrieve --key "testing/theater-detection/phase-3/tester/execution-results")
# フェーズワークを実行
# 1. 包括的なレポートを生成
cat > theater-detection-report.md << EOF
# シアターコード検出レポート
**生成日時:** $(date)
**スキャン期間:** フェーズ1~4を完了
## エグゼクティブサマリー
### 概要
- **発見された問題の総数:** $(echo $SCAN_RESULTS | jq -r '.total_issues')
- **確認されたシアターコード:** $(echo $EXECUTION | jq -r '.confirmed_theater | length')
- **重大な問題:** $(echo $CATEGORIES | jq -r '.critical | length')
- **高優先度の問題:** $(echo $CATEGORIES | jq -r '.high | length')
### 影響評価
$(echo $EXECUTION | jq -r 'if (.confirmed_theater | length) > 0 then "⚠️ シアターコード検出 - コードは機能しているように見えますが、実装がありません" else "✅ シアターコードは検出されませんでした" end')
---
## フェーズ1:コードベーススキャン結果
### パターン検出
- **空のcatchブロック:** $(echo $SCAN_RESULTS | jq -r '.empty_catches')
- **何もしない関数:** $(echo $SCAN_RESULTS | jq -r '.noop_functions')
- **常にパスするテスト:** $(echo $SCAN_RESULTS | jq -r '.always_pass_tests')
- **不完全なマーカー(TODO/FIXME):** $(echo $SCAN_RESULTS | jq -r '.incomplete_markers')
- **疑わしいインポート:** $(echo $SCAN_RESULTS | jq -r '.suspicious_imports')
---
## フェーズ2:実装分析
### 重大度別シアターコード
#### 重大(即座の対応が必要)
$(echo $CATEGORIES | jq -r '.critical[] | "- **\(.file)**\n 信頼度:\(.confidence_score)%\n 指標:\n\(.theater_indicators | map(" - " + .) | join("\n"))\n"')
#### 高優先度
$(echo $CATEGORIES | jq -r '.high[] | "- **\(.file)**\n 信頼度:\(.confidence_score)%\n 指標:\n\(.theater_indicators | map(" - " + .) | join("\n"))\n"')
#### 中優先度
$(echo $CATEGORIES | jq -r '.medium[] | "- **\(.file)**\n 信頼度:\(.confidence_score)%\n"')
---
## フェーズ3:実行検証
### 実行テスト結果
- **テスト対象ファイル:** $(echo $EXECUTION | jq -r '.files_tested')
- **ロードに失敗:** $(echo $EXECUTION | jq -r '.files_failed_load')
- **Trivialなエクスポート:** $(echo $EXECUTION | jq -r '.files_trivial_exports')
- **定数出力:** $(echo $EXECUTION | jq -r '.files_constant_output')
### 確認されたシアターコード
$(echo $EXECUTION | jq -r '.confirmed_theater[] | "- **\(.file)**\n 理由:\(.reason)\n"')
---
## 推奨事項
### 即座のアクション(重大)
1. **シアター実装を置き換え**
- 重大カテゴリのすべてのファイルをレビュー
- 実際のビジネスロジックを実装
- 意味のあるエラーハンドリングを追加
2. **空のエラーハンドラーを修正**
- 適切なエラーログと復旧を追加
- エラーが適切に伝播するようにする
- エラーハンドリング戦略を文書化
3. **常にパスするテストを削除**
- 意味のあるアサーションに置き換え
- 定数ではなく実際の動作をテスト
- 重大パスのテストカバレッジを増加
### 短期的なアクション(高優先度)
1. **何もしない関数を実装**
- スタブ関数を実際のロジックで置き換え
- 包括的なドキュメントを追加
- 新しい実装をテストで覆う
2. **不完全なコードをクリーンアップ**
- すべてのTODO/FIXMEマーカーに対応
- 部分的な実装を完成
- デッドコードを削除
### 長期的なアクション(予防)
1. **コードレビュープロセスを確立**
- AI生成コードの手動レビュー
- CI/CDでの自動シアター検出
- 重大なコンポーネントのペアプログラミング
2. **テスト標準を改善**
- 意味のあるテストアサーションを要求
- カバレッジの閾値を適用
- 構造ではなく動作をテスト
3. **トレーニングと文書化**
- チームにシアターコードパターンについて教育
- 実装の期待を文書化
- 品質標準ガイドを作成
---
## アーティファクト
- スキャン結果:\`scan-summary.json\`
- シアター分析:\`theater-analysis.json\`
- 重大度カテゴリ:\`theater-categories.json\`
- 実行結果:\`execution-results.json\`
- 詳細ログ:\`execution-validation.log\`
---
## 次のステップ
$(echo $EXECUTION | jq -r 'if (.confirmed_theater | length) > 0 then "1. すべての確認されたシアターコードファイルをレビュー\n2. 重大度別に修正を優先付け(重大→高→中)\n3. フラグ付きコードの実際の機能を実装\n4. 修正後にシアター検出を再実行\n5. 将来のシアターコードを防ぐようにテストを更新" else "✅ コードベースはシアターコードから解放されています。標準的な品質保証プロセスを続けてください。" end')
EOF
# 2. サマリーメトリクスを生成
cat > theater-metrics.json << EOF
{
"scan_timestamp": "$(date -Iseconds)",
"total_issues_found": $(echo $SCAN_RESULTS | jq -r '.total_issues'),
"confirmed_theater_count": $(echo $EXECUTION | jq -r '.confirmed_theater | length'),
"critical_count": $(echo $CATEGORIES | jq -r '.critical | length'),
"high_priority_count": $(echo $CATEGORIES | jq -r '.high | length'),
"medium_priority_count": $(echo $CATEGORIES | jq -r '.medium | length'),
"files_analyzed": $(echo $THEATER_ANALYSIS | jq -r '.total_analyzed'),
"theater_detected": $(echo $THEATER_ANALYSIS | jq -r '.theater_detected'),
"execution_tests_run": $(echo $EXECUTION | jq -r '.files_tested')
}
EOF
# 最終レポートを保存
npx claude-flow memory store --key "testing/theater-detection/final-report" --value "$(cat theater-detection-report.md)"
npx claude-flow memory store --key "testing/theater-detection/final-metrics" --value "$(cat theater-metrics.json)"
# フェーズを完了しメトリクスをエクスポート
npx claude-flow hooks post-task --task-id "phase-4-report" --export-metrics true
メモリパターン:
- 入力:
testing/theater-detection/phase-{1-3}/*/output - 出力:
testing/theater-detection/final-report - 共有:
testing/theater-detection/shared/complete-analysis
成功条件:
- すべての検出結果を含む包括的なレポートを生成
- 問題を重大度別に分類して明確に優先付け
- 実行可能な推奨事項を提供
- 追跡とトレンドのためにメトリクスをコンパイル
- 将来の参照のために結果をメモリに保存
成果物:
- シアター検出レポート(Markdown)
- メトリクスダッシュボード(JSON)
- 推奨事項ドキュメント
- 完全なアーティファクトパッケージ
フェーズ5:問題を修正(順序)
エージェント: coder(リード)、reviewer(検証) 期間: 30~60分(問題数による)
スクリプト:
# フェーズを初期化
npx claude-flow hooks pre-task --description "Phase 5: Fix Theater Code Issues"
npx claude-flow swarm scale --target-agents 2
# 確認されたシアターコードを取得
EXECUTION=$(npx claude-flow memory retrieve --key "testing/theater-detection/phase-3/tester/execution-results")
CATEGORIES=$(npx claude-flow memory retrieve --key "testing/theater-detection/phase-2/analyzer/categories")
# メモリ調整
npx claude-flow memory store --key "testing/theater-detection/phase-5/coder/fix-strategy" --value '{"priority":"critical-first","validation":"immediate","backup":"enabled"}'
# フェーズワークを実行
# 1. 修正前にオリジナルファイルのバックアップを作成
echo "Creating backups before fixes..."
mkdir -p .theater-detection-backups
echo $EXECUTION | jq -r '.confirmed_theater[].file' | while read file; do
[ -f "$file" ] && cp "$file" ".theater-detection-backups/$(basename $file).backup"
done
# 2. 重大な問題を最初に修正(空のcatch、no-op)
echo "Fixing critical theater code..."
# 例:空のcatchブロックを修正
find . -name "*.js" -type f ! -path "./node_modules/*" -exec sed -i.bak \
's/catch\s*(\s*\(\w\+\)\s*)\s*{\s*}/catch (\1) {\n console.error("Error caught:", \1);\n throw \1;\n }/g' {} \;
# 例:no-op関数(手動レビューが必要)
cat > fix-guide.md << 'EOF'
# シアターコード修正ガイド
## 手動修正が必要なファイル
以下のファイルには、手動実装が必要なシアターコードが含まれています:
EOF
echo $CATEGORIES | jq -r '.critical[] | .file' | while read file; do
echo "### $file" >> fix-guide.md
echo "指標:" >> fix-guide.md
echo $CATEGORIES | jq -r --arg f "$file" '.critical[] | select(.file == $f) | .theater_indicators[]' | \
sed 's/^/- /' >> fix-guide.md
echo "" >> fix-guide.md
done
# 3. 修正が既存の機能を破壊しないか検証
npm test > fix-validation.log 2>&1
FIX_EXIT_CODE=$?
if [ $FIX_EXIT_CODE -ne 0 ]; then
echo "⚠️ 修正がテスト失敗を引き起こしました。fix-validation.logをレビューしてください"
fi
# 4. 適用された修正を追跡
cat > fixes-applied.json << EOF
{
"timestamp": "$(date -Iseconds)",
"automated_fixes": {
"empty_catches": "Added error logging and re-throw",
"count": $(find . -name "*.js.bak" -type f ! -path "./node_modules/*" | wc -l)
},
"manual_fixes_required": $(echo $CATEGORIES | jq -r '.critical | length'),
"fix_guide": "fix-guide.md",
"validation_passed": $([ $FIX_EXIT_CODE -eq 0 ] && echo "true" || echo "false")
}
EOF
# 修正結果を保存
npx claude-flow memory store --key "testing/theater-detection/phase-5/coder/fixes-applied" --value "$(cat fixes-applied.json)"
# フェーズを完了
npx claude-flow hooks post-task --task-id "phase-5-fix"
npx claude-flow hooks session-end --export-metrics true
メモリパターン:
- 入力:
testing/theater-detection/phase-3/tester/execution-results - 出力:
testing/theater-detection/phase-5/coder/fixes-applied - 共有:
testing/theater-detection/shared/fix-tracking
成功条件:
- すべての重大シアターコードに対応(自動または手動)
- 修正前にバックアップを作成
- テスト実行を通じて修正を検証
- 複雑なケース向けの手動修正ガイドを作成
- 修正結果を追跡して保存
成果物:
- 修正されたコードファイル
- ロールバック用のバックアップファイル
- 修正検証テスト結果
- 残りの問題向けの手動修正ガイド
- 修正追跡JSON
メモリ調整
命名規則
testing/theater-detection/phase-{N}/{agent-type}/{data-type}
例:
testing/theater-detection/phase-1/analyzer/scan-resultstesting/theater-detection/phase-2/analyzer/theater-analysistesting/theater-detection/phase-3/tester/execution-resultstesting/theater-detection/phase-4/reviewer/final-reporttesting/theater-detection/shared/suspicious-files
エージェント間の共有
// スキャン結果を分析フェーズ用に保存
mcp__claude_flow__memory_store({
key: "testing/theater-detection/phase-1/analyzer/output",
value: JSON.stringify({
status: "complete",
results: {
empty_catches: 12,
noop_functions: 8,
always_pass_tests: 3,
total_issues: 23
},
timestamp: Date.now(),
artifacts: {
scan_summary: "scan-summary.json",
suspicious_files: ["auth.js", "payment.js", "logger.js"]
}
})
})
// ダウンストリーム分析用に取得
mcp__claude_flow__memory_retrieve({
key: "testing/theater-detection/phase-1/analyzer/output"
}).then(data => {
const scanResults = JSON.parse(data);
console.log(`${scanResults.results.total_issues}件の潜在的なシアターコード問題を発見`);
})
自動化スクリプト
フック統合
# タスク前フック - 検出セッションを初期化
npx claude-flow hooks pre-task \
--description "Theater code detection for repository: my-app" \
--session-id "theater-detection-$(date +%s)"
# 編集後フック - 修正中のコード変更を追跡
npx claude-flow hooks post-edit \
--file "src/auth/login.js" \
--memory-key "testing/theater-detection/coder/edits"
# タスク後フック - 完結してメトリクスをエクスポート
npx claude-flow hooks post-task \
--task-id "theater-detection" \
--export-metrics true
# セッション終了 - サマリーを生成
npx claude-flow hooks session-end \
--export-metrics true \
--summary "Theater detection completed: 8 issues found, 5 fixed automatically, 3 require manual review"
根拠のある検証
自己整合性チェック
各フェーズを完結する前に:
-
このアプローチは過去の成功した作業と一致しているか?
- 検出パターンを既知のシアターコード例と比較
- 分析方法を実証済みの技術に対して検証
- 修正戦略が確立されたベストプラクティスに従うことを確認
-
出力は述べられた目的をサポートするか?
- 検出された問題が実際にシアターコードであることを確認
- 分析が根本原因を正確に特定することを確認
- 修正が問題を解決し、新しい問題を引き起こさないことを確認
-
選択された方法はコンテキストに適切か?
- 検出の深さをコードベースサイズと重大性に合わせる
- 分析努力をプロジェクトリスクプロファイルに基づいてスケール
- 修正の複雑さを問題の重大度に応じて適用
-
内部的な矛盾はないか?
- 実行検証が静的分析と一致することをチェック
- 重大度分類が実際の影響と一致することを確認
- 修正されたコードがテストをパスし、要件を満たすことを確認
プログラム思考の分解
-
目的を正確に定義
- 目的:完全に見えるが動作しない非機能的なコードを特定
- 成功指標:100%のシアターコードを検出およびレポート
- 制約:誤検知を最小化(< 10%)
-
サブゴールに分解
- サブゴール1:疑わしいパターンについてコードベースをスキャン
- サブゴール2:意味のあるロジックについて実装を分析
- サブゴール3:実際の実行動作を検証
- サブゴール4:実行可能な推奨事項付きで検出結果をレポート
- サブゴール5:修正を適用してリグレッションがないか検証
-
依存関係を特定
- スキャンは分析の前に完了する必要がある
- 分析は実行検証の前に完了する必要がある
- 検証はレポートの前に完了する必要がある
- レポートは修正の前に完了する必要がある
-
選択肢を評価
- 検出アプローチ:パターンマッチング対AST分析対実行テスト
- 分析の深さ:表面レベル対深いセマンティック分析
- 修正戦略:自動化対手動対ハイブリッド
-
ソリューションを統合
- 初期検出にパターンマッチングを組み合わせ
- セマンティック分析を使用して誤検知を削減
- 明確な確認のために実行テストで検証
- 自動修正と手動ガイダンスの両方を提供
計画と解決フレームワーク
計画フェーズ:
- 検出するシアターコードパターンを定義
- 分類の信頼度閾値を確立
- 実行検証戦略を決定
- 修正優先付けフレームワークを作成
検証ゲート1: 戦略をレビュー
- パターンリストが既知のシアターの種類をカバーするか?
- 信頼度閾値は適切か?
- 実行検証は包括的か?
- 修正戦略は健全か?
実装フェーズ:
- 継続的な監視でフェーズ1~5を実行
- 検出精度と誤検險率を追跡
- 修正がテストを破壊していないことを検証
- 検出結果と推奨事項を文書化
検証ゲート2: 出力を検証
- すべてのシアターコードが検出される(誤検知なし)
- 誤検險率< 10%
- 修正がリグレッションなく正常に適用される
- レポートは包括的で実行可能
最適化フェーズ:
- 検出パターンを検出結果に基づいて改善
- 分析ヒューリスティックを向上
- 自動修正機能を強化
- 再発予防の推奨事項を更新
検証ゲート3: ターゲットが達成されたことを確認
- シアターコードが排除されるか文書化される
- リグレッション防止のために品質ゲートを更新
- チームが利用パターンについて教育を受ける
- 将来の検出のための監視が確立される
他のスキルとの統合
関連スキル:
when-validating-code-works-use-functionality-audit- 修正されたコードが実際に動作することを検証when-reviewing-code-comprehensively-use-code-review-assistant- シアター検出を含む包括的なレビューwhen-verifying-quality-use-verification-quality- シアターチェック付き品質検証when-auditing-code-style-use-style-audit- 包括的な品質チェック補完としてのスタイル監査
調整ポイント:
- 明らかな問題をフィルターするために機能監査の前にシアター検出を実行
- コードレビューワークフローにシアター検出を統合
- 修正の検証にシアター検出を使用して品質検証
- 包括的な品質チェックのためにスタイル監査と組み合わせ
メモリ共有:
# シアター検出結果を機能監査と共有
npx claude-flow memory store \
--key "functionality-audit/input/theater-cleared" \
--value "$(cat theater-detection-report.md)"
# コードレビューコンテキストを取得
npx claude-flow memory retrieve \
--key "code-review/output/suspicious-patterns"
よくある問題と解決策
問題1:誤検险率が高い
症状: フラグ付きの多くのファイルが実際に機能している 根本原因: 検出パターンが広すぎるか厳しすぎる 解決策:
- より多くのコンテキストで検出ヒューリスティックを改善
- AST ベースのセマンティック分析を追加
- 分類の信頼度閾値を上げる
- ボーダーラインケースの手動レビュー
問題2:シアターコードが検出されない
症状: 既知のシアターコードが検出を通過 根本原因: パターンが特定のシアタースタイルに一致しない 解決策:
- 新しい例でパターンライブラリを拡張
- すべての疑わしいファイルに実行検証を追加
- 一時的に信頼度閾値を下げる
- 高リスク領域の手動監査を実行
問題3:実行検証がクラッシュ
症状: テストランナーが検証中に失敗 根本原因: コードにランタイム依存関係またはサイドエフェクトがある 解決策:
# サンドボックス内で実行を分離
docker run -it --rm -v $(pwd):/workspace node:18 bash -c "cd /workspace && npm test"
# 外部依存関係をモック
cat > test-setup.js << 'EOF'
global.fetch = jest.fn();
global.console = { log: jest.fn(), error: jest.fn() };
EOF
問題4:自動修正がテストを破壊
症状: 修正を適用した後、テストスイートが失敗 根本原因: 修正が積極的すぎるか、コンテキストを認識していない 解決策:
- 修正の前にバックアップを作成
- 修正を段階的に適用し、各修正を検証
- 複雑なケースでは手動レビューを優先
- 問題のある修正をロールバックして文書化
問題5:複雑なシアターコードを修正できない
症状: 明らかなシアターが検出されたが、修正が些細ではない 根本原因: 要件またはビジネスロジック知識が不足している 解決策:
- コンテキスト付きの詳細な修正ガイドを生成
- 手動開発者レビュー用にフラグ付け
- テスト/ドキュメントから期待される動作を文書化
- TODO マークを使用してスタブ実装を作成
例
例1:空のエラーハンドラーを検出
# 空のcatchをスキャン
grep -rn "catch.*{}" src/
# 出力:
# src/auth/login.js:45: } catch (error) {}
# src/api/client.js:102: } catch (e) {}
# 実装を分析
cat src/auth/login.js | sed -n '40,50p'
# 表示: try { await authenticate() } catch (error) {}
# シアター指標:エラーが静かに飲み込まれている
# 修正:適切なエラーハンドリングを追加
sed -i 's/catch (error) {}/catch (error) { console.error("Authentication failed:", error); throw error; }/' src/auth/login.js
例2:no-op関数を検出
// 検出されたシアターコード
function validatePayment(transaction) {
// TODO:支払い検証を実装
return true; // 常にtrueを返す!
}
// 分析指標:
// - 関数は常にtrueを返す
// - 計算または検証ロジックがない
// - TODOコメントは不完全な作業を示唆
// 修正:実際の検証を実装
function validatePayment(transaction) {
if (!transaction || typeof transaction !== 'object') {
throw new Error('Invalid transaction object');
}
if (!transaction.amount || transaction.amount <= 0) {
throw new Error('Invalid transaction amount');
}
if (!transaction.currency || !['USD', 'EUR', 'GBP'].includes(transaction.currency)) {
throw new Error('Unsupported currency');
}
return true;
}
例3:常にパスするテストを検出
// 検出されたシアタートテスト
describe('Payment Processing', () => {
test('processes payment correctly', () => {
expect(true).toBe(true); // 常にパス!
});
});
// 分析指標:
// - テストアサーションはトートロジー(true === true)
// - 実際のコード実行または検証がない
// - 機能についての誤った信頼を提供
// 修正:実際の動作をテスト
describe('Payment Processing', () => {
test('processes payment correctly', async () => {
const transaction = {
amount: 100,
currency: 'USD',
method: 'credit_card'
};
const result = await processPayment(transaction);
expect(result).toHaveProperty('status');
expect(result.status).toBe('success');
expect(result).toHaveProperty('transactionId');
expect(typeof result.transactionId).toBe('string');
});
test('rejects invalid payment', async () => {
const transaction = { amount: -50 };
await expect(processPayment(transaction))
.rejects
.toThrow('Invalid transaction amount');
});
});
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- majiayu000
- ライセンス
- MIT
- 最終更新
- 2026/5/4
Source: https://github.com/majiayu000/claude-skill-registry / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。