Simon Willison の記事を X で流れてきたのを見て、思わずスクロールを止めた。
sqlite-utils 4.0 のリリース前レビューを Claude Fable に任せたら、37 プロンプト・34 コミット・+1,321 -190 の差分で仕上げたというやつだ。
コストが $149.25 というのも生々しくていい。
delete_where() がトランザクションを壊してたやつ、えぐすぎる
Fable が「リリースブロッカー」として上げた不具合の中に、`Table.delete_where()` のやつがある。
`Table.delete()` は `atomic()` でちゃんと囲まれてるのに、`delete_where()` は素の `self.db.execute()` で走るせいで `conn.in_transaction=True` のまま放置される。
その後に呼んだ `atomic()` がすべてセーブポイント branch に落ちてコミットされない、というコンボだ。
# Simon のブログに載ってた再現コード (意訳)
python - <<'EOF'
import sqlite_utils
db = sqlite_utils.Database("dw.db")
db["t"].insert_all([{"id": i} for i in range(3)], pk="id")
db["t"].delete_where("id = ?", [0]) # in_transaction が True のまま残る
db["t"].insert({"id": 50})
db["u"].insert({"a": 1})
db.close()
# 再オープンすると delete も insert も全部消えてる
EOFこれ自分でも普通に踏みそうで怖い。
個人開発でちょっとした CLI ツールに sqlite-utils を使ってることがあって、`delete_where()` を雑に呼んでるところが何箇所かある。
とりあえず動かしてみた段階で気づかなかったら、データが消えてたことにも気づかずにいた可能性がある。
Python 3.12 の autocommit オプションを完全に見落としてた
もう一個刺さったのが、Python 3.12 で追加された `sqlite3.connect(..., autocommit=True)` の話だ。
Simon 自身も「正直考えてなかった」と書いていて、Fable が書いたドキュメントのドラフトを読んで初めて気づいたらしい。
`autocommit=True` の接続だとテストスイートがほぼ全滅する挙動になるとのことで、そこを Fable と一緒に直した、と。
自分のチームでも Python のバージョンを 3.12 に上げたのが半年前くらいで、その後に書いた DB 周りのコードが `autocommit` の挙動を意識してるかどうか、正直自信がない。
`sqlite3` を直接触るケースは少ないけど、ORM 経由でも内部の挙動が変わってたりするので一回確認しておきたい。
37 プロンプトで Major release を仕上げるという使い方
この記事で一番おもしろいと思ったのは、Simon が Claude Code を iPhone から操作しながら Half Moon Bay の独立記念日パレードを見に行ってた、というくだりだ。
エージェントが重いタスクを回してる間、10〜15 分単位でひとが離れられるというのは確かにそうで、自分も長い test suite を回してる間にコーヒー買いに行くのと同じ感覚に近い。
今回 Fable が変更したファイルは 30 個。
設計の話で言うと、今回のメインは transaction モデルの整備で、「`insert()` や `delete_where()` などの書き込みメソッドはすべて自前でトランザクションを張ってコミットして返る」という設計に統一した。
- 書き込みメソッドはメソッド呼び出しの時点でコミットされる
- 複数操作をまとめたいときだけ `db.atomic()` を使う
- `db.begin()` で自分でトランザクションを開いた場合は自分でコミットする
この設計、ORM ライブラリを自分で書くときに迷うやつそのもので、「デフォルトで auto-commit するか、明示的 commit を要求するか」という古典的な問題だ。
sqlite-utils の答えは「メソッド単位で自動コミット、グルーピングは atomic()」というシンプルな二択に落ち着いた。
個人的にはこれが一番わかりやすい設計だと思う。
最後に Simon が GPT-5.5 でも最終レビューをかけてたのも地味にハマった。
「Fable でここまでやって、別モデルにダブルチェックさせる」という使い方は自分もやってみたい。
モデルごとに見落とすポイントが違うだろうし、コストの話で言えば $149 でメジャーリリース一本分の作業をこなせるなら、ソロ開発者的には悪くない数字だ。
自分の手元にある個人開発の CLI、sqlite-utils を使ってる箇所を全部 grep して、`delete_where()` を呼んでる場所を今日中に確認する。