thiguchi125-debug

task-add

"Todoist登録の入口。期限付き登録の前にGoogle Calendarと突合(✅可能/⚠️タイト/🚫無理)→作業ブロック案→承認分だけtd.py add+カレンダー登録。突合を飛ばすとhookがdeny。他スキルの期限付き登録も本手順。Triggers: タスク登録して/Todoistに入れて/タスクにしといて。NOT: 逆算→gyakusan、棚卸し→task-audit"

thiguchi125-debug 0 Updated 1mo ago

Resources

7
GitHub

Install

npx skillscat add thiguchi125-debug/claude-config/task-add

Install via the SkillsCat registry.

SKILL.md

対象外(2026-09-05〜): 市役所対応の市民要望案件(相談者がいて担当課へ照会→回答→報告)は Todoist でなく市民要望管理台帳(~/.claude/scripts/yobo/yobo.py add)へ。本スキルは草川自身の議会・政策・イベント・選挙タスクだけ扱う。迷ったら判定1問「終わったら誰かに報告するか?」→はい=台帳(本スキル対象外)/いいえ=Todoist。親PJは8本固定(Inbox/🏛議員活動/📝議会(会期別)/🎪地域・イベント/🗳選挙2026/📣発信/🏡家族・プライベート/🗂構想バックログ)=空の案件箱を新設しない。詳細=OPERATIONS.md【B】例外節

task-add — カレンダー突合つきタスク登録

目的: 「実施できない日を期限に設定してしまい、期限切れタスクが積み上がる」を構造的に潰す。提案止まりが既定。承認なしにTodoistへ書き込まない。

設計の正本は同ディレクトリの DESIGN.md。本ファイルと矛盾したら DESIGN.md が優先。

Step 1: タスクの整理

登録候補を「内容・登録先プロジェクト案・期限案」の3点に整理する。

  • 期限案の既定は今日+3日([[feedback_task_deadline_3days]]・あくまで推奨案であって確定値ではない)
  • python3 ~/.claude/scripts/todoist/td.py projects で実在するプロジェクト名を確認してから --project を決める(「📋 政策・一般質問」は実在しない)
  • 相手のボール待ち=@結果待ち、やる方向だが要検討=@保留
  • 期限を付けない登録(@アイデア等)はここで終了。Step 2以降は不要で、hookも素通しする

Step 2: 想定所要の見積り

タスク内容から下表で推定する。所要は時間の合計ではなく「30分コマ」の数で数える(1セッション=1時間=2コマ)。30分粒度にしているのは、電話1本のような30分タスクを1時間単位で切り捨てると「30分空いている日」が0と数えられ、実施可能なのに🚫になるため。

種別 判定語 想定所要 必要コマ 最低所要日数
連絡・電話・アポ取り 電話/連絡/アポ/確認する 15分 1コマ 1日
メール・DM返信 返信/メール/返事 30分 1コマ 1日
挨拶原稿 挨拶/祝辞 30分 1コマ 1日
資料読み込み 読む/目を通す/資料確認 1h 2コマ 1日
ブログ・SNS ブログ/投稿/発信 1h 2コマ 1日
訪問・現地確認 訪問/現地/視察 1h 2コマ 1日
議案分析・調査 分析/調査/リサーチ 3h 6コマ 2日
一般質問・議案質疑原稿 一般質問/質疑/通告 4h 8コマ 2日
スライド・報告会資料 スライド/資料作成/報告会 4h 8コマ 2日
印刷物制作・入稿 チラシ/ポスター/リーフレット/入稿 8h 16コマ 4日
  • 表に該当が無ければ内容から推定し、根拠を1行添える
  • 推定値は提案時に必ず表示する。草川が「これ30分」と訂正したら再計算する
  • 最低所要日数 = ceil(必要コマ ÷ 4)(1日に同一タスクへ割けるのは最大2セッション=4コマのため)

Step 3: カレンダー取得

