アクションアイテム → Todoist + メール下書き
設定 — 開始前に読むこと
../config/user.json を読む(~/executive-assistant-skills/config/user.json に解決)。
以下を抽出し、全体で使用する:
name,full_name— ミーティングノート内であなたのアクションアイテムを特定するため(例:「Gonto (Martin)」)whatsapp— 結果の配信用workspace— OpenClawワークスペースの絶対パス
これらの値を取得するまで先に進まないでください。
デバッグロギング(必須)
../config/DEBUG_LOGGING.md を読み、完全な規約を理解すること。すべての主要なステップで python3 {user.workspace}/scripts/skill_log.py action-items <level> "<message>" ['<details>'] を使用する。すべての外部呼び出し(gog、mcporter、todoist-cli)の前後にログを記録する。エラーが発生した場合は、続行する前に完全なコマンドとstderrをログに記録する。
手順
0. 今日のカレンダーを確認する(両方のアカウント)
Granolaに問い合わせる前に、両方のカレンダーから今日の実際のミーティングを取得して、何が予定されているかを把握します:
python3 {user.workspace}/scripts/skill_log.py action-items INFO "アクションアイテム実行を開始"
# 今日の日付(YYYY-MM-DD)と明日の日付を取得
TODAY=$(date -u -d "$(TZ=America/Argentina/Buenos_Aires date +%Y-%m-%d)" +%Y-%m-%d)
TOMORROW=$(date -u -d "$(TZ=America/Argentina/Buenos_Aires date -d '+1 day' +%Y-%m-%d)" +%Y-%m-%d)
# 両方のカレンダーを確認
gog --account {user.primary_email} --no-input calendar list primary --from "${TODAY}T00:00:00-03:00" --to "${TOMORROW}T00:00:00-03:00" --json 2>&1
gog --account {user.work_email} --no-input calendar list primary --from "${TODAY}T00:00:00-03:00" --to "${TOMORROW}T00:00:00-03:00" --json 2>&1
結果をログに記録:python3 {user.workspace}/scripts/skill_log.py action-items DEBUG "カレンダーイベントが見つかりました" '{"primary": N, "work": M, "total": N+M}'
両方のカレンダーからのイベントをマージする。参加者がいるミーティングにフィルタリングする(個人イベントはスキップ)。これにより、今日発生したミーティングの真実の情報が得られます。これをGranolaの結果のクロスチェックに使用し、Granolaが見逃したミーティングを特定します。
重要な日付構文: -03:00 オフセット付きの明示的なISO8601日付を使用すること。gogフラグで +1 day、today、tomorrow のような相対表現は使用しないでください。これらはサポートされていない可能性があります。常に実際の日付文字列を計算してください。
1. Granolaから今日のミーティングを取得する
タイムゾーンメモ: Granolaはミーティング時間をUTCで保存します。ART(UTC-3)の場合、「今日」をクエリするには、UTCで今日の日付と明日の日付の両方を使用することを意味します。例:3月3日 ARTの場合、custom_start: "2026-03-03" と custom_end: "2026-03-04" をクエリして、ARTの日のすべてのミーティングをキャプチャします。
mcporter call granola list_meetings --args '{"time_range": "custom", "custom_start": "<今日 YYYY-MM-DD>", "custom_end": "<明日 YYYY-MM-DD>"}'
ミーティングIDとタイトルを収集します。ログ:python3 {user.workspace}/scripts/skill_log.py action-items INFO "Granolaミーティングが見つかりました" '{"count": N, "titles": [...]}'
カレンダーとのクロスチェック: Granolaミーティングをステップ0のカレンダーイベントと比較します。参加者がいるカレンダーミーティングで、Granolaで一致するものがない場合(15分以内の時間的重複)、警告をログに記録します。そのミーティングは記録されていない可能性があります。Granolaにあるもので処理を進めますが、一致しないミーティングを出力にメモします。
ミーティングがない場合(Granolaまたはカレンダーのいずれか)はスキップします。
2. Granolaに自分のアクションアイテムとメールトリガーを問い合わせる
mcporter call granola query_granola_meetings --args '{"query": "これらのミーティングから、{user.name} ({user.full_name}) の個人的なアクションアイテム、フォローアップ、およびコミットメントはすべて何ですか? 彼自身が行う必要があることのみで、他の人がコミットしたことは含めません。各アイテムについて、関連する特定の人物、会社、プロジェクト、または候補者名を含めてください。汎用的な参照は決して使用しないでください。また、電子メールでの何らかのアクション(紹介、フォローアップ、ドキュメント送信、情報共有、人との連絡など)を行うという約束、および各ミーティングがその人/会社との最初のミーティングかフォローアップかを特定してください。", "document_ids": ["<id1>", "<id2>", ...]}'
すべてのミーティングIDを渡します。引用リンクは保持します。
3. Todoistタスクを作成する
注: 同じコマンドで環境をロードすること。各シェル呼び出しは新しいセッションです。
CLIの使用法については {user.workspace}/skills/todoist-api/SKILL.md を読むこと。各アクションアイテムについて:
source {user.workspace}/.env && todoist-cli add "<アクション可能なタイトル>" --description "<コンテキスト:ミーティング名、ミーティング日時、依頼者、Granolaリンク>" --priority <1-4> --labels "<関連ラベル>"
タスクの説明には以下を含める必要があります:
- ミーティング名(例:「Braintrust Weekly」)
- ミーティングの日時(例:「2026年3月5日(水) 15:00 ART」)
- 依頼者/コンテキスト
- Granola引用リンク
ルール:
- 自分のアクションのみ: Granolaの要約には、所有権が明確でない「次のステップ」がリストされていることがよくあります。懐疑的になりましょう。アクションが他の人に属する可能性がある場合(例:「自分のコンテンツを消化する」、「空き状況を確認する」、「折り返し連絡する」)、タスクを作成しないでください。疑問がある場合は、所有タスクではなくフォローアップタスク(「XにYについて連絡」)を作成します。
- 他者のコミットメントをキャプチャする: 他の人が何かすると言った場合(例:「2日後に折り返す」)、適切な期日を設定したフォローアップ/連絡タスクを作成します。自分でそのことを行うタスクではありません。
- 具体性: すべてのタスクには、人物/会社/プロジェクトの具体的な名前を含める必要があります。
- 期日: 暗黙の期限がある場合は、自然言語で
--dueを使用します。 - ラベル: 適宜タグ付け:紹介、フォローアップ、メール、緊急。
- 優先度: 4=緊急/時間的制約あり、3=約束した納品物、2=一般的なフォローアップ、1=通常
連続ステップのタスク分割禁止(必須)
同じワークフローの一部であるステップに対して、別々のタスクを作成しないでください。アクションが「Xを準備してからXを送信する」である場合、それは1つのタスクであり、2つではありません。例:
- ❌ 「提案書を作成」+「提案書を送信」 → ✅ 「提案書を作成して送信」
- ❌ 「下書きを書く」+「メールを送信」 → ✅ 「Xにメールの下書きを書いて送信」
- ❌ 「デッキをレビュー」+「デッキを共有」 → ✅ 「Xとデッキをレビューして共有」
意図ごとに1つのタスク。ユーザーは自然と順番に手順を実行します。
タスク重複排除(必須)
タスクを作成する前に、オープンなTodoistタスクに対して重複チェックを実行します:
- 提案されたタイトルを正規化する(小文字化、句読点の除去、空白の圧縮)
- オープンタスクを検索する(
source {user.workspace}/.env && todoist-cli list --filter "!completed")し、正規化されたコンテンツを比較する - ほぼ同一の紹介タスクは重複として扱う(例:「DavidをMarcosに紹介」 vs 「David (n8n) をMarcos Nilsに紹介」)
- 重複が存在する場合:新しいタスクを作成しない。既存のタスクの説明にミーティングコンテキストを追加する(有用な場合)
- 出力では、重複排除の決定を「重複としてスキップ:」の下に報告する
4. フォローアップメールの下書きを作成する
下書きが必要なメール(紹介、フォローアップ、VC返信、ドキュメント送信など)について:
~/executive-assistant-skills/email-drafting/SKILL.mdを読んで従うこと — これがすべての下書きルール、スタイル、テンプレート、人間味付け、配信の唯一の情報源です- ミーティングノートから下書きトリガーを特定する:
- 約束された紹介またはフォローアップ
- 約束されたドキュメント/PDF/デッキ
- VCまたは新しいリードとの初回電話
- 誰かにメールするという約束
- 下書きするかどうか疑問がある場合 → 下書きする
- 例外: 以下の提案のみのコミットメントルールがこれを上書きします。最初に提案を作成するというコミットメントの場合は、下書きを作成しないでください。Todoistタスクのみを作成します。
- HGPデッキ:
{user.workspace}/assets/HGP_Deck_2025.pdf—--attach {user.workspace}/assets/HGP_Deck_2025.pdfで添付します。メール本文では「Hypergrowth Partners デッキ」と記載します(「1ページ」、「弊社デッキ」ではありません) - 既知の連絡先への紹介を下書きする場合: 以前の紹介メールを検索し、同じ形式、トーン、説明を使用します
紹介に関する厳格な要件(必須)
アクションアイテムに紹介が含まれている場合、以下に正確に従ってください:
- 紹介ペアごとに1つの別個の紹介下書きを作成します(複数の紹介を1つの一般的なフォローアップにまとめないでください)。
- 件名は明示的である必要があります:
紹介:<人物A> <> <人物B>。 - 本文には以下を含める必要があります:
- 各人物が誰であるかの1行の説明、
- この紹介が行われる理由の1行のコンテキスト、
ここからはお二人でお進めください。と{user.signature}で締めくくる。
- 紹介が約束されている場合、紹介の下書きを「本日は良いミーティングでした」のような一般的な要約メールに決して置き換えないでください。
- 受信者のメールアドレスがわかっている場合は、すぐにGmailの下書きを作成します。メールアドレスがない場合でも、完全な下書きテキストを生成し、
MISSING_EMAIL:<名前>を報告します。 - WhatsAppの結果には、各紹介ペアと、それがGmailで下書きされたか、メールアドレス不足でブロックされたかを示す「作成された紹介下書き:」セクションを含めます。
初回VC / 初回ディールフローコールのフォローアップ(必須)
ミーティングがVCまたはディールフロー企業との初回の電話である場合:
- 初回ミーティングのフォローアップ下書きを作成します(以下の提案のみルールでブロックされていない場合)。
- 本文では、ミーティング固有のコンテキスト(議論された内容、明示的な次のステップ、具体的なオファー)を使用し、一般的な儀礼的な言葉は使用しません。
- 自分のポジショニング(どのように仕事をしているか)を含め、関連する場合は
{user.workspace}/assets/HGP_Deck_2025.pdfを添付します。 - 「本日は良いミーティングでした」は、この初回ミーティングフォローアップクラスにのみ使用できます。
提案のみのコミットメントルール(必須)
「提案を作成する」(または同等:最初に準備する提案/デッキ/スコープの下書き)ことをコミットした場合:
- まだ外部へのメールを作成しないでください。
- 提案を作成して送信するための単一のTodoistタスクを作成します。例:「Gabriel (BairesDev) へのアドバイザリー提案を作成して送信」
- 「作成」と「送信」の別々のタスクを作成しないでください。それは冗長です。1つのタスクで完全なライフサイクルをカバーします。
5. 既存のTodoistタスクが今日のミーティングで完了したかどうかを確認する
アクションアイテムを処理した後、既存のオープンなTodoistタスクが今日のミーティングで対応/完了されたかどうかを確認します:
- オープンタスクを一覧表示:
source {user.workspace}/.env && todoist-cli list - 各ミーティングについて、議論がオープンタスクをカバーまたは完了したかどうかを確認します(例:「AI戦略をColinと共有」→ 電話でColinと直接AI戦略について議論)
- タスクがミーティングで明確に完了した場合は、それを完了します:
source {user.workspace}/.env && todoist-cli complete <task_id> - 出力で完了したタスクを報告します:「✅ 完了:[タスク] — [ミーティング名] 中に完了」
これにより、Todoistがクリーンに保たれ、実際に起こったことが反映されます。
エラーハンドリング
gog calendarが失敗した場合:エラーを完全なコマンド + stderr とともにログに記録する(python3 {user.workspace}/scripts/skill_log.py action-items ERROR "gog calendar 失敗" '{"command": "...", "stderr": "..."}')、もう一方のアカウントおよび/またはGranolaのみで続行する。mcporter call granolaが認証エラーで失敗した場合:「⚠️ Granola認証期限切れ、mcporter auth granola --resetを実行してください」と報告し、停止する。todoist-cliが失敗した場合:.envが source されていて、トークンが有効であることを確認する。エラーを報告する。- Grain MCP が利用できない場合:Granolaのみの抽出で続行し、出力に「⚠️ Grain利用不可、結果はGranolaのみです。」と記載する。
- いずれかのステップが失敗した場合、可能な場合は残りのステップで続行する。1つの失敗で全体の実行を中止しない。
重複排除(重要 — 重複タスクを防止)
ミーティングレベルの重複排除
- 最初のステップ(処理前):
{user.workspace}/state/processed-meetings-YYYY-MM-DD.jsonを読む(存在する場合 — GranolaミーティングIDの配列) - すでにそのリストにあるIDのミーティングはスキップする。再処理しない。
- 各ミーティングを処理した直後(次のミーティングに移動する前)に、そのGranolaミーティングIDをファイルに追加する。最後まで待たない。他のcronとの競合を防ぐために、各ミーティングの後に書き込む。
- このファイルは、「このミーティングは今日すでに処理されましたか?」に対する唯一の情報源です。
注: タイトルは、同じ名前を共有する定期的なミーティングでは脆弱です。常にGranolaミーティングIDで重複排除してください。
タスクレベルの重複排除
- タスクを作成する前に、オープンタスクと最近完了したタスクの両方をチェックして、ほぼ重複がないか確認します:
- オープンタスクを取得:
source {user.workspace}/.env && todoist-cli list - 今日完了したタスクを取得:Todoist Sync API
completed/get_allをsince=<今日 00:00 UTC>で使用するか、サポートされている場合はsource {user.workspace}/.env && todoist-cli list --filter "completed today"を使用する
- 同じ人物 + 同じアクション意図 = 重複(例:「MorganeにHankについてテキスト」と「Hankの電話の後にMorgane (Braintrust) にテキスト」)
- 正規化:小文字化、括弧内を削除、空白を圧縮
- 重複がオープンまたは完了のいずれかに存在する場合 → スキップ、作成しない
- オープンタスクを取得:
- 出力でスキップされた重複を報告する:「⏭️ スキップ(既に存在):[タスク]」
- 完了したタスクをチェックする理由:ユーザーは、本日早くにポストミーティングcronによって作成されたタスクをすでに完了している可能性があります。それを再作成するのは間違いです。作業は完了しています。
両方のレイヤーが重要な理由
ポストミーティングcronはミーティングごとに起動します。日次の終業時cronはすべてのミーティングを処理します。ミーティングレベルの重複排除がないと、同じミーティングが2回処理されます。タスクレベルの重複排除がないと、ミーティングが再処理された場合(例:ファイルの書き込みに失敗した)、個々のタスクが重複することはありません。
重複排除は交渉不可
ミーティングが processed-meetings-YYYY-MM-DD.json に表示される場合、いかなる状況でも再度処理しないでください。ポストミーティングcronが「何かを見逃したかもしれない」と思ってもです。ポストミーティングcronはすでに処理しています。問題があった場合、ユーザーが手動で再実行を依頼します。
出力
- 作成されたタスクまたは下書き → 簡単な要約付きでタスクをリスト
- 完了したタスク(ミーティングで完了) → ✅ 付きでリスト
- 処理された特定のミーティングを常に名前で示す(例:「Fyxer電話、Braintrustウィークリー、HGPスタッフから」)— 「今日のミーティングから」とは決して言わない
- ミーティングがない、またはアクションアイテムがない場合 → NO_REPLY
Grainとのクロスチェック(アクティブ — トランスクリプトレベルの検証)
Grain MCP はフルトランスクリプトアクセスで利用可能です。Granolaからアクションアイテムを抽出した後:
- Grainでミーティングを見つける:
mcporter call grain.list_attended_meetings --args '{}'注:Grainのスキーマはstart_date/end_dateフィルターをサポートしていません。空の引数で呼び出し、start_datetimeで手動で結果をフィルタリングして、今日の日付範囲に一致させます。 - トランスクリプトを取得する:`mcporter call grain.fetch_me````md …(切り詰められた部分は元のまま保持)
[truncated for translation] 以降は、元のMarkdownの続きを日本語に翻訳して埋めてください。切り詰められた部分は、元の英語のままで構いません。