Claude の作業区間を n8n の work_log へ送る「n8n へ送る」タブを追加 #2
@@ -0,0 +1,167 @@
|
||||
# chktime から n8n の work_log へ作業区間を送る — 設計
|
||||
|
||||
日付: 2026-10-12
|
||||
対象: chktime (このリポジトリ) と n8n (https://n8n.yfox.jp) の work-tracker
|
||||
|
||||
## 目的
|
||||
|
||||
Claude Code での作業を、手で「作業開始・終了」を記録しなくても n8n の `work_log` に入るようにする。
|
||||
入った記録は、手で記録したものと同じく、日報・月報・ガント・ダッシュボード・Redmine 工数同期
|
||||
(work-tracker--redmine-sync) で使われる。
|
||||
|
||||
### 成功の条件
|
||||
|
||||
- chktime の画面で期間を選ぶと、Claude のセッションから作った「作業区間」が一覧で出る。
|
||||
- 区間ごとにタスク名 (Redmine のチケットを選べる) を決め、選んだものだけを `work_log` に送れる。
|
||||
- 同じ区間を二度送っても、`work_log` に二重に入らない。
|
||||
- すでにある記録 (手で記録したもの・他の区間) と時間が重なる区間は、画面で分かり、最初は送らない状態になっている。
|
||||
- chktime に渡す権限は「work_log への取り込み」だけ。n8n の API キーは chktime に持たせない。
|
||||
|
||||
### 前提と決めたこと
|
||||
|
||||
| 項目 | 決定 |
|
||||
|---|---|
|
||||
| 目的 | 記録の手間を減らす |
|
||||
| 時間の数え方 | 連続した区間ごと (空き 30 分以上で切る) |
|
||||
| タスク名 | 送る前に chktime の画面で決める |
|
||||
| 重なり | 画面で知らせ、最初は送らない。送るかは利用者が決める |
|
||||
| 送り方 | 案 A: n8n に受け口のワークフローを作り、chktime から呼ぶ |
|
||||
|
||||
## 1. 区間の作り方 (chktime)
|
||||
|
||||
材料は chktime の既存の「ターン」(人間の発言 1 回と、それに対する応答一式)。
|
||||
|
||||
- 同じセッションの中で、前のターンの応答完了から次の発言までの空きが **30 分未満** ならつなぐ。
|
||||
30 分以上なら区間を切る。
|
||||
- 開始 = 区間の最初の発言の時刻、終了 = 区間の最後のターンの応答完了の時刻。
|
||||
- **5 分未満** の区間は一覧から外す。
|
||||
- ターンの起点は既存の規則どおり (人間の発言だけ。サブエージェント・再開時のメタ行は起点にしない)。
|
||||
- `date` は区間の開始時刻のローカル日付 (日本時間)。日をまたぐ区間も開始日の記録。
|
||||
- 30 分と 5 分は設定 (`n8n.json` の `gapMinutes` / `minMinutes`) で変えられる。画面から変更できる。
|
||||
- セッションの最後の区間で、最後のターンがまだ応答中 (ログの最終更新から `gapMinutes` 経っていない、
|
||||
または最後のターンに応答完了が無い) のものは「進行中」とし、送れない。
|
||||
- `source` = `chktime:<セッションID>:<区間開始の epoch ミリ秒>`。同じログからは毎回同じ値になる。
|
||||
|
||||
区間の計算は、HTTP やファイル読み込みから切り離した純粋な関数 (ターンの列と設定値 → 区間の列) にする。
|
||||
|
||||
## 2. n8n 側
|
||||
|
||||
### データテーブル
|
||||
|
||||
- `work_log` に `source` (string) の列を足す。chktime から入れた行だけ値が入り、手で記録した行は空。
|
||||
既存のワークフローはこの列を書かないので影響しない。
|
||||
- `work_log_deleted` にも `source` を足し、work-tracker--delete の `Backup Row` で一緒にコピーする。
|
||||
|
||||
### ワークフロー `work-tracker--import`
|
||||
|
||||
両方の Webhook に Header Auth の認証情報を付ける (ヘッダー `X-WT-Token`)。違えば n8n が 403 を返す。
|
||||
|
||||
**`GET /webhook/wt-import-rows?from=YYYY-MM-DD&to=YYYY-MM-DD`**
|
||||
|
||||
- `from` / `to` を確かめる (形式、`from <= to`、最大 62 日)。不正なら `{ok:false, error}`。
|
||||
- `work_log` から `date` が `from の前日` 〜 `to` の行を返す
|
||||
(前日を含めるのは、日をまたぐ記録との重なりを見るため)。
|
||||
- 返す値:
|
||||
`{ok:true, rows:[{id, date, start_time, end_time, task, status, source}], deletedSources:[...]}`
|
||||
`deletedSources` は同じ期間の `work_log_deleted` の `source` (空でないもの)。
|
||||
|
||||
**`POST /webhook/wt-import`**
|
||||
|
||||
- 本文: `{rows:[{source, date, start_time, end_time, task, memo}]}`、1 回に最大 200 件。
|
||||
- 1 行ずつ確かめる:
|
||||
- `source` が `chktime:` で始まる (500 文字以内)
|
||||
- `date` が `YYYY-MM-DD`、`start_time` / `end_time` が ISO 8601 で、終了 > 開始、長さ 24 時間以内
|
||||
- `task` が空でない (500 文字以内)、`memo` は 2000 文字以内
|
||||
- `work_log` に同じ `source` がある行はスキップ。
|
||||
- 新しい行は `status: "done"`、`duration_min` = 終了 − 開始 (分、四捨五入、丸めなし) で追加。
|
||||
- 返す値: `{ok, inserted:[{source, id}], skipped:[{source, reason}], errors:[{source, error}]}`。
|
||||
`ok` は errors が 0 件のとき true。
|
||||
|
||||
### 認証情報
|
||||
|
||||
合言葉は利用者が決める。利用者が n8n の画面で Header Auth の認証情報 (例: 名前 `wt-import token`、
|
||||
Name `X-WT-Token`) を作り、chktime の設定画面にも同じ値を入れる。Claude は合言葉を作らず、入力もしない。
|
||||
認証情報の id は一覧 (中身を含まない) から取ってワークフローに設定する。
|
||||
|
||||
## 3. chktime 側
|
||||
|
||||
### 設定
|
||||
|
||||
- `n8n.json` (git 管理外、`.gitignore` に追加。場所は `--n8n-config` で変更可):
|
||||
`{"url": "https://n8n.yfox.jp", "token": "...", "verifySsl": false, "gapMinutes": 30, "minMinutes": 5}`
|
||||
- `GET /api/n8n/config` は `token` の中身を返さず、`hasToken` だけ返す。`POST /api/n8n/config` で保存。
|
||||
Redmine 設定 (`RedmineHolder`) と同じ作り。
|
||||
- `verifySsl` の既定は false (LAN からは n8n.yfox.jp の証明書名が一致しないため)。
|
||||
|
||||
### サーバーの API (chktime 内)
|
||||
|
||||
| ルート | 内容 |
|
||||
|---|---|
|
||||
| `GET/POST /api/n8n/config` | 設定の取得 (合言葉は返さない) / 保存 |
|
||||
| `GET /api/n8n/blocks?from=&to=&project=` | 期間の区間を計算し、n8n の `wt-import-rows` の結果で「送信済み / 削除済み / 重なり」を付けて返す。n8n に届かなくても区間は返し、`n8nError` を付ける |
|
||||
| `POST /api/n8n/send` | `{items:[{source, task, memo}]}` を受け、時刻はサーバーが `source` から区間を計算し直して n8n の `wt-import` に送る。結果をそのまま返す |
|
||||
| `GET /api/redmine/issues?project_id=&q=` | 既存の Redmine 連携で未完了チケットを検索 (チケット選択用) |
|
||||
|
||||
重なりの判定: 区間 [開始, 終了) と、`work_log` の行 (進行中は終了 = 今) または一覧の他の区間が
|
||||
1 秒でも重なれば「重なりあり」。同じ `source` の行 (送信済みの自分) は除く。
|
||||
|
||||
### 画面
|
||||
|
||||
- 右ペインのタブに「n8n へ送る」を足す。左で選んでいるプロジェクト (または すべて) が対象。
|
||||
- 期間: 初期値は直近 7 日。日付入力で指定もできる。
|
||||
- 一覧の 1 行 = 1 区間。列: 送る (チェック) / 日付 / 開始〜終了 / 時間 / プロジェクト / タスク名 (編集可) / チケット (選ぶ) / 状態。
|
||||
- タスク名の初期値は `[作業フォルダ名] セッションのタイトル`。チケットを選ぶと
|
||||
`[Redmine のプロジェクト名] #番号 題名` にする (rich-start と同じ形。工数同期とガントの実績に載る)。
|
||||
- タスク名・チケットは、同じセッションの他の区間にも入れる (切り替え可)。セッションごとに
|
||||
ブラウザの localStorage に覚える (読み書きは try/catch で囲み、使えなくても動く)。
|
||||
- 状態の印: 送信済み / 削除済み / 重なりあり (カーソルで相手を表示) / 進行中。
|
||||
- 送るチェックの初期値: 問題の無い区間だけ on。送信済み・削除済み・重なりあり・進行中は off
|
||||
(送信済みと進行中はチェックできない)。
|
||||
- 「選んだ区間を送る」で送信し、追加・スキップ・エラーの件数と内訳を表示して一覧を読み込み直す。
|
||||
- 設定 (URL・合言葉・証明書の検証・30 分・5 分) は Redmine 設定と同じ形のダイアログ。
|
||||
|
||||
## 4. エラーの扱い
|
||||
|
||||
- n8n に届かない / 403 / 5xx: 一覧は出し、上部に原因を表示して送信ボタンを無効にする。送信時の失敗は n8n の応答をそのまま表示。
|
||||
- 一部の行だけ失敗: 行ごとの結果を表示。`source` で二重登録を防ぐので、再送で失敗分だけ入る。
|
||||
- 同時に 2 回送った場合: n8n 側の「確認 → 追加」は一括の処理ではないので、二重に入る可能性がある。
|
||||
使用者は 1 人なので許容し、README に書く。
|
||||
- 合言葉はログにも画面にも出さない。`n8n.json` は git に入れない。
|
||||
|
||||
## 5. テスト
|
||||
|
||||
### chktime
|
||||
|
||||
- 区間の計算を標準ライブラリの `unittest` で確かめる (`tests/test_blocks.py`)。
|
||||
入力は手で組んだターンの列、またはスクラッチパッドに作ったテスト用 jsonl (実ログは書き換えない)。
|
||||
- 空き 29 分はつながり、30 分で切れる
|
||||
- 5 分未満は除外、5 分ちょうどは残る
|
||||
- 進行中の区間
|
||||
- サブエージェントの行を起点にしない
|
||||
- 日をまたぐ区間の `date` は開始日
|
||||
- `source` が同じ入力で毎回同じ
|
||||
- 重なりの判定 (接しているだけは重ならない、1 秒重なれば重なる、自分の `source` は除く)
|
||||
- サーバーは検証用に `python chktime.py --port 8799 --no-browser` で起動する (常用の 8787 には触れない)。
|
||||
|
||||
### n8n
|
||||
|
||||
- 2000-01-01 付けのダミー (`source: chktime:test:...`) で: 追加される / 再送でスキップ / 合言葉違いで 403 /
|
||||
不正値でエラー / `wt-import-rows` に出る / 削除すると `deletedSources` に出る。
|
||||
- 終わったらダミーを `work_log` と `work_log_deleted` から直接削除する (削除 Webhook は使わない)。
|
||||
|
||||
### 全体
|
||||
|
||||
- 8799 の chktime から、利用者が選んだ実際の区間を 1 件送り、ダッシュボードと日報に出ることを確かめる。
|
||||
|
||||
## 6. 文書
|
||||
|
||||
- `CLAUDE.md`: 「外部通信は Redmine 連携だけ」を「Redmine 連携と n8n への送信だけ」に。API の表に n8n の系統を足す。
|
||||
- `README.md`: 「n8n へ送る」の使い方、設定、同時送信の注意。
|
||||
- `.gitignore`: `n8n.json`。
|
||||
- 保管庫: chktime と n8n のノートに追記。
|
||||
|
||||
## 対象外
|
||||
|
||||
- 自動で定期的に送ること (送るのは利用者が画面で選んだときだけ)。
|
||||
- 送信後に chktime から `work_log` の行を編集・削除すること (編集・削除は既存の work-tracker の画面で行う)。
|
||||
- 他の Webhook への認証の追加 (今回の 2 本だけ。広げるのは別の作業)。
|
||||
Reference in New Issue
Block a user