mcp__claude_ai_Google_Calendar__list_events を1回だけ呼ぶ。

  • calendarId = kusakawa.taku@gmail.com(kusagawa は誤り)

  • 期間 = 今日 〜 期限候補日+14日(+14日は代替期限案を出すための余白)

  • 複数タスクをまとめて登録する場合も、最も遠い期限候補日+14日までを1回で取る。タスクごとに呼ばない

  • 草川のカレンダーは予定が密で、2週間分でも応答が7万字を超えてそのままではコンテキストに載らない。載らなかった場合はツール結果が自動でファイルに保存されるので、そのパスをそのまま Step 4 のスクリプトに渡す(中身を読み下す必要はない)。インラインで返ってきた場合はスクラッチパッドにJSONとして書き出してからパスを渡す

  • nextPageToken を必ず確認する(2026-08-06 実運用で発覚)。 pageSize の上限は250件で、草川のカレンダーは約4週間で250件に達する。トークンが返っていたらページが切れており、取れなかった予定が「空き時間」に見える。そのまま割り付けると実在の予定の上に作業ブロックを重ねる。対処は「窓を4週間以内に狭めて取り直す」(pageToken で継ぎ足すと2ページ目がコンテキストに載ってしまい、ファイル1本にまとまらない)

  • 取得結果のヘッダに nextPageToken が無ければ完全。あれば窓を狭めて取り直す

gyakusan から呼ばれた場合など、呼び出し元が既にカレンダーを取得済みならそれを受け取り、再取得しない。

Step 4: 空き枠の算出と判定(スクリプトで行う)

区間のマージ・隙間の足切り・1日上限を手計算すると必ず間違えるので、同ディレクトリの sessions.py を使う。手で数えない。

python3 ~/.claude/skills/task-add/sessions.py <events.json> \
  --from <今日 YYYY-MM-DD> --due <期限候補日 YYYY-MM-DD> --need <必要コマ数> \
  [--now HH:MM] --plan --plan-json <plan_1.json> --plan-title "<タスク内容>"

出力に日別コマ数・判定・着手推奨日・代替案がそのまま出る。タスクごとに --due と --need を変えて呼ぶ(カレンダーの取得は1回のまま)。

--plan は既定で必ず付ける。 これが「いつやるか」を実際の時間帯に割り付けた作業ブロック案で、Step 10 でカレンダーに書き戻す材料になる。付け忘れると従来通り「期限日という終日の点」しか残らず、スケジュールに時間が反映されない。--plan-json の出力先はスクラッチパッド配下にタスクごと別名で置く。

ブロック配置の規則(判定コマ数の計算とは別レイヤ・plan_blocks()):

  • 1ブロック = 最大60分(1セッション)。1つの空き区間には1ブロックしか置かず、日をまたいで散らす
  • 1日あたり ✅可能なら2コマ(1時間)まで/⚠️・🚫なら4コマまで。余裕がある案件を1日に詰め込まない
  • 昼 12:00–13:00 には置かない(配置専用の規則。コマ数の算出では昼を引いていないので判定は変わらない)
  • 15:00–18:30 は挨拶回り優先枠なので置かない([[feedback_greeting_rounds_time_reserve]]・2026-08-07指示)。例外は草川が「今日はこの時間に作業を入れられる」と明示した日だけで、そのとき reserve_greeting=False で開ける。この枠を空けると実働容量が約1/4減り、役所への照会に使えるのは実質「平日午前」と「13:15–14:45」だけになる
  • 期限までに置き切れない分は ⚠️ 未割付 Nコマ として出る。これが出たら判定は 🚫 側なので代替期限案とセットで出す

スクリプトが実装している規則:

  1. 稼働帯 9:00–21:00(全曜日・土日祝も同じ)。当日は --now 以降
  2. 予定の重なりはマージする。30分未満の隙間は使えないものとして捨てる
  3. その日のコマ数 = min(4, 使える空きの30分単位)。1日に同一タスクへ割けるのは最大2セッション=4コマ
  4. 終日予定は原則ブロックしない。 草川のカレンダーでは終日予定の大半が目印(グラウンドゴルフ・憩いの場・地域行事等)で、実際の拘束は時間指定予定として入っている。一律に作業不可日にするとほぼ全日が0コマになる。「議会/視察/出張/研修/入院/旅行/終日」を含む終日予定だけを**作業不可日(0コマ)**とする
  5. 【参考】 で始まる予定は完全に無視する(他人の行事等の参考情報であり草川を拘束しない)
  6. 移動時間は考慮しない

