GitHub Blog に掲載された記事で、著者はアプリケーションをすべて Markdown で書き、
GitHub Copilot にそれを Go へコンパイルさせていると報告している。著者が出発点として
挙げる課題は、コーディングエージェントとの通常の反復的なワークフローにおけるコンテキストの喪失である。
「X を行うアプリ A を書いて」と頼まれ、その後に機能追加やバグ修正の依頼を次々と与えられたエージェントは、
やがてアプリの目的や過去の決定を見失い、すでに説明したことを尋ねたり、以前の選択と矛盾する変更を
提案したりするようになる。Copilot の copilot-instructions.md のようなカスタム指示ファイルはこの
コンテキストを保持するために存在するが、著者は、エージェントに何かを頼んだ後にそのファイルを更新するのを
忘れてしまうこと、そして同じ情報をチャットのプロンプトと指示ファイルの両方に書くのは冗長に感じられることに
気づいた。
これに対する著者の答えは、Markdown ファイルをコードに付随する指示として扱うのをやめ、それをコードそのものと
して扱うことだった。自身の趣味のプロジェクト(GitHub のディスカッション、イシュー、プルリクエストを要約する
実験的な MCP サーバー)で、著者はアプリケーションを main.md に書き、プロンプトファイルを呼び出して
main.go を生成しており、Go のコードを直接編集したり見たりすることはめったにないと報告している。記事は
これを推奨ではなく実験的なワークフローとして提示しており、その根拠は 1 つのプロジェクトでの数か月にわたる
著者自身の経験である。
要点
- アプリケーションは 4 つのファイルを軸に構成されている。ユーザー向けドキュメントである
README.md、 仕様を保持するmain.md、仕様からコードを生成するようエージェントに指示するcompile.prompt.md、 そして生成されたmain.goである。 README.mdはmain.mdに複製されるのではなく参照によって取り込まれるため、ドキュメントと実装は 同期した状態に保たれる。引数のエイリアスを追加するには README だけを編集すればよい。- 著者は
main.mdを書くことを、Markdown と平易な英語によるプログラミングだと特徴づけている。そこには 変数、ループ、論理条件が記述され、if、foreach、continueといったおなじみのキーワードが使え、 構造的なスタイルと宣言的なスタイルが混在し、Markdown のリンクがインポートとして使われる。データベース スキーマも同じファイルに、主キーとインデックスを持つテーブルとして書かれている。 - コンパイル用のプロンプトは意図的に最小限にとどめられている。仕様に従うようにアプリを更新し、エディタの タスクでビルドし、各ライブラリのホームページを取得してドキュメントとする、という内容である。本当の情報は 仕様に書くべきであり、単純なプロンプトであれば他のエージェントにも持ち運べる、というのがその理由である。
- 開発ループは、仕様を編集し、エージェントにそれをコンパイルさせ、実行してテストし、うまくいかない点が あれば仕様を更新する、というものである。
- 仕様はコードと同じようにリントできる。2 つ目のプロンプトファイルは、明確さと簡潔さのために仕様を最適化し、 英語をプログラミング言語として扱い、1 つの概念に 1 つの用語を使い続けることで同義語を最小限にし、詳細を 保ちながら重複を取り除くよう、エージェントに指示する。
main.mdを書くことは、Go を直接書くよりも難しい場合がある。何が欲しいのかを正確に記述する必要があるから であり、著者はそれをソフトウェア開発でおそらく最も難しい部分だと述べている。著者は仕様そのものを書くのにも Copilot の助けを借りており、Copilot がページネーションのスタイルやパラメータ名を提案してくれたと報告している。- 生成されるファイルが大きくなるにつれてコンパイルは遅くなる。著者が挙げる次のステップは、各セクションを 独立したモジュールに分割するよう仕様でエージェントに指示することである。
- 執筆時点で著者はまだテストを追加していなかったが、仕様は意図された振る舞いを記述するものであり、テストは それを検証するものであるため、仕様駆動のワークフローにおいてもテストは不可欠であり続けると述べている。
文脈
この記事は、仕様が開発者の直接編集する唯一の成果物となり、コードはそこから生成される、というところまで推し 進めた 仕様駆動開発 の実体験の一例である。記事はこの立場に、それを論じることに よってではなく、実践を通じて到達している。著者はこの手法を原理的にはエージェントにも言語にも依存しない ものと位置づけており、VS Code、Copilot、Go はたまたま自分が使っている例にすぎないとしている。記事の 結びでは、まだ試していない実験として、Go のコードを完全に破棄し、アプリケーションを別の言語で再生成して 一発で動くかどうかを確かめることに触れている。GitHub 自身の GitHub Spec Kit は、 著者自身の記述とは別の囲み記事の中で、同じ実践への構造化された道筋として紹介されている。