大数跨境
0
0

技术速递|规范驱动开发:使用 Markdown 作为 AI 构建中的编程语言

技术速递|规范驱动开发:使用 Markdown 作为 AI 构建中的编程语言 微软开发者MSDN
2025-11-12
0

M

点击蓝字 / 微软开发者MSDN

关注我们


作者:Tomas Vesely

排版:Alan Wang


我最新的应用是完全用 Markdown 编写的,然后让 GitHub Copilot 将其编译为 Go。这样做的结果是:规范更清晰、迭代更快速,而且再也不会丢失上下文。✨


使用 GitHub Copilot 等 AI 编码 agent 的常见工作流程其实很简单:

“编写一个能执行 X 的应用 A。”

你从这个种子开始,然后不断迭代:

“添加功能 Y”、“修复 Bug Z”。

这种方式是可行的——至少在 Agent 没有忘记你应用的目标或过去的设计决策之前。


如果你刚开始接触 AI 编码 Agent,这种变化可能是很微妙的。突然之间, Agent 会要求你重复已经解释过的内容,或者提出忽略你先前指令的修改建议。

有时,它会忘记某个功能存在的原因,甚至提出与早期决策相矛盾的解决方案。


一些 AI 编码 Agent 尝试通过支持自定义说明文件来解决这个问题。 例如,GitHub Copilot 支持 copilot-instructions.md 文件。你可以把应用的目标和设计决策写在这个 Markdown 文件中,GitHub Copilot 每次生成代码时都会读取它。


但当我在“编码冲刺”中时,我常常会忘记在让 Copilot 执行任务后去更新 copilot-instructions.md。把同样的信息既写在聊天提示里,又写进说明文件里,显得有些多余。


支持

https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions?tool=vscode/?wt.mc_id=3reg_webpage_reactor

试试 Spec Kit:

让规范驱动开发真正落地


Spec Kit 提供了一套结构化流程,让你可以在 GitHub Copilot、Claude Code、Gemini CLI 等 AI 编码 Agent 中实践规范驱动开发。此外,它是开源的(我们也在持续更新中)。


👉 在 GitHub 上开始使用 Spec Kit


这让我开始思考:如果我把整个应用都“写”在 Markdown 说明文件中,会怎样?


在我最新的个人项目——GitHub Brain MCP Server 中,我尝试了这种方法:在 Markdown 中编写应用代码,然后让 GitHub Copilot 将其编译为 Go 代码。结果,我几乎不再直接编辑或查看 Go 源码。


这种流程理论上适用于任何 AI 编码 Agent 与编程语言,不过下面我会以 VS Code、GitHub Copilot 和 Go 作为示例,并以 GitHub Brain MCP Server 作为贯穿全文的案例。


那就开始吧。


在 GitHub 上开始使用 Spec Kit

https://github.blog/ai-and-ml/generative-ai/spec-driven-development-with-ai-get-started-with-a-new-open-source-toolkit/?wt.mc_id=3reg_webpage_reactor

GitHub Brain MCP Server

https://github.com/wham/github-brain/?wt.mc_id=3reg_webpage_reactor

环境准备:

我用到的文件结构


共有四个关键文件:

.├── .github/│   └── prompts/│       └── compile.prompt.md├── main.go├── main.md└── README.md

整体思路是:我在 README.md 或 main.md 中编辑内容来开发应用,再调用 compile.prompt.md 让 AI 编码 Agent 生成 main.go,然后像普通 Go 应用一样构建并运行。接下来,我会逐个拆解这些文件与对应流程。

README.md:面向用户的文档

示例应用 GitHub Brain MCP Server 是一个命令行工具。它的 README.md 提供了清晰的安装与使用说明。如果你写的是库文件,这里应包含 API 文档。以下是该示例 README.md 的简化片段:

