研究パイプライン
目標: クリーンなチェックアウトと生の data/ から、bash pipeline/run_pipeline.sh を実行して、すべての処理済みデータセット、分析結果、レポート、原稿出力を再現すること。下流で使用される出力を生成するすべてのスクリプトは、pipeline/ 内のスクリプトによって依存関係順に呼び出されます。
レイアウト
pipeline/
_common.sh # 共有ヘルパー。すべての run_*.sh から source される(直接実行はしない)
run_pipeline.sh # トップレベルオーケストレータ:各ステージスクリプトを順に呼び出す
run_preprocessing.sh # ステージ:src/prepro/*.R -> output/prepro/
run_analyses.sh # ステージ:src/analysis/*.R -> output/analysis/
run_reports.sh # ステージ:src/reports/*.qmd -> output/reports/
run_manuscript.sh # ステージ:src/manuscript/* -> output/manuscript/
run_script.sh # 任意の単一の .R / .qmd を同じログ設定で実行
ステージ名はプロジェクトの src/ フォルダに従います(例:noh-survey は src/manu/ と run_manu.sh を使用)。存在するフォルダに対してのみステージを追加し、空のフォルダを作成しないでください。
規約
- すべてのスクリプトで
#!/usr/bin/env bashとset -euo pipefailを使用。 - すべてのスクリプトにヘッダーコメントを記述:そのスクリプトの機能、使用法(
bash pipeline/<name>.sh)、および最初に実行する必要があるステージ(Requires ...)。 _common.shを介してスクリプトはプロジェクトルートにcdするため、どのディレクトリからでも動作します。内部のすべてのパスはプロジェクトルートからの相対パスです。- ログ:
run_pipeline.shはPIPELINE_LOG_DIR=logs/run_pipeline_<timestamp>をエクスポートします。各ステージは${PIPELINE_LOG_DIR:-logs}/run_<stage>_<timestamp>/を作成するため、ステージはパイプライン実行下にネストされるか、単独で実行された場合はlogs/の下に配置されます。各 R スクリプト / Quarto ドキュメントは、独自の<name>_<HH-MM-SS>.txtにログを記録します。 - エラー時、
run_r/render_qmdは失敗したスクリプト、そのログパス、ログの最後の20行を表示し、パイプライン全体を停止します。 - ステージ内では、依存関係の深さに応じて
echo "=== Layer N: <理由> ==="ヘッダーの下に呼び出しをグループ化します。依存関係が明らかでない呼び出しには末尾にコメントを付けます(# needs output/prepro/redcap-joined.rds)。ステージ間の依存関係は、それ専用のラベル付きブロックに配置します(例:PCA結果を必要とする前処理スクリプトは、PCAの後の分析ステージに配置)。 - 各ステージは、書き込み先の出力ディレクトリを
mkdir -pで作成します。 - Quarto はソースフォルダ内にレンダリングするため、
render_qmdは結果をoutput/に移動します。フォルダ内のすべてのレポートが同じ方法でレンダリングされる場合は、for qmd in src/reports/*.qmdループを使用します(テンプレートはスキップ)。 - 時間のかかるステップの前には
echo "NOTE: ... は時間がかかる場合があります"を記述します。 - 呼び出しは明示的に、1行に1スクリプトずつ記述します。グロブで R スクリプトを自動検出しないでください。順序が依存関係グラフであり、読み取り可能である必要があります。
テンプレート
このスキルの templates/ ディレクトリからコピーして、内容を記入してください:
| テンプレート | 作成されるもの |
|---|---|
_common.sh | pipeline/_common.sh(そのままコピー) |
run_pipeline.sh | pipeline/run_pipeline.sh |
run_stage.sh | ステージごとに pipeline/run_<stage>.sh を1つ |
run_script.sh | pipeline/run_script.sh(そのままコピー) |
_common.sh が提供するもの:
init_log_dir <stage-name>:LOG_DIRを作成して設定run_r <script.R> [args...]:R スクリプトを実行し、stdout+stderr をログに記録(引数はログ名に追加され、noh-survey のグループループのようなパラメータ化された実行に使用)run_r_console <script.R> <stdout-file>:stdout を成果物として保存(例:output/manuscript/<name>-console.txt)、stderr はログに記録render_qmd <doc.qmd> <dest-dir-or-file> [quarto args...]:レンダリングして出力を移動。dest としてファイルパスを渡すと名前を変更(例:-P group:...ごとに1つのPDF)find_quarto:RStudio/Positron にバンドルされた Quarto にフォールバック
ワークフロー
1. プロジェクトの調査
src/(およびfns/、config/)と既存のpipeline/をリストします。pipeline/が存在する場合は、変更前にすべてのスクリプトを読み、この規約と異なる部分があればスタイルを維持します(確立されたパイプラインを移行する前に確認します)。- プロジェクトの CLAUDE.md / README を読み、指定された実行順序を確認します。
2. 依存関係の順序を決定
src/ 内のすべての .R / .qmd について、読み込みと書き込みを確認します:
grep -nE 'readRDS|read_rds|read_csv|read_excel|read\.csv|load\(|fread|readMat|source\(' <file>
grep -nE 'saveRDS|write_rds|write_csv|ggsave|save\(|writexl|write\.csv|pdf\(|png\(|tiff\(' <file>
各読み込みを、そのファイルを書き込むスクリプトと照合します。プロデューサーがいない読み込みは、data/ 内の生入力である必要があります。そうでない場合はフラグを立てます(欠落しているパイプラインステップか、手動で作成された出力のいずれか)。レイヤーを割り当てます:レイヤー0は data/ のみを読み込み、レイヤーNはレイヤー < N の出力を読み込みます。明白でない場合は、スクリプトを作成する前に結果の順序をユーザーに表示します。
特にユーザーが指定しない限り、archive/、misc/、テンプレート(*template*)、およびスクラッチスクリプトはスキップし、スキップしたものをリストします。
3. スクリプトを作成
テンプレートをコピーし、ステージとレイヤーを記入し、chmod +x pipeline/*.sh を実行します。
4. カバレッジと構文をチェック
bash <this-skill-dir>/scripts/check_coverage.sh <project-root>
これにより、すべてのパイプラインスクリプトに対して bash -n および(インストールされていれば)shellcheck が実行され、次にパイプラインスクリプトで名前が言及されていない src/ ファイルがリストされます。グブループでレンダリングされたファイルは未言及として表示されるため、手動で確認します。残りのすべてのファイルは、パイプラインに追加されるか、意図的に除外されたものとして確認されます。
5. 再現性監査
src/ を grep し、以下の問題を報告します(静かに修正はしません):
setwd(または絶対パス(/Users/、C:/、~/):他のマシンで動作しません- ランダム性(
sample(、rnorm(、boot、simr、set.seedなし)set.seed()がない場合 - インタラクティブ専用コード:
View(、file.choose(、readline(、browser( output/以外に書き込まれる出力(Quarto の render-then-move を除く)rm(list = ls()):スクリプトが1つのセッションで実行された場合の依存関係の欠落を隠します
6. 実行
完全なパイプラインは時間がかかり、output/ を上書きするため、実行前に確認します。最初に1つのステージまたは run_script.sh を1つのファイルで実行することを提案します。スクラッチからの再現性を確認するには、output/ を移動し(mv output output.bak、削除しない)、run_pipeline.sh を実行して比較します。
7. ドキュメント化
プロジェクトの CLAUDE.md / README に「パイプラインの実行」セクションを追加または更新します:1つのコマンド、各ステージの機能、および1つのスクリプトを実行する方法。
既存のパイプラインにスクリプトを追加する
- 新しいスクリプトが読み込む内容(ステップ2)を特定し、どのステージとレイヤーに属するかを判断します。
- そこに
run_r行を1つ追加し、明白でない場合は依存関係のコメントを付けます。 - その出力が後続のスクリプトに供給される場合、それらがまだ後続のレイヤーにあることを確認します。
scripts/check_coverage.shを実行します。