バッチ処理およびストリーミングパイプライン向けのYAML(設定記述言語)ベースの承認契約です。単なる「エラーが出ていない」ではなく、収束の検証が必要な場合に対応しています。 K個連続でゼロ件の結果ウィンドウ(一定期間の処理件数がゼロ)が続いた後にのみPASS(成功)を宣言します。 **次のような場合に使用:** - ストリーミングジョブ(常に流れてくるデータを処理する仕事) - ゆっくり時間をかけて処理する一括データの読み込み - 「待機中のキューが空になること」が成功の条件であるパイプライン
YAML-driven acceptance contract for batch and streaming pipelines that need convergence verification, not just "no exceptions". Declares PASS only after K consecutive zero-result windows (consecutive-zero-window convergence). Use for streaming jobs, slowly-draining backfills, or any pipeline whose success is "the pending queue is empty".
aidp-acceptance-contract — バッチ/ストリーミングジョブの収束検証「例外なし」でのパスは、ストリーミングやバックフィルのパイプラインにとって十分ではありません。 まだ処理中の行が残っている可能性があるためです。 このスキルは YAML ベースのコントラクトを設定し、K 回連続して未処理件数がゼロのウィンドウを確認して初めて PASS を宣言します。
成功 = "saveAsTable 完了" であるような単純な ETL には不要です。
1. マイグレーターが Pass-2 を完了まで実行する。
2. アクセプタンスコントラクトが定期的(sleep_between_s 秒ごと)にプローブを開始する。
3. 各プローブで pending_count_sql を実行し、pending = 0 であるかを確認する。
4. zero_window 回連続してゼロプローブを確認 → PASS を宣言する。
5. max_attempts に達しても収束しない場合 → ACCEPTANCE_CONTRACT_VIOLATED を宣言する。
マイグレーション全体の結果は FAIL に降格される。
reports/<MyJob>_acceptance.yaml に保存してください:
# <task_key> のアクセプタンスコントラクト
task_key: "<task_key>"
description: "リトライキューが空になるまで待機する"
pending_count_sql: "SELECT COUNT(*) AS pending FROM <sandbox_schema>.<retry_queue_table> WHERE status = 'PENDING'"
zero_window: 3 # PASS に必要な K 回連続のゼロウィンドウ数
sleep_between_s: 30 # プローブ間隔(秒)
max_attempts: 60 # 上限。60 × 30秒 = 30分のハードキャップ
# オプション: クラスターの上書き(デフォルトは job_migrate のクラスターを使用)
cluster_id: null
# オプション: 違反時の通知フック(収束前に max_attempts に達した場合に1回呼び出される)
on_violation_log_path: "/tmp/<MyJob>_acceptance.log"
YAML がマニフェストと同じ場所に存在する場合、コントラクトは job_migrate.py によって自動的に読み込まれます:
# 規則: <MyJob>_manifest.json と <MyJob>_acceptance.yaml を同じディレクトリに配置
ls reports/
# → reports/<MyJob>_manifest.json
# → reports/<MyJob>_acceptance.yaml
python3 ${CLAUDE_PLUGIN_ROOT}/engine/scripts/job_migrate.py \
--manifest reports/<MyJob>_manifest.json \
--acceptance-contract reports/<MyJob>_acceptance.yaml \
# + その他の引数
--acceptance-contract を省略した場合、コントラクトはスキップされます
(デフォルト動作 — PASS = Pass-2 の全セルがグリーン)。
YAML の task_key フィールドは、マニフェスト内の 1つのタスク にコントラクトをスコープします。
複数のタスクに収束確認が必要な場合は、リスト形式で記述します:
contracts:
- task_key: "<task_a>"
pending_count_sql: "SELECT COUNT(*) FROM <schema>.<queue_a> WHERE pending"
zero_window: 3
sleep_between_s: 30
max_attempts: 60
- task_key: "<task_b>"
pending_count_sql: "SELECT COUNT(*) FROM <schema>.<queue_b> WHERE pending"
zero_window: 5
sleep_between_s: 60
max_attempts: 30
コントラクトは、対応するタスクの完了後に順次実行されます。
実行後、JOB_REPORT.md にアクセプタンスコントラクトのセクションが追加されます:
## Acceptance contracts
| task_key | status | windows_observed | converged_at |
|---|---|---|---|
| <task_a> | PASS | 3 consecutive zeros | 2026-XX-XX HH:MM:SS |
| <task_b> | ACCEPTANCE_CONTRACT_VIOLATED | 60 attempts, 0 consecutive zeros | -- |
いずれか1つでも コントラクトが VIOLATED になった場合、
セルレベルの成功状態に関わらず、全体の RESULT: は PASS から ACCEPTANCE_CONTRACT_VIOLATED に降格されます。
pending_count_sql の書き方クエリに関するいくつかの指針:
sleep_between_s ごとに実行される。
適切なフィルター/パーティションを追加すること記述例:
-- ストリーミングリトライキュー
SELECT COUNT(*) AS pending
FROM <sandbox_schema>.<retry_queue_table>
WHERE status IN ('PENDING','RETRYING')
AND ingest_ts > current_date - INTERVAL 1 DAY
-- バックフィルの進捗
SELECT (target_count - processed_count) AS pending
FROM <sandbox_schema>.backfill_progress
WHERE backfill_id = '<id>'
-- ストリーミングウォーターマークのギャップ
SELECT GREATEST(
0,
CAST((unix_timestamp(current_timestamp()) - unix_timestamp(max(event_ts))) / 60 AS INT)
) AS pending
FROM <sandbox_schema>.<streaming_output_table>
job_migrate.py がすでにセルを実行済みです。
コントラクトはあくまで 実行後の検証ステップ です。pending_count_sql が担います。aidp-fixup-cell を使用してください。max_attempts を増やす)aidp-acceptance-contract — convergence verification for batch/streaming jobsA "no exception" pass is not enough for streaming or backfill pipelines. They might still be processing rows that haven't drained yet. This skill wires up a YAML-driven contract: PASS only after K consecutive empty-pending windows.
Not needed for plain ETL where success = "the saveAsTable finished".
1. Migrator runs Pass-2 to completion.
2. Acceptance contract starts probing periodically (every `sleep_between_s` seconds).
3. Each probe runs `pending_count_sql` and checks `pending = 0`.
4. After `zero_window` consecutive zero-probes → declare PASS.
5. If we hit `max_attempts` without convergence → declare ACCEPTANCE_CONTRACT_VIOLATED.
Overall migration result is demoted to FAIL.
Save at reports/<MyJob>_acceptance.yaml:
# Acceptance contract for <task_key>
task_key: "<task_key>"
description: "Wait until the retry queue drains"
pending_count_sql: "SELECT COUNT(*) AS pending FROM <sandbox_schema>.<retry_queue_table> WHERE status = 'PENDING'"
zero_window: 3 # K consecutive zero windows required for PASS
sleep_between_s: 30 # seconds between probes
max_attempts: 60 # ceiling; 60 × 30s = 30-min hard cap
# Optional: override the cluster (default = use job_migrate's cluster)
cluster_id: null
# Optional: notify-on-violation hook (called once if max_attempts hit before convergence)
on_violation_log_path: "/tmp/<MyJob>_acceptance.log"
The contract is loaded by job_migrate.py automatically if the YAML exists alongside the manifest:
# Convention: <MyJob>_manifest.json + <MyJob>_acceptance.yaml side by side
ls reports/
# → reports/<MyJob>_manifest.json
# → reports/<MyJob>_acceptance.yaml
python3 ${CLAUDE_PLUGIN_ROOT}/engine/scripts/job_migrate.py \
--manifest reports/<MyJob>_manifest.json \
--acceptance-contract reports/<MyJob>_acceptance.yaml \
# + the rest of the args
If --acceptance-contract is omitted, the contract is skipped (default behavior — PASS = Pass-2 cells all green).
The YAML's task_key field scopes the contract to ONE task in the manifest. If you have multiple tasks needing convergence, write a list:
contracts:
- task_key: "<task_a>"
pending_count_sql: "SELECT COUNT(*) FROM <schema>.<queue_a> WHERE pending"
zero_window: 3
sleep_between_s: 30
max_attempts: 60
- task_key: "<task_b>"
pending_count_sql: "SELECT COUNT(*) FROM <schema>.<queue_b> WHERE pending"
zero_window: 5
sleep_between_s: 60
max_attempts: 30
Contracts run sequentially after their respective tasks complete.
After a run, JOB_REPORT.md will include an acceptance-contract section:
## Acceptance contracts
| task_key | status | windows_observed | converged_at |
|---|---|---|---|
| <task_a> | PASS | 3 consecutive zeros | 2026-XX-XX HH:MM:SS |
| <task_b> | ACCEPTANCE_CONTRACT_VIOLATED | 60 attempts, 0 consecutive zeros | -- |
If ANY contract is VIOLATED, the overall RESULT: line is demoted from PASS to ACCEPTANCE_CONTRACT_VIOLATED regardless of cell-level success.
pending_count_sqlSome rules of thumb for the query:
sleep_between_s. Add appropriate filters / partitions.Example shapes:
-- Streaming retry queue
SELECT COUNT(*) AS pending
FROM <sandbox_schema>.<retry_queue_table>
WHERE status IN ('PENDING','RETRYING')
AND ingest_ts > current_date - INTERVAL 1 DAY
-- Backfill progress
SELECT (target_count - processed_count) AS pending
FROM <sandbox_schema>.backfill_progress
WHERE backfill_id = '<id>'
-- Streaming watermark gap
SELECT GREATEST(
0,
CAST((unix_timestamp(current_timestamp()) - unix_timestamp(max(event_ts))) / 60 AS INT)
) AS pending
FROM <sandbox_schema>.<streaming_output_table>
pending_count_sql.aidp-fixup-cell.max_attempts), (b) the queue is genuinely stuck (data issue, scheduler issue), or (c) the contract is wrong (check the SQL).原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。