
(Japanese translation follows / 日本語は以下に続きます)
These days, the only thing I'm reliably writing by hand is markdown.
That on its own isn't interesting. I've always spent a lot of time speccing before I build, and I like writing spec. The interesting thing is the change in the balance of spec/coding. Even last year, it was still skewed heavily toward code (even though I was mostly managing at that time). Now, even though I'm technically outputting more lines of code, spec is pretty much the only thing I'm hands-on creating. VS Code has become a tool I use to read code that was written elsewhere and to edit markdown files.
On our AI-driven projects I keep a folder of nothing but markdown docs, and about 90% of those files are hand-written or directly maintained by a human. It's the same relationship I used to have with the code itself — that folder is the thing I tend to. It holds everything that is meaningful to the project: feature definitions, entity definitions, coding guidelines, principles, and the "unspoken rules" that teams are usually expected to pick up by osmosis.
This level of detail is how it has to be now. We use AI to code, but AI is not a person, and it forgets. I'll ask an agent something like "why did you make a struct out there for no reason? it needs a reason to exist," and it'll say "oh yeah, good call boss, let me file that away and fix it," and then a few days later it does the exact same thing. Its memory is nebulous, and you can't fix nebulous memory by saying the right thing once. Context is localized, so even if I tell it not to do something, it's happy to repeat the same mistake on another engineer's harness. So instead of correcting the same mistake forever, I spend a lot of time turning those learning moments into concrete, plainly-worded rules and committing them to the docs.
Here's an example of one of the rules in our docs:
## Helpers Have Owners
Lean heavily against standalone, package-scoped helper functions. A free-floating helper has no owner, and an ownerless helper has an invisible blast radius: you cannot see, from the helper, who depends on it or what breaks if you change it. Before writing one, find its owner.
We have pages and pages of these notes, and arguably keeping them true and concise is more important than the code itself: code is cheap now, but only as long as we don't have to rewrite it a hundred times before the robot gets it right. And to come back to that earlier post about yelling at your harness — if the robot is getting it wrong, it's not necessarily because it's stupid, it's because you didn't explain yourself well enough the first time.
This kind of AI-shaping is now a big chunk of my normal work. Rather than sitting down to write the code, I read the code and use it as raw material for formalizing how the project should be built.
In a way, that's exactly the thing a "learned engineer" lets you skip. The ideal used to be that you hire people who already carry this knowledge and apply it without being told. But even so, I've found that everyone carries their own version of how code should work anyway — and we'd already written down our coding guidelines long before any of this, so it's not as if the rules lived inherently in anyone's head. The real difference now is that we have to actively formalize what we think and take ownership of it.
To be fair, even this feels like a transitional phase. I'm still telling the agent what to write, what to avoid, what to refactor. Maybe it's only a matter of time before we decide that writing spec in prose is too loose, invent some formalized spec language to tighten it up, and swing all the way back around into writing code again — code the AI compiles into spec, which it compiles into code. Turtles all the way down.
Which is why I keep coming back to a point Linus Torvalds has made: the AI isn't "writing the code" any more than a compiler is. That matches my experience exactly. The work is the same work it always was: deciding what the software is and how it should behave. Only now I do it a layer up. I spec, the spec gets transpiled into code, and the code gets compiled into something we can run. So I've stopped worrying about which layer I'm sitting at. What matters is that the thing it builds is the thing I meant — and getting that right is, and always was, just spec.
最近、私が自分の手で確実に書いているものといえば、Markdown くらいです。
それ自体は、面白くもなんともありません。私は昔から、何かを作る前の仕様づくりに多くの時間を割いてきましたし、仕様を書くこと自体が好きです。面白いのは、仕様とコーディングのバランスが変わったことです。去年の時点では、まだ大きくコード寄りでした(当時の私は、ほぼマネジメント中心だったにもかかわらず、です)。それがいまでは、行数のうえでは以前より多くのコードを生み出しているのに、自分が手を動かして作っているものといえば、ほとんど仕様だけになっています。VS Code は、よそで書かれたコードを読んだり、Markdown ファイルを編集したりするためのツールになりました。
AI を活用するプロジェクトでは、私は Markdown のドキュメントだけを集めたフォルダを用意しています。そして、その中の約90%は、人間が手で書いたか、人間が直接メンテナンスしているファイルです。これは、かつて私がコードそのものに対して持っていた関係とまったく同じで、いまはそのフォルダこそが、私が手をかけて世話をする対象になっています。そこには、プロジェクトにとって意味のあるものがすべて入っています。機能定義、エンティティ定義、コーディングガイドライン、原則、そしてチームが普通は「自然と身につけるもの」とされがちな“言葉にされないルール”まで。
いまは、ここまで細かく書いておく必要があるのです。私たちはコードを書くために AI を使いますが、AI は人間ではなく、忘れます。たとえば私がエージェントに「なんで意味もなくそんなところで struct を作ったの? struct には存在する理由が必要でしょ」と言うと、エージェントは「ああ、たしかに。さすがですね、ボス。メモして直しておきます」と返してきます。それなのに、数日後にはまったく同じことをやるのです。AI の記憶はあいまいで、一度正しいことを言ったくらいでは直りません。コンテキストはその場限りなので、私がある場所で「やるな」と伝えても、別のエンジニアのハーネス(AI を取り巻くツールやフィードバックの仕組み)では平気で同じ失敗を繰り返します。だから私は、同じ間違いを永遠に直し続ける代わりに、そうした“学びの瞬間”を、具体的で平易な言葉のルールに落とし込み、ドキュメントに残すことに多くの時間を使っています。
私たちのドキュメントにあるルールの一例を挙げてみます。
## Helpers Have Owners
Lean heavily against standalone, package-scoped helper functions. A free-floating helper has no owner, and an ownerless helper has an invisible blast radius: you cannot see, from the helper, who depends on it or what breaks if you change it. Before writing one, find its owner.
こうしたメモは何ページにもわたって積み上がっていますが、それを正確かつ簡潔に保つことは、コードそのものよりも重要かもしれません。いまやコードは安く手に入ります。ただし、それはロボットが正しく仕上げるまでに百回も書き直さずに済む場合に限った話です。そして、以前の「ハーネスに怒鳴るのはやめよう」という記事の話に戻りますが、ロボットが間違えるのは、必ずしもロボットが馬鹿だからではなく、こちらが最初に十分わかりやすく説明できていなかったからなのです。
この種の“AI を形づくる”作業が、いまや私の日常業務のかなりの部分を占めています。腰を据えてコードを書く代わりに、私はコードを読み、それを素材にして、プロジェクトをどう作るべきかを形式化していくのです。
ある意味でこれは、「経験を積んだエンジニア」を雇えば省けるはずの部分でもあります。かつての理想は、こうした知識をすでに身につけていて、言われなくても実践してくれる人を雇うことでした。とはいえ実際には、誰もが「コードはこうあるべきだ」という自分なりの流儀を抱えているものです。しかも私たちは、この流れが始まるずっと前からコーディングガイドラインを文書化していました。つまり、ルールが誰かの頭の中に最初から備わっていたわけではないのです。いま本当に変わったのは、自分たちの考えを能動的に形式化し、その内容に責任を持たなければならなくなった、という点です。
正直に言えば、このやり方すら過渡期のものに感じます。私はいまも、エージェントに何を書くか、何を避けるか、何をリファクタリングするかを指示しています。「文章で仕様を書くのは曖昧すぎる」と私たちがいつか気づき、それを厳密にするための形式化された仕様言語を編み出し、ぐるりと一周してまたコードを書く側に戻る——AI がそのコードを仕様へとコンパイルし、その仕様をさらにコードへとコンパイルする——そんな日が来るのも、時間の問題なのかもしれません。どこまでいっても切りがない、亀の上にまた亀が乗っているようなものです。
だからこそ私は、リーナス・トーバルズが述べているある指摘に何度も立ち返ります。コンパイラを指して「コードを書いている」とは言わないのと同じで、AI もコードを「書いている」わけではない、という指摘です。これは私の実感そのものです。仕事の本質は、昔からずっと変わっていません。ソフトウェアが何であり、どう振る舞うべきかを決めること——それが仕事です。ただ、いまはそれを一段上のレイヤーでやっているだけです。私が仕様を書き、その仕様がコードへとトランスパイルされ、そのコードが動かせる何かへとコンパイルされる。だから私は、自分がいまどのレイヤーに座っているのかを気にするのをやめました。大事なのは、出来上がったものが自分の意図したとおりのものであること。そして、それを正しく仕留めることは、いまも昔も、結局のところ仕様を書くということに尽きるのです。