Step 5: 3値判定(スクリプト出力の読み方)

判定 条件 提案に書くこと
✅ 可能 確保可能 ≧ 必要コマ × 1.5 着手推奨日を併記
⚠️ タイト 必要 ≦ 確保可能 < 必要 × 1.5 逼迫の理由(終日拘束日・予定過密日)と着手推奨日を併記
🚫 無理 確保可能 < 必要コマ、または残り日数 < 最低所要日数 代替期限日を2案(最短で足りる日/余裕×1.5を満たす日)

残り日数が最低所要日数を下回る場合は、空き状況を見るまでもなく 🚫 になる(例: 入稿16コマ=最低4日を3日後の期限で登録しようとした場合)。

着手推奨日 = 「その日から期限日までに確保できるコマ数が必要数以上になる」日のうち最も遅い日。これ以上先延ばすと間に合わなくなる境界日。

Step 6: 提案

python3 ~/.claude/scripts/todoist/td.py week で同期間に期限が来る既存タスクの件数を取り、ヘッダに併記する(所要を推定して空き時間から差し引くことはしない)。

期限だけでなく作業ブロック案も同じ画面に出す。 確認は1回に束ねる([[feedback_ask_bundling_and_upfront_reflection]])ので、「登録していいか」と「この時間帯でいいか」を別々に聞かない。

📋 タスク登録の確認(カレンダー突合済み 8/3〜8/12・同期間の既存タスク7件)

1. 川合町報告会のスライド作成
   PJ: 🏛 議員活動 / 期限案: 8/12(火) / 想定: 4h(8コマ・最低2日)
   確保可能 19コマ → ✅ 可能(着手推奨 8/10)
   🗓 作業ブロック案: 8/5(火)14:30-15:30 / 8/6(水)9:00-10:00 / 8/8(金)9:00-10:00 / 8/9(土)9:00-10:00

2. ◯◯さんへ回答メール
   PJ: 🏛 議員活動 / 期限案: 8/6(木) / 想定: 30分(1コマ)
   確保可能 1コマ → ⚠️ タイト(8/4は視察で終日・8/5も予定過密)
   🗓 作業ブロック案: 8/6(木)9:00-9:30

3. リーフレット入稿
   PJ: 🗳 選挙2026 / 期限案: 8/5(水) / 想定: 8h(16コマ・最低4日)
   🚫 残り3日 < 最低4日(確保9コマ < 必要16コマ)
      代替案 a) 8/8(土) 累計19コマ  b) 8/10(月) 累計27コマ ●推奨
      ※ブロック案は期限日を決めてから出し直します

→ 「1と2」「3はaで」「全部」「見送り」等でお答えください
→ 時間帯を変えたいものは「1は午後で」「2は要らない」等もどうぞ
  • ブロック案はタスクごとに出す。🚫のタスクは期限日が動くので、代替案を選んでもらってから出し直す
  • 「ブロックは要らない・期限だけでいい」と言われたらカレンダー登録はスキップし、Step 9 だけ実行する

Step 7: 承認取得

草川の返答を待つ。返答が無いもの・見送られたものは登録しない。 既定値で勝手に確定登録しない([[feedback_ask_destination_and_deadline_before_register]])。

Step 8: 突合記録の書込

承認された分だけを ~/.claude/skills/task-add/_verified.json に書く。この記録が無いと次のStep 9が hook に deny される。

