プログラミング
Docket – エージェントによって書かれたコードのコミットごとの証拠記録
Docket – Per-commit evidence records for agent-written code (github.com)
要約
Docketは、AIコーディングエージェントが生成したコードのコミットごとに、その実装の過程を記録するツールです。エージェントが試したこと、検証したこと、レビューされなかった行などを追跡し、コードの変更点(hunk)ごとに証拠記録を作成します。これにより、コードレビューの際に、どこに注意を払うべきか(証拠が少ない箇所)を特定しやすくなります。インストールは簡単で、Gitリポジトリにフックを仕掛けることで機能します。
全文翻訳
エージェントによって書かれたコードのコミットごとの証拠記録。
コーディングエージェントは、誰かが検証できるよりも速くコードを生成します。
レビュー担当者は、実装の過程なしに、完成した差分を受け取ります。最初に何を試したか、何を検証したか、どの行が誰も見ていないかという記録はありません。
ハーネスはすでにそのジャーニーを出力しますが、コミット時にそれを破棄します。Docketはそれをキャプチャし、差分と照合し、コミットごとの証拠記録を生成します。これにより、レビューの注意は証拠がない場所に集中します。
$ docket show HEAD
docket 7a9da95a2a748c2fb99706f48f2ddf64760ffab2
record sha256:046c5278e93cb516e3ba72400fd1a69648c85b93833d31d57648e9ed8e535ebf
trust local_claimed (signed on local)
verified digest and signature check out (ed25519:f889a26cbc34c95e)
1 hunks in 1 files, 4 added lines
100% of added lines attributed to a recorded edit
mean evidence density 0.77
src/auth.js:3-6 (4 lines)
covered density 0.77
origin claude-code/main via Edit (reported by the harness)
claude-opus-5
task Fix session fixation on login intent
The raw UUID is reused across logins, so minting a prefixed id instead.
attempt Stamping a creation time on the session so expiry can be checked. [superseded]
vitest failed after this change: npx vitest run
evidence coverage: 4 of 4 lines executed (coverage/coverage-final.json)
evidence test_execution: pass (npx vitest run --coverage) — failed before this change
human no recorded human contact with these lines
インストール
単一の静的バイナリ。
Goツールチェーンもランタイムも、コンパイルするものは何もありません。
curl -fsSL https://raw.githubusercontent.com/Dillonsmart/docket/main/install.sh | sh
または、macOSとLinux(arm64およびx86-64)、Windows(両方)向けのリリースページからアーカイブを取得し、展開して、PATHにdocketを追加してください。
すべてのリリースでSHA256SUMSが公開されており、インストーラーがそれらをチェックします。
ソースからのビルドは、希望する人なら誰でも利用可能です:
go install github.com/Dillonsmart/docket/cmd/docket@latest
その後、リポジトリ内で:
docket init
何もインストルメントする前に確認してください
scripts/demo.sh
これは一時ディレクトリに使い捨てのリポジトリを構築し、記録されたセッションを含んでいます。エージェントがセッション固定バグを修正し、一度間違え、テストの失敗を見て、正しく修正します。そしてコミットのdocketを出力します。
あなたのリポジトリは変更されず、ディレクトリは終了時に削除されます。
アップグレード
インストーラーを再実行してください。
バイナリを最新リリースに上書きします:
curl -fsSL https://raw.githubusercontent.com/Dillonsmart/docket/main/install.sh | sh
docket version は現在お使いのバージョンを示します。リリースページは現在のバージョンを示します。
ピン留めするか、戻るには、タグ名を指定してください:
curl -fsSL https://raw.githubusercontent.com/Dillonsmart/docket/main/install.sh | DOCKET_VERSION=v0.0.2 sh
(変数はパイプのsh側に設定されます。curlの前に設定するとダウンロード用になり、スクリプト用ではありません。)
ソースからは、go install github.com/Dillonsmart/docket/cmd/docket@latest です。
CIでは、アクションのデフォルトバージョン:latestは実行ごとに最新リリースを取得します。そうしたい場合はタグにピン留めしてください。
移行する必要のあるものはありません。
既に保存されているレコードは読み取り可能のままです。各レコードは、書き込まれたスキーマバージョンを保持しており、ローカル状態は署名キー以外にはありません。アップグレードはそれを変更しません。
バイナリが新しい場所に配置された場合にのみ、docket initを再実行する必要があります。
フックは絶対パスで呼び出され、PATHにあるdocketにフォールバックするため、インプレースアップグレードには何も必要ありません。別のディレクトリにインストールして古いコピーを削除する場合、記録されたパスが古くなります。
これは、prepare-commit-msgフック(トレーラーを書き込む。監査されたエージェントは自身の監査レコードを書き込まない)、post-commitフック(レコードを保存する)、refs/docket/* refspec、ローカル署名キー、およびdocketがシェル経由で行われた編集を観察できるようにするClaude Codeフックをインストールします。
それ以降、すべてのコミットには、Signed-off-byやReviewed-byが存在するトレーラーブロックに、追加の1行が含まれます:
Add the session helper
The API needs a stable id per session, and the obvious place is here rather than in the middleware.
Reviewed-by: Someone Else <someone@example.com>
Docket: sha256:db77fdb4b0c1fc6cc7644d3fa2204267e25799d74a6f8f665aff3d32b12c39af
これが履歴におけるフットプリント全体です。
git log --oneline は変更されず、件名はそのままです。ダイジェストはURLではなくrefs/docket/records上の署名付きレコードの名前を付けます。したがって、永続的な履歴の何も、サービスがまだ存在することに依存しません。
修正はレコードを再構築し、トレーラーを置き換えるため、コミットは以前のコンテンツを指しません。
マージにはトレーラーがなく、帰属させるものがないコミットにもトレーラーはありません。
リベースとチェリーピックは厄介なケースです。gitはいずれの場合もprepare-commit-msgを実行しないため、トレーラーはそれが構築されなかった差分に移動します。docket verify は、トレーラーを信頼するのではなく、それを明確に報告します。
停止するには:.git/hooks内の2つのフックを削除してください。
既存のトレーラーは不活性なテキストとして履歴に残ります。
使用方法
docket show HEAD # コミットのレコード、リスク順
docket explain src/auth.js:51 # なぜこの行が存在するのか? (git blame経由)
docket review --format md # プルリクエストコメント
docket verify HEAD # ダイジェスト、署名、コミットバインディング
docket push # レコードをリモートに送信
docket doctor # docketが見えるものと見えないもの
docket gate --commits 20 # 実際の履歴に対する帰属を測定
プルリクエストの場合、GitHubアクションはコミットが持ってきたレコードを読み取り、1つのコメントを投稿します。証拠がないhunkを上に並べ替え、よくカバーされたボイラープレートを下に折りたたみます。
ランナーに何もインストールする必要はありません。同じバイナリをダウンロードします。
誰かの理由を読み返す
このコードがなぜこのように見えるのかを説明するフィールドは、task、intent、attemptです:
task — この編集が下りてくるリクエスト、つまり人間が実際に求めたものです。
intent — エージェントが編集を行った直前の文で、何をしていると述べたかです。ここに理由が、エージェント自身の言葉で記録されます。
attempt — 同じ領域に書き込まれてから再び削除されたコード、そしてその間に失敗したチェックです。放棄されたアプローチは、数時間のうちに失われる部分です。
$ docket explain database/migrations/0001_01_01_000000_create_players_table.php:54
database/migrations/…:54 was last written by be66f35c5977
origin claude-code/main via Edit
task Look at the engine plan for this project, challenge any assumptions then start implementing
intent Postgres `jsonb` normalises key order, so the replayed response wasn't byte-identical to the original. For a stored response we only ever return verbatim, `json` is the right column type.
attempt Now the schema. Replacing the default `users` table with `players` as the authenticatable model. [superseded]
docket explain はgit blameを通じてコミットを見つけるため、どのコミットを見るべきかを知る必要なく、目の前のコードから始めることができます。
docket show <sha> --all --json は、データとして読みたい場合に完全なレコードを提供します。
Docketは会話全体ではなく、決定を再構築するのに十分な、短く編集された抜粋を保存します。なぜなら、完全なトランスクリプトは秘密を運び、無制限に成長するからです。
仕組み
帰属。Docketはエージェントのトランスクリプトを順序付けられたイベントストリームに解析し、ファイルごとのすべての記録された編集を再生し、後続の編集を通じてプロビジョニングベクトル(1行あたりのオリジン)を転送します。
コミット時に、コミットされたファイルをその再生と整列させ、各ハングを解決します。
行は、そのテキストが整列された位置で、クレジットされている編集の記録された出力で見つかった場合にのみ帰属されます。
タイムスタンプはイベントを順序付けるだけで、帰属を正当化することはありません。
編集の記録された事前画像が再生と一致しない場合(シェルコンマのため)