mcpField
S
sobriety-tools-guardian

sobriety-tools-guardian

github.com/curiositech開発257155 回インストール2 日前に更新
リポジトリ

sobriety-tools-guardian について

sobriety.toolsの高速化とオフライン対応を重視する開発スキルです。危機時に重要な処理経路の最適化、性能監視、回帰検出を扱います。

主な機能

  1. 01ミーティング検索のキャッシュ最適化
  2. 02連絡先のオフライン利用
  3. 03チェックイン処理の高速化
  4. 04性能とバンドルサイズの監査
  5. 05危機に関わる利用パターンの検出
  6. 06性能回帰の課題登録

活用シーン

  1. 01sobriety.toolsのデプロイ前の変更確認
  2. 02検索や連絡先表示の遅延調査
  3. 03危機リソースのオフライン利用確認

インストール

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

$npx skills add https://github.com/curiositech/some_claude_skills --skill sobriety-tools-guardian

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
CRISIS_DETECTION.md
PERFORMANCE_PATTERNS.md
scripts/
bundle-analyzer.ts
cache-health.ts
crisis-path-test.ts
perf-audit.ts

詳細

Sobriety Tools Guardian

使命:sobriety.tools が命を救えるだけの速さを保ちます。危機に直面したフェンタニル依存症の人に残された時間は、数分ではなく数秒です。アプリは瞬時に読み込まれ、オフラインで動作し、助けを求める前に支援を提示しなければなりません。

パフォーマンスが生死を分ける理由

CRISIS TIMELINE:
0-30 seconds:  User opens app in distress
30-60 seconds: Looking for sponsor number or meeting
60-120 seconds: Decision point - call someone or use
2+ minutes:    If still searching, may give up

EVERY SECOND OF LOAD TIME = LIVES AT RISK

核心となる事実:これはビジネスアプリではありません。パフォーマンスの低下は「UX の悪化」ではなく、危機に直面した人が利用をやめることにつながります。スピナーを見つめているユーザーは、生きるか死ぬかを決めようとしているかもしれません。

技術スタック固有の最適化に関する知識

アーキテクチャ(完全に把握しておくこと)
Next.js 15 (static export) → Cloudflare Pages
    ↓
Supabase (PostgREST + PostGIS)
    ↓
Cloudflare Workers:
  - meeting-proxy (KV cached, geohash-based)
  - meeting-harvester (hourly cron)
  - claude-api (AI features)
重要なパフォーマンス経路

1. ミーティング検索(必ず <500ms)

User location → Geohash (3-char ~150km cell)
    → KV cache lookup (edge, ~5ms)
    → Cache HIT: Return immediately
    → Cache MISS: Supabase RPC find_current_meetings
        → PostGIS ST_DWithin query
        → Store in KV, return

ボトルネック:Supabase クエリのコールドスタート。解決策:/warm エンドポイント経由で主要な 30 の都市圏を事前にウォームアップします。

2. スポンサー/連絡先リスト(必ず <200ms)

User opens contacts → Local IndexedDB first
    → Show cached contacts instantly
    → Background sync with Supabase
    → Update UI if changes

アンチパターン:連絡先を表示する前にネットワーク応答を待つこと。危機の際は、古いデータでもすぐに表示します。

3. チェックインフロー(最初の入力まで必ず <100ms)

Open check-in → Pre-rendered form shell
    → Load previous patterns async
    → Submit optimistically
オフラインファーストの要件(絶対厳守)
// Service Worker must cache:
const CRISIS_CRITICAL = [
  '/contacts',           // Sponsor phone numbers
  '/safety-plan',        // User's safety plan
  '/meetings?saved=true', // Saved meetings list
  '/crisis',             // Crisis resources page
];

// These MUST work with zero network:
// 1. View sponsor contacts
// 2. View safety plan
// 3. View saved meetings (even if stale)
// 4. Record check-in (sync when online)

危機検知のパターン

ジャーナルの感情分析シグナル
// RED FLAGS (surface help proactively):
const CRISIS_INDICATORS = {
  anger_spike: 'HALT angry score jumps 3+ points',
  ex_mentions: 'Mentions ex-partner 3+ times in week',
  isolation: 'No check-ins for 3+ days after daily streak',
  time_distortion: 'Check-ins at unusual hours (2-5am)',
  negative_spiral: 'Consecutive declining mood scores',
};

// When detected: Surface sponsor contact, safety plan link
// DO NOT: Be preachy or alarming. Gentle nudge only.
チェックイン分析
-- Detect concerning patterns
SELECT user_id,
  AVG(angry_score) as avg_anger,
  AVG(angry_score) FILTER (WHERE created_at > NOW() - INTERVAL '3 days') as recent_anger,
  COUNT(*) FILTER (WHERE EXTRACT(HOUR FROM created_at) BETWEEN 2 AND 5) as late_night_checkins
FROM daily_checkins
WHERE created_at > NOW() - INTERVAL '30 days'
GROUP BY user_id
HAVING AVG(angry_score) FILTER (WHERE created_at > NOW() - INTERVAL '3 days') >
       AVG(angry_score) + 2;

パフォーマンスの監視とログ記録

追跡する主要な指標
// Client-side (log to analytics)
const PERF_METRICS = {
  ttfb: 'Time to First Byte',
  fcp: 'First Contentful Paint',
  lcp: 'Largest Contentful Paint',
  tti: 'Time to Interactive',

  // App-specific critical paths
  contacts_visible: 'Time until sponsor list renders',
  meeting_results: 'Time until first meeting card shows',
  checkin_interactive: 'Time until check-in form accepts input',
};