python3 -c "
import json, os
from datetime import datetime
p = os.path.expanduser('~/.claude/skills/task-add/_verified.json')
json.dump({
  'generated_at': datetime.now().isoformat(timespec='seconds'),
  'ttl_minutes': 30,
  'calendar_ok': True,
  'approved': [
    {'content': '<td.py add に渡すのと同じ文字列>', 'due': 'YYYY-MM-DD',
     'slots': <必要コマ数>, 'verdict': 'ok'},
  ],
}, open(p, 'w'), ensure_ascii=False)
"
  • content は td.py add に渡す文字列と同じものを書く(hookは絵文字・空白・記号を無視して照合するので多少の揺れは吸収されるが、揃えておく)
  • due は --due に渡す YYYY-MM-DD と完全一致させる
  • verdict は ok / tight / unverified
  • TTLは30分。承認から時間が空いたら書き直す

Step 9: 登録

承認分のみ td.py add を実行する。

python3 ~/.claude/scripts/todoist/td.py add "<内容>" --due YYYY-MM-DD --project "<実在PJ名>" [--priority 1-4] [--label 結果待ち] [--desc "<判定根拠1行>"]

--desc に「想定4h(8コマ)・確保19コマ・着手推奨8/10」のような判定根拠を1行入れておくと、後で見返したときに期限の由来が分かる。

登録後、_verified.json は放置してよい(30分で失効する)。

Step 10: 作業ブロックをカレンダーへ登録

Todoistの期限は「いつまでに」しか表さない。「いつやるか」はカレンダー側に置く。 承認された作業ブロックを mcp__claude_ai_Google_Calendar__create_event で1ブロック=1予定として作成する。

calendarId  : kusakawa.taku@gmail.com
summary     : 【作業】<タスク内容>
startTime   : 2026-08-06T09:00:00+09:00   (plan.json の date + start)
endTime     : 2026-08-06T10:00:00+09:00   (plan.json の date + end)
timeZone    : Asia/Tokyo
description : task-add 自動生成/Todoist期限 2026-08-12/想定4h(8コマ)の1/4
colorId     : 8   (グレー系。既存の実予定と見分けるため全ブロック共通で固定)
availability: AVAILABILITY_BUSY
  • タイトルは必ず 【作業】 で始める。 実際の予定(会議・訪問)と区別でき、後から一括削除もできる
  • eventType: FOCUS_TIME は使わない。フォーカスタイムは設定次第で招待を自動辞退するため、副作用が読めない
  • ブロックは時間指定予定として入るので、次回以降の sessions.py が自動的にこれを埋まった時間として扱う。二重に予定を入れない自己修復が効く
  • 作成後、実際に入った日時をチャットに1行でまとめて報告する

ブロックの後始末

  • タスクを前倒しで終えた/不要になった場合、残った 【作業】 予定は自動では消えない。td.py done はカレンダーを触らない
  • 「作業ブロック消して」と言われたら search_events で 【作業】 を引き、対象を delete_event する
  • 期限を動かした場合も同様に、古いブロックを消してから貼り直す

一括モード(既存タスクへまとめて作業ブロックを入れる)

「今のTodoistのタスクを全部スケジュールして」のように既存タスク群を対象にするときは、Step 1〜9(新規登録)を飛ばす。Todoistには何も書かないので _verified.json も hook も関係しない。

手順は「案を作る → 見せる → 直す → 登録」の4段。登録は最後

⚠️ 範囲の合意は登録の許可ではない。「今週分だけ」のようなスコープの返事をもらっただけで書き込んではいけない。ブロック案そのものを全件見せ、少なくとも1回は調整のやり取りを経てから登録する(2026-08-06 草川指摘「事前に提案して調整を試みてから入力する手法に変えてください」)。

段 やること 出力
① 案を作る estimate.py → bulk_plan.py。カレンダーには一切書かない bulk_plan.json
② 見せる 日別に全ブロックを提示+除外・置けなかった分も必ず提示。自分が自信のない分類を名指しで挙げる チャット
③ 直す 迷った点を1件1問の選択式で聞き、回答を tasks.json に反映 → ①へ戻る。草川が「これでいい」と言うまで登録しない 修正版
④ 登録 承認された分だけ Step 10 で create_event カレンダー
# ① タスク一覧をJSON化(td.py を import して projects_map / all_tasks を使う)
# ② 想定所要を機械的に付与
python3 ~/.claude/skills/task-add/estimate.py tasks.json
# ③ 現実性フィルタ込みで累積割り付け(提案止まり)
python3 ~/.claude/skills/task-add/bulk_plan.py <events.json> tasks.json <今日> <HH:MM> <窓の終端>

