FACTUAL ACTIVITY RECORD · 実際の作業をもとにした活動記録
AIタレント編集部の日次Runnerを作る
外部情報の取得とAI編集を分離し、検証済みの下書きだけを受け渡す
目的
日次のニュース収集から編集下書きまでを自動化するには、外部通信や認証情報、database操作を扱う信頼された処理と、記事を編集するAIの処理を分ける必要があった。AIが取得元や保存先を自由に操作できる構成では、入力の安全性と公開権限の境界を保てない。
親Runnerが安全に取得・整形したNewsPacketを固定した編集Taskへ渡し、出力を検証したうえで下書きとしてだけ保存する流れを作ることを目指した。承認と公開は自動化の外に残し、失敗時も同じ入力から再開できるようにする。
実装
日次実行入口に親Runnerを実装した。保留中の送信を先に再試行し、同日の重複実行を確認してから、認証、利用許可された情報源の読込み、NewsPacket作成、AI編集、出力検証、下書き送信を順に進める。
- 情報源はHTTPSだけを許可し、localhost、private、loopback、link-local、multicast、reserved addressを拒否する。DNS解決とredirectの各段階で宛先を再確認する。
- 取得時間、redirect回数、byte数、item数に上限を設け、feed内のHTML、script、style、control characterを除去する。
- 記事全文は保存せず、見出し、URL、短い抜粋、公開日時だけをNewsPacketへ収め、packetのSHA-256を記録する。
task executorは、毎回新しい会話を作らず固定したroot Taskを再開する。AIへ渡すのはpacketと構造化出力のpathだけとし、Runner本体、database、Web、MCP、network、credentialへのアクセスを持たせない。子processの環境変数を絞り、timeout時はprocess group全体を終了する。
workflow coordinatorでは、処理前後でNewsPacketが変わっていないこと、packetと出力が通常fileでsymbolic linkではないこと、JSON schema、Task識別子、10人分の参加、全員が同じ入力hashをreviewしたこと、参照した情報源がpacket内に存在することを検証する。条件を満たさない出力は送信しない。
- Runner用accountはbindingとrow-level securityで、許可された情報源の読込みと下書き送信だけに制限する。編集、承認、公開はできない。
- 送信に失敗した下書きはpacketとdraftのhashを保った
upload_pendingとして残し、次回は古い保留分から送信だけを再試行する。 - 認証fileとstate fileを0600で管理し、process lock、quarantine、日付単位のrun keyとdatabase側の一意制約で重複実行を防ぐ。
launchdから毎日10時に起動し、sleepからの復帰時にも当日分を補完できる設定とした。同じ日付の完了済みrunは再処理せず、途中状態は記録された段階から安全に扱う。
親RunnerはAI出力をそのまま送信せず、regular file、size、read中の変更、schema、hashを一つのartifact boundaryで検証した。
図を描画しています…
確認したこと
確認結果
TypeScript型検査、71件のtest、production buildを含むcheckが成功した。
URL安全性、feed整形、stateとfile権限、同日冪等性、hash検証、timeout、下書き限定権限を含むtestが通った。
変更範囲とsecret混入を確認し、local認証fileとbuild生成物が成果物へ含まれないことを確認した。
最初のend-to-end実行は、MCPを無効化する起動設定が受理されずAI processの開始地点で停止した。下書きの送信、承認、公開は行われていない。
cutoff時点で親Runnerの初期実装と静的検証は対象へ反映されていたが、実運用の一巡は完了していなかった。起動設定の修正と再実行は次の独立した作業範囲である。
完了とした根拠
安全な情報取得、固定Taskへの受け渡し、出力検証、下書き限定送信、再試行と冪等性を備えた初期Runnerが対象へ反映され、型検査、71件のtest、buildまで通ったことを初期実装の完了基準とした。end-to-endの完了は基準に含めず、cutoff時点の起動failureを未解消事項として残した。