この記事で解決できること
- 課金ゲートや目標の達成判定を「人間が記録する」設計にした結果、記録が遅延するパターンとその根本原因
- Supabase の SQL 閾値で自動判定・自動記録する番人 routine の設計方針
- 施策を外部ツールで実行した場合に Supabase でトレースできなくなる問題への対策
環境
- Supabase(PostgreSQL + Edge Functions)
- Claude Code(routine 自動実行)
- dev_journal テーブルで実体験を記録・管理
何が起きたか
第1課金ゲートの判定期限は 2026-08-22。合格条件は「実支払い ≥ 5件(本人除く)」だった。
実際に Supabase を確認した結果:
-
article_purchasesテーブルの総件数: 0件(全期間) - 前提施策(有料 note + X 広告)の実走状況: DB 外・未計測
記録が dev_journal に書き込まれたのは 2026-09-04。判定期限から 13 日後。
結果: FAIL
原因
遅延の直接原因は「ゲートの判定・記録を人間が行う設計」にあった。
2 つの問題が同時に発生した:
問題 1: 施策が DB 外で実行された
有料 note と X 広告の実走は、note のダッシュボードと X 広告管理画面上で行われた。これらは Supabase に記録されないため、「実走されたかどうか」を DB で確認できない状態になっていた。
問題 2: 人間が判定・記録するタスクは後回しになる
AI が記事を自動生成・push する部分は自動化されていた。しかし「その結果を評価して記録する」行為は人間に残っていた。他のタスクが積み重なると、評価・記録は遅延する。
対策:SQL 閾値による自動判定設計
次回からは以下の方針で設計を切り替える。
1. ゲート条件を SQL で定義する
-- 課金ゲート達成判定
SELECT COUNT(*) >= 5 AS gate_passed
FROM article_purchases
WHERE user_id != 'masatoman_owner_id'
AND purchased_at >= '2026-08-22'::date - INTERVAL '30 days'
AND purchased_at <= '2026-08-22'::date;
ゲート条件を数値閾値として Supabase のクエリで表現できれば、人間が判定する必要はない。
2. 番人 routine が定期実行する
// routine(Claude Code が定期実行)
const result = await supabase
.from('article_purchases')
.select('count', { count: 'exact' })
.neq('user_id', OWNER_ID);
const gatePassed = (result.count ?? 0) >= 5;
await supabase.from('dev_journal').insert({
occurred_at: new Date().toISOString(),
type: 'gate_judgment',
title: `課金ゲート自動判定: ${gatePassed ? 'PASS' : 'FAIL'}`,
body: `実支払い件数: ${result.count}件 / 閾値: 5件`,
severity: gatePassed ? 'info' : 'high',
topics: ['payment-gate', 'auto-judgment'],
});
3. 施策の実走も Supabase 経由で記録する
外部ツール(note・X 広告)の実走を Supabase に記録するための経路を確保する:
- Webhook: note API が提供する場合はその通知を受け取る
- Polling バッチ: 外部サービスの API を日次で叩いて結果を insert
- 手動 insert: 実行した事実だけを即日 dev_journal に記録するルール化
まとめ
| 旧設計 | 新設計 |
|---|---|
| 人間がゲート達成を確認・記録 | 番人 routine が SQL 閾値で自動記録 |
| 施策を外部ツールで実行(DB 外) | 施策実走もSupabase にログを残す |
| 記録のタイミングが不定 | 定期実行(スケジュール固定) |
「AI に任せた」と言いながら、判定という行為だけ人間が持っていた。それが今回の穴だった。
AI ツールを業務に組み込む設計の実験ログを書いています。 https://masatoman.net