現実性フィルタ(task_windows.py)

空き時間があるかより先に「相手がいる時間か」「自分の手番か」を見る。 2026-08-06 の初回実行では、空いているという理由だけで日曜に市役所照会を8件・18時以降に7件置き、「連絡待ち」のタスクにまでブロックを作った。カレンダーは埋まったが1件も実行できない。

種別 判定語の例 置ける曜日・時間 理由
除外 @結果待ち @保留 ラベル/件名に「〜待ち」 置かない 自分の手番ではない
役所・関係機関 照会/担当課/県/警察/消防/教委/アポ/要望書 平日 9:00–17:00 窓口が開いていない
現地確認 現地/下見/視察/写真記録/点検 全曜日 9:00–18:00 暗いと状況が見えない
住民・関係者連絡 連絡/電話/返信/経過報告/◯◯さんへ/訪問 全曜日 9:00–20:00 夜遅く個人宅にかけない
机上作業 上記以外 全曜日 5:00–7:00 と 9:00–21:00 相手がいない

早朝5:00–7:00は机上作業だけ([[feedback_early_morning_desk_band]]・2026-08-07指示)。役所・連絡・現地は早朝に置かない=電話を早朝にかけない。Kind.band() が容量の数え方から分けているので、役所タスクの実施可能性が早朝で水増しされることはない。街頭活動6:30・あまね朝準備7:00がある日は自動的に短くなる(実測: 平日2〜3コマ/土日4コマ)。

配置側の規則(判定コマ数は変えない):

  • 前後の予定と15分のバッファ(BUFFER)。予定が終わった瞬間に次を始められない。結果として予定に挟まれた30分の隙間は使わない
  • 1日の総ブロック上限は平日4件・土日2件(CAP_WEEKDAY / CAP_WEEKEND)
  • 昼 12:00–13:00 は置かない

分類は正規表現なので必ず外れが出る。外れを草川に直してもらうのが②③の工程で、ここを飛ばすと同じ失敗を繰り返す。

③の聞き方=1件1問の選択式([[feedback_ask_one_by_one_choices]])

「以下の4点を直してください」と箇条書きで並べて自由記述の返信を求めない。 草川に文章を組み立てさせるのがコストになる(2026-08-06 指摘)。AskUserQuestion で1件1問・タップで答えられる形にする。

  • 1回につき最大4問。5件以上あるときは影響の大きい順に4問出し、残りは次のラウンドへ
  • 選択肢は推奨案を先頭に置き「(推奨)」を付ける
  • 典型的な設問=「この件の種別は役所/現地/連絡/机上のどれか」「所要は30分か1時間か」「分割せず1回で終わるか」
  • 迷いが無い項目は聞かない。自分で判断がつかないものだけを設問にする

既存の【作業】ブロックとの整合(2026-08-06 草川指摘)

再提案の前に、既にカレンダーへ入れた 【作業】 を必ず消してから空きを数える。 消さずに計算すると、自分が置いた仮ブロックを「埋まっている」と誤認する。初回はこれで今週の空きがゼロになり、提示した候補時刻が全部すでに埋まっている枠だった。

# 再提案の第一手:既存ブロックの棚卸し
#   list_events(fullText="【作業】") → 全件 delete_event → その後に list_events で取り直す
  • カレンダーの 【作業】 を消してもTodoistのタスクは消えない。 消えるのは「いつやるか」の枠だけで、「やること」は残る。草川に確認されたら必ずこう説明する(td.py は一切呼ばない)
  • 「作業」を含む実在の予定(例:「けんろう折込チラシ作業」「奉仕作業」)を巻き込まない。先頭が 【作業】 のものだけを対象にする
  • 1件の時刻を直すと他のブロックが押し出される。 累積割り付けなので、1件確定するたびに残り全部を再計算し、動いた分を差分として見せる。見せずに黙って動かすと、答えたはずの内容と結果がずれる