# GitHub Brain MCP Server
**GitHub Brain** is an experimental MCP server for summarizing GitHub discussions, issues, and pull requests.
## Usage
```shgo run main.go <command> [<args>]```
**Workflow:**
1. Populate the local database with the `pull` command.2. Start the MCP server with the `mcp` command.
### `pull`
Populate the local database with GitHub data.
Example:
```shgo run main.go pull -o my-org```
Arguments:
- `-t`: Your GitHub personal access token. **Required.**- `-o`: The GitHub organization to pull data from. **Required.**- `-db`: Path to the SQLite database directory. Default: `db` folder in the current directory.
### `mcp`
Start the MCP server using the local database.
...README.md continues...

这里没有什么特别的内容,只是常规的文档。但当这个文件被包含进 main.md 时,事情就变得有趣了。

GitHub Brain MCP Server

https://github.com/wham/github-brain/?wt.mc_id=3reg_webpage_reactor

README.md

https://github.com/wham/github-brain/blob/main/README.md/?wt.mc_id=3reg_webpage_reactor

main.md:AI 编码 Agent 规范

main.md 是该应用程序的实际源代码:一个用 Markdown 编写的指令文件。每当我需要添加功能或修复错误时,我都会编辑这个文件。以下是示例应用程序 main.md 的开头部分:

# GitHub Brain MCP Server
AI coding agent specification. User-facing documentation in [README.md](README.md).
## CLI
Implement CLI from [Usage](README.md#usage) section. Follow exact argument/variable names. Support only `pull` and `mcp` commands.
## pull
- Resolve CLI arguments and environment variables into `Config` struct:  - `Organization`: Organization name (required)  - `GithubToken`: GitHub API token (required)  - `DBDir`: SQLite database path (default: `./db`)- Use `Config` struct consistently, avoid multiple environment variable reads- Pull items: Repositories, Discussions, Issues, Pull Requests, Teams- Use `log/slog` custom logger for last 5 log messages with timestamps in console output
...main.md continues...

请注意:README.md 被直接嵌入在规范中。这样可以保证文档与实现保持一致。如果我要为 -o 参数增加一个别名,只需修改 README.md 即可,无需额外步骤。


以下是示例应用程序 main.md 的另一段代码片段:

### Discussions
- Query discussions for each repository with `has_discussions_enabled: true`- Record most recent repository discussion `updated_at` timestamp from database before pulling first page
```graphql{  repository(owner: "<organization>", name: "<repository>") {    discussions(first: 100, orderBy: { field: UPDATED_AT, direction: DESC }) {      nodes {        url        title        body        createdAt        updatedAt        author {          login        }      }    }  }}```
- If repository doesn't exist, remove the repository, and all associated items from the database and continue- Query discussions ordered by most recent `updatedAt`- Stop pulling when hitting discussions with `updatedAt` older than recorded timestamp- Save or update by primary key `url`- Preserve the discussion markdown body
...main.md continues...

这其实就是在用 Markdown 和自然语言进行编程:存变量、写循环、设条件。拥有类似 ifforeachcontinue 等逻辑结构。它融合了结构化与声明式风格,用 Markdown 链接 []() 来充当导入。


数据库模式同样写在 Markdown 中:

## Database
SQLite database in `{Config.DbDir}/{Config.Organization}.db` (create folder if needed). Avoid transactions. Save each GraphQL item immediately.
### Tables
#### table:repositories
- Primary key: `name`- Index: `updated_at`
- `name`: Repository name (e.g., `repo`), without organization prefix- `has_discussions_enabled`: Boolean indicating if the repository has discussions feature enabled- `has_issues_enabled`: Boolean indicating if the repository has issues feature enabled- `updated_at`: Last update timestamp
...main.md continues...

main.md

https://github.com/wham/github-brain/blob/main/main.md/?wt.mc_id=3reg_webpage_reactor

README.md

http://readme.md/?wt.mc_id=3reg_webpage_reactor

compile.prompt.md:AI 编译提示文件

compile.prompt.md 使用 GitHub Copilot 的提示文件格式,它指示 Agent 将 main.md 编译为 main.go。以下是示例应用程序中的 compile.prompt.md 文件内容:

---mode: agent---
- Update the app to follow [the specification](../../main.md)- Build the code with the VS Code tasks. Avoid asking me to run `go build` or `go test` commands manually.- Fetch the GitHub home page for each used library to get a documentation and examples.

我让这个提示尽量简洁,因为真正的信息都在 main.md 中。虽然它用的是 GitHub Copilot 的格式,但简单设计让它能轻松移植到其他 Agent 中。


提示文件

https://docs.github.com/en/copilot/tutorials/customization-library/prompt-files/your-first-prompt-file/?wt.mc_id=3reg_webpage_reactor

compile.prompt.md

https://github.com/wham/github-brain/blob/main/.github/prompts/compile.prompt.md/?wt.mc_id=3reg_webpage_reactor

main.md

http://main.md/?wt.mc_id=3reg_webpage_reactor

工作流整合



整个开发循环很直接:

  • 编辑 main.md 或 README.md 中的规范

  • 让 AI 编码 Agent 将其编译为 Go 代码

  • 运行并测试

  • 若结果不符合预期,再更新规范


在 VS Code 的 Copilot 中,只需使用 / 命令调用对应提示。


对于较小的规格说明,GitHub Copilot 通常会自动捕捉更改。随着规格说明变大,我会通过在提示末尾添加“focus on <the-change>”来引导它朝正确方向调整。

编码

在 main.md 中编码有时比直接编写 Go 代码更难 。你必须清楚地描述你想要的内容,而这可能是软件开发中最难的部分 😅。幸运的是,你可以像日常使用 GitHub Copilot 编写 Go 代码一样,让它来帮你完成这部分工作。


这里我们让它为 main.md 中的所有 MCP 工具添加分页。Copilot 不仅帮我们节省了重复操作的时间,还会推荐合适的分页风格和参数名称。

代码整理

main.md 也会像任何代码一样变得凌乱。你可以请 Copilot 来清理它。示例应用的 lint.prompt.md 内容如下:

---mode: agent---
- Optimize [the app specification](../../main.md) for clarity and conciseness- Treat the english language as a programming language- Minimize the number of synonyms - i.e. pull/get/fetch. Stick to one term.- Remove duplicate content- Preserve all important details- Do not modify the Go code withthis. Only optimize the Markdown file.- Do not modify this prompt itself.

同样地,我通过 / 命令调用它,AI 编码 Agent 会优化 main.md,若结果满意,再使用 compile.prompt.md 将其编译为 Go 代码。


lint.prompt.md

https://github.com/wham/github-brain/blob/main/.github/prompts/lint.prompt.md/?wt.mc_id=3reg_webpage_reactor

尾声:一些心得


经过几个月的实践,我的观察如下:

  • 它确实有效!而且随着 Copilot 的 Agent 功能更新越来越好。

  • 编译速度会随着 main.go 的增长而变慢我接下来想做的事情是修改规范,将编译后的代码拆分成多个模块——通过添加“Break each ## section into its own code module.”。

  • 测试?我还没加上测试。但即使是规范驱动开发,测试仍然必不可少。 规范描述“期望行为”,测试验证“实际行为”。


我还想尝试的另一件事: 丢弃所有 Go 代码,直接让 AI 用另一种语言重新生成整个应用。新代码能立即正常运行吗?


AI 编码领域的快速进步令人鼓舞,希望我的这些实验性流程,能给你带来一些可实践的灵感。


微信公众号|微软开发者MSDN

新浪微博|微软中国MSDN

·END·

【声明】内容源于网络
0
0
微软开发者MSDN
微软云Azure技术生态官方公众平台
内容 2706
粉丝 0
微软开发者MSDN 微软云Azure技术生态官方公众平台
总阅读2.3k
粉丝0
内容2.7k