// Log slow paths
if (contactsVisibleTime > 500) {
  logPerf('contacts_slow', { duration: contactsVisibleTime, network: navigator.connection?.effectiveType });
}
パフォーマンスのリグレッションを自動検知
# scripts/perf-audit.sh - Run in CI
lighthouse https://sobriety.tools/meetings --output=json --output-path=./perf.json
SCORE=$(jq '.categories.performance.score' perf.json)
if (( $(echo "$SCORE < 0.9" | bc -l) )); then
  echo "Performance regression: $SCORE"
  # Create GitHub issue automatically
fi

問題の自動検知と起票

バックグラウンドのパフォーマンススキャナー
// Run hourly via Cloudflare Worker cron
async function performanceAudit() {
  const checks = [
    checkMeetingCacheHealth(),
    checkSupabaseQueryTimes(),
    checkStaticAssetSizes(),
    checkServiceWorkerCoverage(),
  ];

  const issues = await Promise.all(checks);
  const problems = issues.flat().filter(i => i.severity === 'high');

  for (const problem of problems) {
    await createGitHubIssue({
      title: `[Auto] Perf: ${problem.title}`,
      body: problem.description + '\n\n' + problem.suggestedFix,
      labels: ['performance', 'automated'],
    });
  }
}

よくあるアンチパターン

1. ネットワーク応答を待ってから連絡先を表示する

症状:連絡先ページが取得中にスピナーを表示する 問題:危機に直面したユーザーに、スポンサーの電話番号ではなく読み込み状態が表示される 解決策:

// WRONG
const { data: contacts } = useQuery(['contacts'], fetchContacts);

// RIGHT
const { data: contacts } = useQuery(['contacts'], fetchContacts, {
  initialData: () => getCachedContacts(), // IndexedDB
  staleTime: Infinity, // Never refetch automatically
});
2. ミーティング検索をキャッシュしない

症状:検索のたびに Supabase にアクセスする 問題:検索のたびに 200~500ms の遅延が発生する 解決策:ジオハッシュベースの KV キャッシュ(meeting-proxy にはすでに実装済み)

3. 大きなバンドルが操作性を妨げる

症状:TTFB が速いにもかかわらず TTI が高い 問題:JavaScript バンドルがメインスレッドをブロックする 解決策:

// Lazy load non-critical features
const JournalAI = dynamic(() => import('./JournalAI'), { ssr: false });
const Charts = dynamic(() => import('./Charts'), { loading: () => <ChartSkeleton /> });
4. チェックイン送信が同期処理になっている

症状:ネットワークリクエスト中、ボタンが無効のままになる 問題:ユーザーが処理に失敗したと思い、アプリを閉じてしまう 解決策:楽観的 UI とバックグラウンド同期キュー

パフォーマンス最適化チェックリスト

デプロイの前に毎回確認
  • バンドルサイズの増加が < 5KB
  • 重要な経路に新たな同期ネットワーク呼び出しがない
  • Lighthouse のパフォーマンススコアが >= 90
  • オフラインモードをテスト済み(DevTools でネットワークを無効化)
毎週の監査
  • Supabase の低速クエリログを確認する
  • KV キャッシュのヒット率を確認する(>80% が目安)
  • 実ユーザー指標(RUM)で P95 の読み込み時間を分析する
  • 3G の速度制限を設定した接続でテストする
毎月の詳細な調査
  • React のレンダーをプロファイリングする(なぜ再レンダーされたのか?)
  • サードパーティスクリプトを監査する
  • 未使用の依存関係を確認し、削除する
  • 実機で危機対応フローをエンドツーエンドでテストする

利用可能なスクリプト

スクリプト目的
scripts/perf-audit.tsLighthouse とカスタムチェックを実行し、問題を起票する
scripts/cache-health.tsKV キャッシュのヒット率と古さを確認する
scripts/crisis-path-test.ts危機対応に不可欠なフローを自動テストする
scripts/bundle-analyzer.tsバンドルサイズの経時変化を追跡する

連携ポイント

meeting-harvester との連携
  • 収集後、主要な都市圏のキャッシュをウォームアップする
  • 収集所要時間とミーティング件数を監視する
  • 収集に失敗したらアラートを出す(データが古いと、ミーティング時間を誤って表示する)
チェックインシステムとの連携
  • 危機検知のためにパターンを分析する
  • 送信成功率を追跡する
  • オフラインキューの深さを監視する
連絡先/スポンサーとの連携
  • オフラインで利用できることを確保する
  • 表示までの時間を追跡する
  • 同期の失敗を監視する

エスカレーションする条件

次の場合は、直ちに GitHub issue を作成してください:

  • Lighthouse スコアが 85 未満に低下した
  • ミーティング検索の P95 が 1 秒を超えた
  • 連絡先ページに 200ms を超える読み込み状態がある
  • Service Worker が危機対応ページをキャッシュできない
  • 危機が起こりやすい時間帯(夕方/週末)に、ユーザーから「読み込めなかった」と報告があった

これは回復を支援するアプリです。パフォーマンスは機能の一つではありません。誰かが助けを得られるか、誰にも看取られずに亡くなるかを分けるものです。

コメント