一括モードで必ず守ること

  • 期限切れタスクは割り付け対象外。 今日より前の期限には置く先が無い。一覧を出して草川の判断を仰ぐ(期限の付け替えは hook のゲート対象で、勝手に動かさない)
  • 入り切らない分を黙って捨てない。 「置けなかった N件」「除外 N件」を必ず一覧で出す。全部入ったように見せるのが最悪
  • 量を先に見せる。 生成ブロック数と日別件数を提示してから作る
  • 実績値(2026-08-06): アクティブ178件・期限あり164件で想定所要は合計415コマ=207.5時間。タスク量が容量を超えているというシグナル自体が成果物なので、詰め込んで隠さない

カレンダーが取れないとき

Google Calendar MCP が応答しない場合は突合を諦めて止まるのではなく、次のように進める。

  1. 提案に 「⚠️ カレンダー未確認」 と明示する(判定は出さない)
  2. 草川の承認を得る
  3. _verified.json を calendar_ok: false・各エントリの verdict: 'unverified' で書く
  4. 登録する(Step 10 の作業ブロックは作らない。空きが分からないまま予定を入れると実在の予定と衝突する。「カレンダーが復旧したらブロックを入れ直しますか」と1行添える)

hook は calendar_ok の値で分岐しないので、記録さえあれば通る。黙って未確認のまま登録しないことが要件。

📌 恒久ガードルール

  • 提案止まりが既定。承認なしのTodoist書込は禁止([[feedback_ask_destination_and_deadline_before_register]])
  • 期限案の「今日+3日」は推奨案であって確定値ではない([[feedback_task_deadline_3days]] は上記に上書きされている)
  • 想定所要は必ず提示する。 黙って見積もって黙って判定しない。訂正されたら再計算する
  • カレンダーIDは kusakawa.taku@gmail.com(kusagawa は誤り・CLAUDE.md正本)
  • td.py projects で実在PJ名を確認してから --project を指定する
  • 1日に同一タスクへ割けるのは最大2セッション(4コマ)。空きが8時間ある日でも1タスクには4コマしか計上しない
  • **空き枠の算出は必ず sessions.py に任せる。**区間のマージ・30分未満の足切り・1日上限を手計算すると間違える
  • **sessions.py は --plan 付きで呼ぶ。**期限日(終日の点)だけ登録して「いつやるか」をカレンダーに書き戻さないと、突合で空きを計算した意味が消える(2026-08-05 草川指摘「日付の終日で登録されているだけで時間を細かくスケジュールに反映できていない」)
  • **作業ブロックの時間帯も承認事項。**期限の承認とまとめて1回で聞き、承認された時間帯だけカレンダーに入れる
  • 範囲の合意を登録の許可と取り違えない。「今週分だけ」等のスコープ回答は入口の合意にすぎない。ブロック案を全件見せて調整を1回は回してから登録する(2026-08-06 草川指摘)
  • **空き時間があることを「やれる」と読み替えない。**役所は平日9-17時、現地確認は明るいうち、@結果待ち は自分の手番ではない。判定は task_windows.py
  • **作業ブロックのタイトルは 【作業】 始まり固定。**実予定と混ざると後始末ができなくなる
  • **カレンダー未確認のときは作業ブロックを作らない。**空きが分からないまま入れると実在の予定と衝突する
  • **終日予定を一律に作業不可日としない。**草川のカレンダーでは終日予定の大半が目印であり、一律ブロックするとほぼ全日が0コマになる(2026-08-03 実データで確認)
  • 既存タスクは件数のみ併記。所要を推定して空き時間から差し引かない(裏付けのない数字で判定を歪めない)
  • list_events は1回だけ。タスクごとに呼ばない
  • まず「記録で足りるか、タスク化が要るか」を振り分ける。方針・状況は記録に残すだけでタスクにしない
  • 単発で完結しないタスクは CLAUDE.md「タスク登録時のプロジェクト化判定」基準A〜Eでプロジェクト化要否を問いかける